繼續討論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
獲得密碼時,將出現授權提示框。
運行後在命令歷史記錄中可以看到
history | tail
結果如下
10052 security find-generic-password -l "SurfacePro3VirtualBox" -a "IEUser" -gw
當用戶授權了security
獲得密碼後,查看密碼信息可以看到。
如果有惡意軟件從命令歷史記錄中識別這樣的命令,而且用戶也授權了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
將出現授權提示框
可以看到在授權提示框中顯示的是編譯後的應用程序名稱,不再是security
。對FindGenericPasswordSwiftSurfacePro3VirtualBox
授權後,查看密碼信息可以看到FindGenericPasswordSwiftSurfacePro3VirtualBox
程序名稱。
此時如果使用security
請求密碼,將再次顯示授權提示框,因爲security
和FindGenericPasswordSwiftSurfacePro3VirtualBox
是不同的程序。
這個程序可以直接嵌入在使用密碼的命令行中。
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
所有者變了,但是Mode
爲0755/-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
如果僅從這個演示案例看,似乎是把鑰匙串的授權操作變成了提權操作。在實際應用環境可以結合實際情況相應改進。