-
-
[翻译]利用变量检查特性完成远程代码执行
-
发表于: 2021-2-9 16:38 9735
-
大家好,我是Shawar Khan,这是2021年的第一篇专文,很激动能够和你们分享我的新发现。最近渗透Synack时遇见一个有质量准则的项目,因此我注重于找出点更好的、独特的东西。我将目标命名为redacted.com(译注:为了保护客户隐私,不会把渗透的域名透露,作者在其它文章有提及过)
这个应用程序是某种界面编辑器,允许用户上传诸如.py,.txt,.ctx2格式的文件,还可以为界面编辑器创建模板。如下图所示,有一些文件上传区域能够供用户上传模板:
Model区域可以上传扩展名为.py,.txt,.ctx2的任何文件,不限文件内容。在界面中直接打开文件并不会运行。但是,当界面编辑器的url为 4f7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6h3c8S2j5%4c8W2k6q4)9J5k6h3y4G2L8g2)9J5c8X3g2F1k6s2m8G2K9h3&6@1i4K6u0r3j5Y4g2A6L8r3c8W2M7W2)9J5c8W2)9J5x3#2)9J5c8X3q4#2N6r3S2G2M7U0q4Q4x3V1k6@1k6i4y4@1M7s2u0A6K9X3g2U0N6o6R3`.时,应用程序要求加载模型。
允许上传扩展名为.py的文件的情况并不常见。面对这种情况,我尝试最多的是了解应用程序如何处理这些文件,我们所能做的就是做到通常不可能做到的事情,然后去得到通常不可能得到的结果。
我捕获了更改已上传的python模型文件的请求,试着改动请求并在repeater中观察结果。(译注:burpsuite中的repeater模块,下同)
blob参数保存文件内容所以我在repeater中将其保留。在导航到Interface Builder并选择我的python文件后,我发现一个向 843K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6h3c8S2j5%4c8W2k6q4)9J5k6h3y4G2L8g2)9J5c8Y4j5J5i4K6u0r3L8h3!0V1k6h3I4Q4x3V1k6A6L8Y4c8J5L8%4y4H3k6h3y4@1i4K6u0r3j5i4g2@1K9r3!0J5x3g2)9J5c8Y4c8W2M7%4c8H3M7X3W2B7k6h3y4@1z5q4)9J5c8Y4c8W2M7%4c8Q4x3X3g2H3P5b7`.`.发出的请求。
这个请求是选择test.py文件后发起的,所以检查这个GET请求的响应后获得以下内容:
响应中有些奇怪的地方,它返回的JSON中functions,ranges,variables值均为null,我猜测之所以为null,是因为作为pythoncontent提交,functions,ranges,variables都不存在于我的文件中。
接下来我尝试上传含有s=1337的python文件,应用程序返回以下响应:
此时我可以确定这是个变量特征提取。从上传的python文件中提取所有可用的variables,functions和ranges并进一步使用它们处理模型。
我尝试使用woot变量,设置blob变量值为blob=print(woot)并发送请求,得到以下响应:
这是个变量woot未声明时抛出的python异常,同python交互模式下输入print(woot)抛出的异常是一样的:
这时候我确信代码执行了,但通过测试了解到代码执行需要一些条件。如果应用程序中包含的任何变量或者其它东西,没有抛出异常,则会返回所有的变量和值。但如果存在任何异常,则不会。
现在我需要得到一个包含任何命令的异常。尝试下面的代码能否运行:
import os
os.system('ls')
上传该代码并向69dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6h3c8S2j5%4c8W2k6q4)9J5k6h3y4G2L8g2)9J5c8Y4j5J5i4K6u0r3L8h3!0V1k6h3I4Q4x3V1k6A6L8Y4c8J5L8%4y4H3k6h3y4@1i4K6u0r3j5i4g2@1K9r3!0J5x3g2)9J5c8Y4c8W2M7%4c8H3M7X3W2B7k6h3y4@1z5q4)9J5c8Y4c8W2M7%4c8Q4x3X3g2H3P5g2!0q4y4g2)9^5c8W2)9&6x3g2!0q4z5g2)9^5x3q4)9^5x3g2!0q4z5q4!0m8c8W2!0n7y4#2!0q4y4W2!0n7x3g2)9^5x3W2!0q4c8W2!0n7b7#2)9^5b7#2!0q4z5q4!0n7c8W2)9&6y4q4!0q4y4g2)9&6b7W2)9&6c8g2!0q4y4q4!0n7b7W2!0m8y4g2!0q4y4q4!0n7z5q4)9^5b7W2!0q4y4g2)9&6x3#2)9^5c8q4!0q4y4g2!0n7b7g2)9&6y4q4)9K6b7b7`.`.
这证实代码被盲目的执行了但这是个作为JSON响应返回的对象,所以我不得不获取数据。由于应用程序最后一步是在运行后返回所有数据。我尝试制造异常返回代码执行的结果。通过使用str()将输出命令转换为字符串,使用int()转换为整数,应用程序将会产生ValueError并返回命令执行后的运行结果。
我将blob值设置为blob=import+os;int(str(os.listdir('/etc/')))发送请求,这个blob值将列出/etc/目录下所有files/dirs并将输出转换为字符串、整数。
向Introspect发出请求后,得到以下响应:
代码执行了!输出是/etc/下的可用文件 rc2.d', 'gai.conf', 'ld.so.cache', 'issue', 'rc0.d', 'bindresvport.blacklist', 'default', 'update-motd.d', 'rmt', 'group', 'gshadow'
我向Synack提交了最好的质量报告并获得3/3星。由于申请获得更多渗透权限没有获批,我没有更加深入。
不论何时测试应用程序的这种问题,尝试去了解应用程序如何处理用户提供的数据。或许针对用户上传的文件,存在多个端点对其进行不同的处理,比如这个项目中,检查变量时,就存在应用程序盲目执行任何命令而没有抛出错误的情况。