macOS红蓝对抗:如何欺骗具有特权的帮助工具以获取root权限

41yf1sh 系统安全 2019年12月12日发布
Favorite收藏

导语:在本文中,我们将探索一些新颖的方式,可以滥用AppleScript的功能来欺骗用户已经在本地系统上信任的特权进程。

概述

我们在此前的文章曾经提到过,macOS权限提升通常是通过诱导用户,而不是利用0-day或未修复的漏洞来实现的。从红队的角度来看,有一个可能提供帮助的本地工具——AppleScript。AppleScript可以轻松、快速地产生虚假的授权请求,这些请求在用户看起来可能很有说服力。尽管这并非一项新的技术,但在本文中,我们将探索一些新颖的方式,可以滥用AppleScript的功能来欺骗用户已经在本地系统上信任的特权进程。

什么是具有特权的帮助工具?

Mac上的大多数应用程序都不需要权限提升就可以执行工作。如果是从Apple的App Store购买的应用程序,从技术上来看,它们是不允许提升权限的。尽管如此,有时应用程序确实有充分合理的理由,需要获取比当前登录用户更大的特权。我们根据Apple提供的文档,梳理了几种情况:

1、操纵文件的权限,文件的所有权;

2、创建、读取、更新或删除文件;

3、打开用于TCP或UDP连接的特权端口;

4、打开原始Socket;

5、管理进程;

6、读取虚拟内存中的内容;

7、更改系统设置;

8、加载内核扩展。

通常,应用程序如果需要执行上述任意功能,通常只是偶尔需要执行一次。针对这种情况,在需要执行的当时要求用户授权是有必要的。但是,尽管请求用户授权这件事是为了提升安全性,但如果应用程序在某些场景中过于频繁请求用户授权执行这些动作,对用户而言会造成一些不便。用户不喜欢重复出现的对话框警告,也不喜欢重复多次输入密码。

为了解决这一问题,开发人员提出了特权分离的技术。通过创建功能受限的独立“帮助程序”来执行这些任务,仅在安装时要求用户授权安装这些帮助工具。在日常使用过程中,我们可能见过类似于以下的权限请求:

1.jpg

帮助程序工具始终会以提升的权限来运行,但是其功能是有限的。至少从理论上讲,该公欧只能按照父程序的要求执行特定任务。这些特权帮助工具位于本地“Library”(库)文件夹的子文件夹中:

/Library/PrivilegedHelperTools

由于它们仅由来自App Store外部的第三方应用程序安装,因此只有部分用户会在系统中安装某些软件。然而,有一些非常流行、被用户广泛使用的macOS软件已经使用了这类工具。由于操作系统并没有移除独立的特权帮助工具,因此,我们对一些操作系统进行排查,很有可能发现其中一些具有特权的帮助工具正在使用中。以我的操作系统为例,我在系统中发现了一些具有特权的帮助工具,具体是:

BBEdit;

Carbon Copy Cloner;

Pacifist。

父进程和特权帮助工具之间可能会滥用这一信任机制(参考CVE-2019-13013漏洞),但这并不是我们今天想要尝试的方法。相反,我们将利用这样的一个事实,即用户非常熟悉这些特权进程的父应用程序,并且会习惯性地信任来自它们的授权请求。

为什么要使用AppleScript进行欺骗?

有效的社会工程学攻击需要依赖于良好的上下文环境。当然,我们可以随时抛出一个虚假的用户警报,但如果想使其更具迷惑性,我们希望这个警报具有以下的特点:

1、看起来更加真实:包括在警报中使用令人容易信任的文本、具有迷惑性的标题以及具有相关性的图标。

2、出于令人信任的理由触发:如果一个与业务无关,或者从没有要求过特权的应用程序触发了用户警报,将会有很大概率引起用户的怀疑。因此,以具有特权的帮助工具作为目标将非常关键,特别是在我们提供足够真实的详细信息以便用户进行确认,这会增加提示信息的可信性。

3、在适当的时间触发:例如,可以选取当前用户正在使用我们试图仿冒成的应用程序时。

利用AppleScript,上述所有要求都非常容易实现。下面是一个例子,我们可以尝试使用AppleScript来创建。

2.jpg

