MacOS鑰匙串授權特定應用程序獲得密碼

繼續討論MacOS鑰匙串授權應用程序獲得密碼的那些安全隱患

MacOS鑰匙串授權應用程序這個過程的安全隱患,在前一篇博文中討論過了,參見MacOS鑰匙串授權應用程序獲得密碼(命令行/Python/Objective-C/Swift)

從文章可以看到,授權過程的安全隱患比較隱蔽,在使用階段的安全隱患更加隱蔽。

授權和使用的安全問題容易混淆,因爲幾乎所有的互聯網網站都是按照登錄用戶隔離,從用戶的操作過程來看,登錄之後個人的數據限於自己訪問,看不到其他用戶的個人數據。此時,安全的關鍵環節就是授權(authorization),準確的說是鑑權(authentication)。

目前的操作系統也是類似的情況,當用戶登錄後,只能看到自己的個人文件夾中的文件,看不到其他用戶的個人文件夾中的文件。即使有其他用戶同時登錄同一臺電腦,也是都只能看到自己的個人文件夾中的文件,看不到其他用戶的個人文件夾中的文件。以各種UNIX爲代表的早期的多用戶服務器都是如此隔離,只是早期的個人電腦操作系統沒有這麼區分。

因此,用戶往往會忽視登錄後的安全隱患,不過個人電腦除了數據安全之外,還有一個隱患就是惡意軟件。登錄後,相當於用戶對所有自己啓動的進程授權訪問所有自己個人文件夾中的文件,即使像MacOS可以單獨控制應用程序訪問一些文件夾,但是控制的顆粒度比較粗,例如整個“文檔”文件夾。像勒索軟件,就可能會欺騙用戶授權,然後操作這些文件。對於這種情況,MacOS對程序進行校驗是一種防護措施,不過正如MacOS鑰匙串授權應用程序獲得密碼(命令行/Python/Objective-C/Swift)中討論的,對於像Python這種運行代碼的程序而言,在一個場景中授權後,其他場景就可以任意調用了。

即便用戶登錄授權了,將個人文件夾中的數據暴露給進程,MacOS鑰匙串中的密碼仍舊需要授權訪問,在MacOS鑰匙串授權應用程序獲得密碼(命令行/Python/Objective-C/Swift)中討論了鑰匙串授權特定應用程序獲得密碼的一些安全隱患,下面以具體例子說明。

命令歷史記錄中的安全隱患

假設在鑰匙串中保存了一臺服務器的密碼,名稱爲SurfacePro3VirtualBox,賬戶爲IEUser。那麼可以使用如下命令訪問密碼。

security find-generic-password -l "SurfacePro3VirtualBox" -a "IEUser" -gw

當沒有授權security獲得密碼時,將出現授權提示框。

5c21e02db30c74fecc40f79b9c0dbdcf.png

運行後在命令歷史記錄中可以看到

history | tail

結果如下

10052  security find-generic-password -l "SurfacePro3VirtualBox" -a "IEUser" -gw

當用戶授權了security獲得密碼後,查看密碼信息可以看到。

056932656abda35e947adc871a732427.png

如果有惡意軟件從命令歷史記錄中識別這樣的命令,而且用戶也授權了security獲得密碼,那麼惡意軟件就可以運行相同的命令獲取密碼。

使用專門的程序訪問特定的密碼

參照MacOS鑰匙串授權應用程序獲得密碼(命令行/Python/Objective-C/Swift),專門編譯程序訪問密碼可以一定程序避免這種識別。

編輯文件FindGenericPasswordSwiftSurfacePro3VirtualBox.swift

代碼爲

//
//  FindGenericPasswordSwiftSurfacePro3VirtualBox.swift
//  FindGenericPasswordSwiftSurfacePro3VirtualBox
//
//  Created by 胡爭輝 on 2020/5/27.
//  Copyright © 2020 胡爭輝. All rights reserved.
//

import Foundation

var service: String = "SurfacePro3VirtualBox"
var account: String = "IEUser"
var pwLength: UInt32 = 0
var pwData: UnsafeMutableRawPointer?
var item: SecKeychainItem?

var status: OSStatus = SecKeychainFindGenericPassword(
    nil,
    UInt32(service.lengthOfBytes(using: String.Encoding.utf8)),
    service.cString(using: String.Encoding.utf8),
    UInt32(account.lengthOfBytes(using: String.Encoding.utf8)),
    account.cString(using: String.Encoding.utf8),
    &pwLength,
    &pwData,
    &item)
if status == errSecSuccess {
    if let myData = pwData {
        let password: String? = String(bytesNoCopy: myData, length: Int(pwLength), encoding: String.Encoding.utf8, freeWhenDone: true)
        if let myPassword = password {
            print(myPassword)
        }
    }
}

