從偶然出發

在做測試的時候發現了這樣一個漏洞,原請求報文如下:

GET / HTTP/1.1
Host: attack_website
[... HEADER ...]

...

當時最初目的是想測SSRF的,但是經過測試沒發現存在漏洞後來想起之前看過的一些漏洞案例,將請求報文中的URI部分替換成了網址:

gh0st.cn

就變成了如下的請求:

GET http://gh0st.cn HTTP/1.1
Host: attack_website
[... HEADER ...]

...

在BurpSuite里進行重放測試發現返回的響應正文就是 gh0st.cn 的,也就是說這裡的attack_website可以被作為HTTP代理,於是進入下一步的測試能否使用非http/https協議進行請求?例如file:///,測試後發現確實沒辦法這樣玩,看來是這裡代理伺服器不支持。

在這裡替換URI部分為內網的地址,可以直接漫遊內網的系統,進行深入的滲透測試了,後續的事情就不在這多說了,那麼來研究看看為什麼會有這樣的問題呢?

從被動偶然到主動發現

了解原理

查閱了一番資料和詢問了一下朋友,都說具體的不太清楚,後來看見這樣一篇文章:

secpulse.com/archives/7

其中所說原理大致是因為Nginx反向代理配置不當導致可以被作為正向代理,導致能被外部作為HTTP代理伺服器。

正向代理 and 反向代理

正向代理

  • 瀏覽器(/全局)設置代理伺服器IP和對應埠
  • 瀏覽器輸入目標地址->代理伺服器->目標伺服器

簡而言之,正向代理類似我們經常用到的跳板機,利用代理去訪問外部的資源。

反向代理

跟正代不同的地方在於反向代理相對瀏覽器來說是透明的,不需要在瀏覽器(/全局)做什麼配置,而是有反向代理伺服器自己做請求轉發到其伺服器上所配置的地址。

大致如下的流程:

  1. 瀏覽器訪問網站(網站所指即反向代理伺服器)
  2. 網站(反向代理伺服器)做處理,將請求轉發給所設置的目標伺服器
  3. 由請求最終到達的目標伺服器響應給網站(反向代理伺服器),然後再通過其返回給瀏覽器

TIPs:

  • 一、反向代理伺服器也可以變成WAF(例如Nginx支持反代功能,nginx+lua也可以搭建網站waf)
  • 二、反向代理伺服器也可以起到負載均衡的作用,由反向代理伺服器做選擇分配Web伺服器

主動發現腳本開發

腳本語言選擇:python2.7

系統環境:all

思考

如何判斷這個網站存在可以作為HTTP代理訪問資源?唯一特徵是什麼?

腦子中唯一的思路就是IP,如果這目標站點能作為HTTP代理訪問資源,那麼我設置的這個資源就是返回真實IP的,這樣就可以判斷了~

這裡我在團隊官網上小小的寫了一個,但是在大批量去測試卻無法使用,因為官網的空間沒那麼大的吞吐量,承載不住高並發,後期建議大家使用 httpbin.org/ip 這個介面~

hi-ourlife.com/getip.ph

PHP代碼:

<?php
echo $_SERVER[REMOTE_ADDR];
?>

代碼構建

Import 庫

import urllib, sys, re, json

全局變數:

poc = "http://www.hi-ourlife.com/getip.php"

獲取使用代理訪問資源後內容(IP)函數:

def useProxy(site):
try:
res = urllib.urlopen(poc, proxies={http: site}).read()
return res
except:
return getIP()

正常本機獲取IP函數:

def getIP():
res = urllib.urlopen(poc).read()
return res

防止有些會出錯返回的內容不是IP,其實返回不是IP也就間接證明不存在這種漏洞,所以需要寫個正則來匹配,這時候判斷是否是IP的函數就誕生了:

def isIP(ip):
compileIP = re.compile(^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)$)
if compileIP.match(ip):
return True
else:
return False

對比IP函數:

def isVul(site):
resA = getIP()
#print resA
resB = useProxy(site)
#print resB
if resA == resB or not isIP(resB):
print "

相关文章