我直接调用 execve("pkexec", a_argv, a_envp);,在a_envp中指定GCONV_PATH不就完事了吗?
linux 的动态连接器ld-linux-x86-64.so.2 会在特权程序执行的时候清除敏感环境变量,除了GCONV_PATH以外,也有其他环境变量可以直接引入外部so,如LD_PRELOAD ,所以这种方法是没用的
可以看到,GCONV_PATH就在其中,这些环境变量都能有动态加载路径的能力,因此需要防止低权限用户通过这些环境变量利用suid程序造成提权
linux 的动态连接器ld-linux-x86-64.so.2 会在特权程序执行的时候清除敏感环境变量,除了GCONV_PATH以外,也有其他环境变量可以直接引入外部so,如LD_PRELOAD ,所以这种方法是没用的
可以看到,GCONV_PATH就在其中,这些环境变量都能有动态加载路径的能力,因此需要防止低权限用户通过这些环境变量利用suid程序造成提权
高级攻击者可能会尝试攻击存在漏洞的自定义组件和第三方组件。
浏览该网站时,我们可以看到浏览器加载了几个不同的 JavaScript 文件,这些文件的 URL 很奇怪,以 /l/ 开头,后面跟着一个编码后的 JSON 对象。
在这些 JavaScript 文件中,我们可以找到最常用端点的定义,包括自定义端点和/或第三方应用程序的端点。这些定义以 JSON 格式编码:
通过扫描响应中类似格式的 JSON 字符串,可以了解自定义方法以及如何调用它们。
浏览该网站时,我们可以看到浏览器加载了几个不同的 JavaScript 文件,这些文件的 URL 很奇怪,以 /l/ 开头,后面跟着一个编码后的 JSON 对象。
在这些 JavaScript 文件中,我们可以找到最常用端点的定义,包括自定义端点和/或第三方应用程序的端点。这些定义以 JSON 格式编码:
通过扫描响应中类似格式的 JSON 字符串,可以了解自定义方法以及如何调用它们。
Salesforce Experiences 运行在 Salesforce 的 Lightning 框架之上。Lightning 是一个用于移动和桌面网站的快速开发框架。
Salesforce Lightning 是一个面向组件的框架。这些组件被称为 Aura 组件,它们是独立的对象,开发人员可以将它们组装起来以创建自定义网页。
Aura 组件可用于对 Salesforce 对象执行操作,例如查看或更新记录。组件包含控制器,这些控制器导出不同的方法来执行特定任务。
使用代理服务(例如 Burp Suite)浏览 Experience 站点,可以直观地了解 Lightning 的运行方式。Experience 的前端 Web UI 使用 HTTP 端点 /s/sfsites/aura。
当用户与 Experience 站点交互时,浏览器使用 Aura 端点来检索站点信息并执行服务器端操作。当然,这些操作都受用户的权限限制。
Salesforce Lightning 是一个面向组件的框架。这些组件被称为 Aura 组件,它们是独立的对象,开发人员可以将它们组装起来以创建自定义网页。
Aura 组件可用于对 Salesforce 对象执行操作,例如查看或更新记录。组件包含控制器,这些控制器导出不同的方法来执行特定任务。
使用代理服务(例如 Burp Suite)浏览 Experience 站点,可以直观地了解 Lightning 的运行方式。Experience 的前端 Web UI 使用 HTTP 端点 /s/sfsites/aura。
当用户与 Experience 站点交互时,浏览器使用 Aura 端点来检索站点信息并执行服务器端操作。当然,这些操作都受用户的权限限制。
现在我们可以执行 alt=media 的技巧。Google 云端硬盘返回的 JSON 数据是我们控制的响应,因此我们可以控制 URL。首先获取的文件会被解析为 PPT 格式,从而阻止完全读取权限,但我怀疑即使解析失败,下载文件也已经存储在 CDN 上了。总之,为了获得响应,我们只需重定向到一个返回 404 的页面,从而在 Java 层抛出一个异常,该异常最终会在 Web 应用中被抛出。
注意——标头“SSRF”,我的服务器会读取此标头以重定向到内部主机。
我本来想尝试一些与 pptx 相关的攻击,但团队反应迅速,一直在监控我的漏洞利用,在我第二天醒来之前就已经在生产环境中修复了。团队的反应真是太棒了 ;)
While you were playing with our systems our alerting went batshit, so we were able to react pretty quickly. We deployed quick fix for the issue. Would you be so kind and validate if our quick attempt was successful?
注意——标头“SSRF”,我的服务器会读取此标头以重定向到内部主机。
我本来想尝试一些与 pptx 相关的攻击,但团队反应迅速,一直在监控我的漏洞利用,在我第二天醒来之前就已经在生产环境中修复了。团队的反应真是太棒了 ;)
While you were playing with our systems our alerting went batshit, so we were able to react pretty quickly. We deployed quick fix for the issue. Would you be so kind and validate if our quick attempt was successful?
寻找__destruct方法,因为有一些类都存在 __wakeup方法,所以剩下的也不多。剩下的类 __destruct方法调用也很乱,所以尝试搜索 __call 方法,看看有什么可以利用的。在vendor/symfony/cache/Traits/RedisProxy.php 定义的RedisProxy类存在__call方法:
我们可以调用任意类的 __invoke 方法,并且参数可控。寻找可利用的 __invoke,在vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php定义的SchemaAssetsFilterManager类:
可以发现明显的动态函数调用,并且函数名和参数都可控。与之类似的vendor/symfony/console/Helper/Dumper.php 定义的Dumper类,这个更直接一些:
所以现在我们只需在 __destruct 中找到任意一个可控变量对任意函数的调用即可,类似$xxxx->xxxx(),这应该不难寻找,在vendor/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php中定义的CacheAdapter类:
我们可以调用任意类的 __invoke 方法,并且参数可控。寻找可利用的 __invoke,在vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php定义的SchemaAssetsFilterManager类:
可以发现明显的动态函数调用,并且函数名和参数都可控。与之类似的vendor/symfony/console/Helper/Dumper.php 定义的Dumper类,这个更直接一些:
所以现在我们只需在 __destruct 中找到任意一个可控变量对任意函数的调用即可,类似$xxxx->xxxx(),这应该不难寻找,在vendor/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php中定义的CacheAdapter类:
variables.c的initialize_shell_variables函数用于将环境变量注册成SHELL的变量,其中包含的一段代码引起了我的注意:
这里for遍历了所有环境变量,并用=分割,name就是环境变量名,string是值。
当满足下面这些条件的情况下,temp_string将被传入parse_and_execute执行:
privmode == 0,即不能传入-p参数
read_but_dont_execute == 0,即不能传入-n参数
STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN),环境变量名前10个字符等于BASH_FUNC_
STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN),环境变量名后两个字符等于%%
STREQN ("() {", string, 4),环境变量的值前4个字符等于() {
前两个条件肯定是满足的,后三个条件是用户可控的,所以这个if语句是肯定可以进入的。进入if语句后,去除前缀BASH_FUNC_和后缀%%的部分将是一个变量名,而由() {开头的字符串将会被执行。
这里for遍历了所有环境变量,并用=分割,name就是环境变量名,string是值。
当满足下面这些条件的情况下,temp_string将被传入parse_and_execute执行:
privmode == 0,即不能传入-p参数
read_but_dont_execute == 0,即不能传入-n参数
STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN),环境变量名前10个字符等于BASH_FUNC_
STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN),环境变量名后两个字符等于%%
STREQN ("() {", string, 4),环境变量的值前4个字符等于() {
前两个条件肯定是满足的,后三个条件是用户可控的,所以这个if语句是肯定可以进入的。进入if语句后,去除前缀BASH_FUNC_和后缀%%的部分将是一个变量名,而由() {开头的字符串将会被执行。
这个地方的鉴权可以被绕过,使用空账号密码来连接即可,绕过代码如下
dnspy附加进程调试之后,发现成功绕过鉴权返回result
接着跟入又是tcp编程的写法,异步callback,关键函数在Veeam.Backup.ServiceLib.CInvokerServer.ExecThreadProc(object)
tcp压缩数据流通过ReadCompressedString读出字符串,然后通过CForeignInvokerParams.GetContext(text)获取上下文,然后交由this.DoExecute(context, cconnectionState)进行分发调用。
在GetContext函数中
public static CSpecDeserializationContext GetContext(string xml)
{
return new CSpecDeserializationContext(xml);
}
将字符串交给CSpecDeserializationContext构造函数
dnspy附加进程调试之后,发现成功绕过鉴权返回result
接着跟入又是tcp编程的写法,异步callback,关键函数在Veeam.Backup.ServiceLib.CInvokerServer.ExecThreadProc(object)
tcp压缩数据流通过ReadCompressedString读出字符串,然后通过CForeignInvokerParams.GetContext(text)获取上下文,然后交由this.DoExecute(context, cconnectionState)进行分发调用。
在GetContext函数中
public static CSpecDeserializationContext GetContext(string xml)
{
return new CSpecDeserializationContext(xml);
}
将字符串交给CSpecDeserializationContext构造函数
這技巧是由 project zero 在 2014 所提出的方法,覆蓋 TLS 上的 tls_dtor_list 來做利用,藉由覆蓋該變數可在程式結束時控制程式流程。
這邊就稍微提一下這個方法,tls_dtor_list 是個 dtor_list object 的 singly linked list 主要是存放 thread local storage 的 destructor,在 thread 結束時會去看這個 linked list 並去呼叫 destructor function,我們可藉由覆蓋 tls_dtor_list 指向我們所構造的 dtor_list。
而當程式結束呼叫 exit() 時,會去呼叫 call_tls_dtors() ,該 function 會去取 tls_dtor_list 中的 object 並去呼叫每個 destructor,此時如果我們可以控制 tls_dtor_list 就會去使用我們所構造的 dtor_list 來呼叫我們指定的函式。
但在新版本和 synology 的 libc 中,dtor_list 的 function pointer 有被 pointer guard 保護,導致正常情況下,我們並不好利用,一樣需要先 leak 出 pointer guard 才能好好控制 rip 到我們想要的位置上。
但有趣的是 pointer guard 也會在 TLS 上,他會存在 TLS 中的 tcbhead_t 結構中,如果我們 overflow 夠多,也可以在 overflow tls_dtor_list 的同時,也將 pointer guard 也一併清掉,這樣就可以讓我們不用處理 pointer guard 問題。
struct dtor_list
{
dtor_func func;
void *obj;
struct link_map *map;
struct dtor_list *next;
}
這邊就稍微提一下這個方法,tls_dtor_list 是個 dtor_list object 的 singly linked list 主要是存放 thread local storage 的 destructor,在 thread 結束時會去看這個 linked list 並去呼叫 destructor function,我們可藉由覆蓋 tls_dtor_list 指向我們所構造的 dtor_list。
而當程式結束呼叫 exit() 時,會去呼叫 call_tls_dtors() ,該 function 會去取 tls_dtor_list 中的 object 並去呼叫每個 destructor,此時如果我們可以控制 tls_dtor_list 就會去使用我們所構造的 dtor_list 來呼叫我們指定的函式。
但在新版本和 synology 的 libc 中,dtor_list 的 function pointer 有被 pointer guard 保護,導致正常情況下,我們並不好利用,一樣需要先 leak 出 pointer guard 才能好好控制 rip 到我們想要的位置上。
但有趣的是 pointer guard 也會在 TLS 上,他會存在 TLS 中的 tcbhead_t 結構中,如果我們 overflow 夠多,也可以在 overflow tls_dtor_list 的同時,也將 pointer guard 也一併清掉,這樣就可以讓我們不用處理 pointer guard 問題。
❤1
Please open Telegram to view this post
VIEW IN TELEGRAM