簡單調用API,把獲取密碼的參數-l "SurfacePro3VirtualBox" -a "IEUser"編譯在代碼中。

var service: String = "SurfacePro3VirtualBox"
var account: String = "IEUser"

因爲只有一個文件,不需要啓動Xcode編譯,直接使用命令行編譯即可。

swiftc -emit-executable ./FindGenericPasswordSwiftSurfacePro3VirtualBox.swift

運行編譯後的程序

./FindGenericPasswordSwiftSurfacePro3VirtualBox

將出現授權提示框

6e98d55fa34edb3dda8fe144b339d628.png

可以看到在授權提示框中顯示的是編譯後的應用程序名稱,不再是security。對FindGenericPasswordSwiftSurfacePro3VirtualBox授權後,查看密碼信息可以看到FindGenericPasswordSwiftSurfacePro3VirtualBox程序名稱。

6c643445bd58578dd3463c27d62a835d.png

此時如果使用security請求密碼,將再次顯示授權提示框,因爲securityFindGenericPasswordSwiftSurfacePro3VirtualBox是不同的程序。

這個程序可以直接嵌入在使用密碼的命令行中。

xfreerdp /u:'IEUser' /p:"$(FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

運行後在命令歷史記錄中可以看到

history | tail
10088  xfreerdp /u:'IEUser' /p:"$(FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

沒有明顯的security字樣,不過惡意軟件仍舊可以(當然,幾乎沒有這種可能)調用該程序。

修改運行程序的賬戶

爲了避免被未知程序調用,一個直觀的想法就是修改運行程序的賬戶,一般可以改爲root,先設置可執行文件的所有者。

sudo chown root ./FindGenericPasswordSwiftSurfacePro3VirtualBox

然而還是能運行,查看可執行文件的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox

結果爲

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox"
  Size: 26900        FileType: Regular File
  Mode: (0755/-rwxr-xr-x)         Uid: (    0/    root)  Gid: (   20/   staff)
Device: 1,4   Inode: 104266797    Links: 1
Access: Wed May 27 18:29:20 2020
Modify: Wed May 27 18:29:03 2020
Change: Wed May 27 18:29:48 2020

所有者變了,但是Mode0755/-rwxr-xr-x,其他用戶仍可執行。

接下來去掉可執行權限。

sudo chmod 744 ./FindGenericPasswordSwiftSurfacePro3VirtualBox

運行程序

./FindGenericPasswordSwiftSurfacePro3VirtualBox

顯示沒有權限

zsh: permission denied: ./FindGenericPasswordSwiftSurfacePro3VirtualBox

看上去解決了安全隱患,然而並非如此,這也就是MacOS鑰匙串授權應用程序獲得密碼(命令行/Python/Objective-C/Swift)反覆討論的問題。

下面複製文件,複製文件不需要提權。

cp ./FindGenericPasswordSwiftSurfacePro3VirtualBox ./FindGenericPasswordSwiftSurfacePro3VirtualBox2

查看複製文件後的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox2

可以看到文件的所有者爲當前用戶,而且有可執行權限。

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox2"
  Size: 26900        FileType: Regular File
  Mode: (0744/-rwxr--r--)         Uid: (  501/huzhenghui)  Gid: (   20/   staff)
Device: 1,4   Inode: 104267947    Links: 1
Access: Wed May 27 18:37:48 2020
Modify: Wed May 27 18:37:48 2020
Change: Wed May 27 18:37:49 2020 

運行命令,也不需要提權。

./FindGenericPasswordSwiftSurfacePro3VirtualBox2

如果之前用戶授權原來的程序可以獲得密碼的話,那麼複製後的命令也可以獲得密碼。

因此,不僅要去掉可執行權限,還需要去掉,讀取權限。

sudo chmod 700 ./FindGenericPasswordSwiftSurfacePro3VirtualBox

查看可執行文件的信息。

stat -x ./FindGenericPasswordSwiftSurfacePro3VirtualBox

結果爲

  File: "./FindGenericPasswordSwiftSurfacePro3VirtualBox"
  Size: 26900        FileType: Regular File
  Mode: (0700/-rwx------)         Uid: (    0/    root)  Gid: (   20/   staff)
Device: 1,4   Inode: 104266797    Links: 1
Access: Wed May 27 18:29:20 2020
Modify: Wed May 27 18:29:03 2020
Change: Wed May 27 18:42:08 2020

這樣不僅不能執行,也不能複製,只有提權才能複製。

當然,直接嵌入在使用密碼的命令行中時也需要提權。

xfreerdp /u:'IEUser' /p:"$(sudo FindGenericPasswordSwiftSurfacePro3VirtualBox)" /v:192.168.1.51:13389

如果僅從這個演示案例看,似乎是把鑰匙串的授權操作變成了提權操作。在實際應用環境可以結合實際情況相應改進。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章