这个对话框实际上是非常粗糙的。可以看到,这里没有使用输入用户名和密码的两个字段。但即使如此,这个对话框也有一定的迷惑性。其中包含一个有效的标题、一个有效的图标饿一个有效的进程名称,如果用户需要进一步确认,用户会找到相应的具有特权的帮助工具。具体而言,用户在验证的过程中,会发现这个帮助工具确实位于自己的/Library/PrivilegedHelperTools文件夹中。用户必须深入挖掘,才能真正发现我们的欺诈行为。

当然,一些对其怀疑的用户很可能会直接按下“取消”键,而不会进行过多的深入挖掘。但幸运的是,使用AppleScript,我们可以使得用户在按下“取消”按钮后杀死父应用程序,或产生无限循环的代码,从而使这一请求看起来更具说服力,并且阻止目标用户再次点击“取消”键。

但是,无限次重复的情况可能还会引起用户的怀疑,但是杀死父应用程序并发出合适的警报来“解释”这种情况似乎更为合理。当用户重新启动父应用程序,并再次触发我们的授权请求时,用户会更有可能输入密码,并继续其工作。

为了实现良好的效果,我们还可以针对用户首次尝试输入的密码弹出错误提示,并让用户输入两次。由于输入的内容不会在用户屏幕上显示,因此用户也并不清楚自己是否在第一次时无意出现错误。强制用户输入两次时,我们可以判断第一次用户的输入是否正确,并在第二次输入验证通过之前,先验证用户密码。在本文中,我们将不会过多描述这一技术细节,此前我们已经进行了大量的研究工作。

创建欺骗脚本

如果我们不熟悉AppleScript,或者不了解自Yosemite 10.10以来的macOS最新特性,我们可能会惊讶地发现,可以将Objective-C代码嵌入到脚本之中,并直接调用Cocoa和Foundation API。这意味着,我们就拥有了本地API的所有功能,例如:NSFileManager、NSWorkspace、NSString、NSArray等等。在下面的示例中,我使用的是商业版AppleScript编辑器,但它也有免费版本。与内置的Script Editor应用程序相比,AppleScript编辑器更加便于作为开发环境使用。

与其他任何脚本或编程语言一样,我们需要“导入”所需使用的框架,在AppleScript中是使用use关键字来完成的。我们可以将以下内容放在脚本的最开始部分:

3.jpg

这些既能充当快捷方式,也能作为AppleScript与ObjectiveC脚本之间的“桥梁”,同时还可以让我们以便捷的方式访问命名的API,如下所示。

接下来,我们编写一些“处理程序”(函数)来遍历PrivilegedHelper工具目录。在下图中,左边展示了我们将要编写的处理程序,右边是在我的计算机上返回的示例。

4.jpg

如我们所见,这个处理程序只是另一个处理程序enumerateFolderContents:的包装器,这个处理程序是我们从社区论坛借鉴而来的。我们来仔细分析一下它的代码,代码部分有一些复杂:

# adapted from a script by Christopher Stone
on enumerateFolderContents:aFolderPath
       set folderItemList to "" as text
       set nsPath to current application's NSString's stringWithString:aFolderPath
       --- Expand Tilde & Symlinks (if any exist) ---
       set nsPath to nsPath's stringByResolvingSymlinksInPath()
       
       --- Get the NSURL ---
       set folderNSURL to current application's |NSURL|'s fileURLWithPath:nsPath
       
       set theURLs to (NSFileManager's defaultManager()'s enumeratorAtURL:folderNSURL includingPropertiesForKeys:{} options:((its NSDirectoryEnumerationSkipsPackageDescendants) + (get its NSDirectoryEnumerationSkipsHiddenFiles)) errorHandler:(missing value))'s allObjects()
       set AppleScript's text item delimiters to linefeed
       try
              set folderItemList to ((theURLs's valueForKey:"path") as list) as text
       end try
       return folderItemList
end enumerateFolderContents:

现在,我们有了具有特权的帮助工具的列表,我们需要在路径中提取出文件名,因为我们希望在消息文本中使用这些名称来增强可信度。此外,我们可以从帮助工具的二进制文件中找到父应用程序,并将其显示给用户,同时还需要查找应用程序对应的图标。

这是我们执行第一个任务的方式,下图左侧是我们的代码,右侧展现了输出内容:

5.jpg

现在,我们已经有了目标,接下来的工作就是找到父应用程序。为此,我们将借鉴Erik Berglund的脚本并进行微调。

6.jpg

在上面的示例中,我们可以看到父应用程序的Bundle Identifier是“com.barebones.bbedit”。我们可以通过多种方式从字符串中提取标识符子字符串,比如我们可以使用awk之类的命令行使用工具(类似于Erik使用的方法),或者使用cut to slice字段。但是,出于效率的考虑,同时为了避免不必要地产生更多进程,我选用了Cocoa API的方法。请注意,无论使用哪种技术,标识符都不会始终出现在同一位置,并且可能不会以“com”开头。不过,在我们尝试的所有场景中,它都是紧随在“identifier”之后的。因此,我将其作为主要的分隔符。在这里,需要确保我们的代码考虑了一些特殊情况,由于空间不足,我在这里将省略错误检查的环节。

7.jpg

在上面的代码中,我使用Cocoa API首先在分隔符的任意一边拆分字符串。我们在第二个子字符串的开头部分找到实际的Bundle Identifier。在这里,需要注意后面的as text。在混合AppleScript与Objective C时,我们必须解决的一个难题时如何在NSString和AppleScript文本之间来回转换。

有了父应用程序的Bundle Identifier之后,借助NSWorkspace,我们可以找到父应用程序的路径。我们还将添加一个循环,以对PrivilegedHelperTools文件夹中的所有项目执行相同的操作。

8.jpg

请关注我在这里是如何将文本转换从bundleID变量中移走的,因为现在仍然需要NSString来进行NSWorkspace调用。文本转换将被延迟,直到在AppleScript调用中再次需要改字符串,该调用发生在repeat方法的末尾。

至此,我们现在有了每个具有特权的帮助工具的名称及其路径,以及Bundle Identifier和每个帮助工具父应用程序的路径。有了这些信息,我们就几乎拥有了授权请求所需的一切。接下来的最后一步,就是从每个父应用程序中获取应用程序图标。

获取父应用程序的图标图像

应用程序图标通常位于应用程序包的“Resources”(资源)文件夹中,并具有.icns扩展名。由于我们已经拥有了应用程序的路径,因此获取图标的过程应该非常简单。

在继续之前,我们首先需要为接下来的工作添加几个“帮助处理程序”,以保证代码的简洁。

10.jpg

此外,在脚本的最上方,我们定义了一些常量。目前,我们将其保留为纯文本格式,但在最终版本中我们可以借助各种方法对其进行混淆处理。

11.jpg

注意其中的defaultIconStr常量,它提供了我们的默认值。如果要查看其详细内容,可以使用以下命令来进行调用:

-- let's get the user name from Foundation framework:
       set userName to current application's NSUserName()
       display dialog hlprName & my makeChanges & return & my privString & userName & my allowThis default answer "" with title parentName default button "OK" with icon my software_update_icon as «class furl» with hidden answer

12.jpg

这个显示的图标还不错,但还有继续优化的空间,如果使用应用程序的实际图标,看起来会好很多。图标的名称被定义在应用程序的Info.plist中。我们可以添加另一个处理程序来对其进行抓取:

13.jpg

这是获取整理后的图标的代码:

14.jpg

下面是我们的脚本目前生成的一些示例:

15.jpg

16.jpg

总结

至此,我们产生的授权请求看起来非常具有说服力。在这些请求中,现在已经包含了一个真实的应用程序名称和一个进程名称。如果用户对它们进行深入调查,会发现它们都是合法的。此外,我们还有一个适当的密码字段,并且在消息文本中包含用户名称。在这一点上,并没有触发Mojave和Catalina版本中对AppleScript的增强安全机制,因此使用时也无需预先调查受害者计算机的版本信息。最重要的时,这一过程中完全不需要任何特权。

这样一来,我们就获得了想要的权限。在下一部分的文章中,我们将继续深入探究如何捕获用户输入的密码、如何在用户计算机上找到适当的时间来启动欺骗脚本,以及如何找到恰当的应用程序。我们将研究如何采用相同的技术来针对使用kexts和LaunchDaemons的其他特权应用程序。除此之外,我们将研究其他AppleScript技术,以构建具有两个文本字段的增强型对话框,敬请关注我们接下来的文章!

说明:本文中所提及的所有技术和操作过程都是完全合法的,且全程未利用任何漏洞,文章未涉及到任何漏洞的详细信息。仅供安全研究者与开发人员学习使用,不得用于非法用途。

本文翻译自:https://www.sentinelone.com/blog/macos-red-team-spoofing-privileged-helpers-and-others-to-gain-root/如若转载,请注明原文地址: https://beta.4hou.com/system/21887.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论