taibeihacker
Moderator
###HPP参数污染的定义
HTTPParameterPollution簡稱HPP,所以有的人也稱之為“HPP参数污染”,HPP是一種注入型的漏洞,攻擊者通過在HTTP請求中插入特定的參數來發起攻擊,如果Web應用中存在這樣的漏洞,可以被攻擊者利用來進行客戶端或者服務器端的攻擊。###HPP参数污染的原理
首先講下HTTP的參數處理,在跟服務器進行交互的過程中,客戶端往往會在GET/POST請求裡面帶上參數:POST /foo HTTP/1.1
User-Agent: Mozilla/5.0
Host: Host
Accept: */*
Content-Length: 19
POST /foo HTTP/1.1
User-Agent: Mozilla/5.0
Host: Host
Accept: */*
Content-Length: 19
如上面的例子所示,這些參數會以名稱-值對的形勢出現,通常在一個請求中,同樣名稱的參數只會出現一次。但是在HTTP協議中是允許同樣名稱的參數出現多次的。大家可以在下面給出的W3School鏈接上試試看:

W3Schools online HTML editor
The W3Schools online code editor allows you to edit code and view the result in your browser


https://www.baidu.com /search?p=italyp=china(百度處理第一個參數)
如果同時提供2個搜索的關鍵字參數給Google,那麼Google會對2個參數都進行查詢;百度會處理第一參數的值,但是Yahoo則不一樣,它只會處理後面一個參數。下面這個表簡單列舉了一些常見的Web服務器對同樣名稱的參數出現多次的處理方式:
Web服務器
參數獲取函數
獲取到的參數
PHP/Apache
$_GET(“par”)
last
JSP/Tomcat
Request.getParameter(“par”)
First
Perl(CGI)/Apache
Param(“par”)
First
Python/Apache
getvalue(“par”)
All (List)
ASP/IIS
Request.QueryString(“par”)
All (comma-delimited string)
假設這個URL:http://www.xxxx.com/search.php?id=110id=911
百度會理解成讓百度搜索:110 #選擇了第一個參數,放棄了第二個參數。
雅虎會理解成讓雅虎搜索:911#選擇了第二個參數,放棄了第一個參數。
谷歌會理解成讓谷歌搜索:110 911 #兩個參數同時選擇。
主要的就是這三種情況了。這主要是源於,不同的網站對處理參數的處理方式不同。
###HPP参数污染攻击方式
HTTP 參數污染,或者HPP,在網站接受用戶輸入,將其用於生成發往其它系統的HTTP 請求,並且不校驗用戶輸出的時候發生。它以兩種方式產生,通過服務器(後端)或者通過客戶端1.对客户端的攻击
比如有這樣一個網站,用來給其他人在2個候選人之間投票,這個網站的URL和代碼是這樣的:Url : http://host/election.jsp?poll_id=4568
Link1: a href='vote.jsp?poll_id=4568candidate=zhang'為張三投票/a
Link2: a href='vote.jsp?poll_id=4568candidate=li'為李四投票/a
因為種種原因,這個頁面裡面用於投票的鏈接實現的方式如下:如果這時候惡意攻擊者生成瞭如下的一個URL發給投票人:
http_://host/election.jsp?poll_id=4568candidate=zhang
那麼最終在頁面的內容會是:
Url : http://host/election.jsp?poll_id=4568candidate=zhang
Link1: a href='vote.jsp?poll_id=4568candidate=zhangcandidate=zhang'為張三投票/a
Link2: a href='vote.jsp?poll_id=4568candidate=zhangcandidate=li'為李四投票/a
前面我們有知道對於JSP來說在有2個相同的名稱的參數的時候,會取第一個值,所以不管投票人選擇的是誰,始終都是張三得票。
一般來說,對客戶端的攻擊一般會是如下流程,導致用戶選擇不期望的選項:

2.对服务器端的攻击
比如某網站的實現如下:void private executeBackendRequest(HTTPRequest request){
String action=request.getParameter('action');
String user=request.getParameter('userid');
String target=request.getParameter('target');
HttpRequest('http://centralauthencationserver/checkpriviledge.jsp', 'POST','action='+action+'user='+user+'target='+target);}
/* get feedback of whether this user has privilege to perform specified action. If no such privilege, return error, otherwise continue perform the action*/
HttpRequest('http://businessserver/performaction.php', 'POST','action='+action+'user='+user+'target='+target);}
它有個獨立的集中認證服務器用來做用戶權限方面的認證,另外的業務服務器專門用來處理業務,對外的門戶實際上緊緊只是用來做請求的轉發。那麼看看一個本來緊緊只是具有隻讀權限的用戶,如果發送如下請求給服務器:
那麼根據我們知道的Web服務器參數處理的方式,這個用戶可以通過認證做一些本來沒有權限做的事情。
Web服務器
參數獲取函數
獲取到的參數
PHP/Apache
$_GET(“par”)
Last
JSP/Tomcat
Request.getParameter(“par”)
First
###HPP参数污染TIPS
HPP還可以被攻擊者用來繞過一些Web應用防火牆(WAF, WebApp Firewall),HTTP參數污染注入源於網站對於提交的相同的參數的不同處理方式導致。例如:
www.backlion.org/a?key=abkey=3
如果服務端返回輸入key的值,可能會有
一: ab
二:3
三:ab3
這三種不同的方式。
具體服務端處理方式如下:
Web服務器
參數獲取函數
獲取到的參數
PHP/Apache
$_GET(“par”)
Last
JSP/Tomcat
Request.getParameter(“par”)
First
Perl(CGI)/Apache
Param(“par”)
First
Python/Apache
getvalue(“par”)
All (List)
ASP/IIS
Request.QueryString(“par”)
All (comma-delimited string)
假設輸入www.backlion.org/a?key=selectkey=1,2,3,4 from table
服務端有可能會將key處理為select 1,2,3,4 from table,從而導致SQL注入
再比如對某頁面的SQL注入攻擊如下:
show_user.aspx?id=5;select+1,2,3+from+users+where+id=1--
這個攻擊因為在參數id裡面存在明顯的SQL注入的模板:select…from…而會被WAF成功攔截。但是如果換成HPP的方式:
show_user.aspx?id=5;select+1id=2id=3+from+users+where+id=1--
這時候沒有任何參數具備select…from…的特徵,可能就可以繞過WAF的攔截了。
在PHP可用於以下繞過WAF:
http://www.xishaonian.com/hello.php?id=select 1id=2,3,4 from admin
該種情況還可用於Bypass WAF,當然還可以與XSS結合。
###HPP参数污染案例
案例一:2009年,ModSecurity過濾器會將類似於select1,2,3 from table這類的語句歸類為黑名單。當web服務器遇到類似/index.aspx?page=select 1,2,3 from table這樣的語句時,會阻斷請求。但是這個web服務器在遇到為同一個參數賦值不同數值時,會將它們連接起來,攻擊者可以通過這個方法來繞過黑名單。例如提交如下的URL:/index.aspx?page=select 1page=2,3from table
首先,這不是黑名單中的模式,不會觸發黑名單的攔截功能。其次,由於web程序會採取連接操作,即將符號前後的內容連接,因此SQL注入行為能夠被執行。
案例二:這個案例是關於Apple Cups的,它是被許多UNIX系統利用的打印系統。利用如下的方式觸發一個XSS攻擊:
利用這個方法可以繞過系統的驗證機制,原因是這個驗證系統只採納了第二個kerberos的值,這個值為空,因此不會觸發。而第一個kerberos直到被用於構建動態HTML內容前都沒有被驗證。最終在web站點的上下文中javascript語句被執行
案列三:很多的付款鏈接,有可能存在漏洞;一方面,付款鏈接一般會有重要的參數構建的簽名;這些簽名是由某些重要的字段組成的,加了同名的字段以後;有可能在簽名的時候驗證了第一個付款金額參數;但是在實際付款的時候用了後面的一個付款金額參數,導致簽名被繞了過去。
假設我們擁有以下站點:https://www.example.com/transferMoney.php,它可以通過POST 方法訪問,帶有以下參數:
amount=1000fromAccount=12345
當應用處理請求時,它生成自己的發往其它後端系統的POST 請求,這實際上會使用固定的toAccount參數來處理事務。
分離後端URL:https://backend.example/doTransfer.php
分離後端參數:toAccount=9876amount=1000fromAccount=12345
現在,如果在提供了重複的參數時,後端僅僅接受最後一個參數,並且假設攻擊者修改了發往網站的POST 請求來提交toAccount參數,像這樣:
amount=1000fromAccount=12345toAccount=99999
存在HPP 漏洞的站點就會將請求轉發給另一個後端系統,像這樣:
toAccount=9876amount=1000fromAccount=12345toAccount=99999(php處理最後1個參數值,即99999)
這裡,由惡意用戶提交的第二個toAccount參數,會覆蓋後端請求,並將錢轉賬給惡意用戶調教得賬戶(99999)而不是由系統設置的預期賬戶(9876)。
如果攻擊者打算修改它們自己的請求,並且由漏洞系統處理,這非常實用。但是如果攻擊者可以從另一個攢點生產鏈接,並且誘使用戶無意中提交惡意請求,並帶有由攻擊者附加的額外參數,它也可以對攻擊者更加實用一些。
案列四:另一方面,HPP 客戶端涉及到向鏈接和其它src屬性注入額外的參數。在OWASP 的一個例子中,假設我們擁有下列代碼:
? $val=htmlspecialchars($_GET['par'],ENT_QUOTES); a href='/page.php?action=viewpar='.=$val?''View Me!/a
它從URL 接受par的值,確保它是安全的,並從中創建鏈接。現在,如果攻擊者提交了:
產生的鏈接可能為:
a href='/page.php?action=viewpar=123action=edit'View Me!/a
這會導致應用接受編輯操作而不是查看操作
###HPP参数污染实列
1. HackerOne 社交分享按钮
报告连接:
Expanding Reputation: Introducing Signal and Impact
Edited on 4/8/2016 to reflect the latest Signal and Impact implementations. We first introduced Reputation in October 2014 to provide additional recognition to the best researchers, and to highlight quality reports to security teams. Each researcher has a Reputation based on their track record...
攻擊者可以將另一個URL 參數追加到鏈接中,並誘惑受害者點擊。 HackerOne 將其包含在發向社交媒體站點的POST 請求中的參數更改,從而導致漏洞的產生。漏洞報告中所用的示例是將URL:
修改為:
要注意額外的參數u,如果更改後面U參數的值誘惑受害者點擊,嘗試通過社交媒體鏈接分享內容,惡意鏈接就會變為:
Log into Facebook
Log into Facebook to start sharing and connecting with your friends, family, and people you know.
2. Twitter 取消订阅
报告连接:
mert tasci – Medium
Read writing from mert tasci on Medium. Every day, mert tasci and thousands of other voices read, write, and share important stories on Medium.
注意到參數UID可能是Twitter賬戶UID。現在要注意他做了認為多數黑客都會做的事情,嘗試UID修改為其它用戶, Twitter返回了錯誤。考慮到其他方式可能已經放棄了,Mert添加了第二個UID參數,所以URL看起來是這樣:
3. Twitter Web Intents
报告链接: 漏洞描述:根據檔Twitter Web Intents提供了彈出優化的數據流用於處理Tweets Twitter用戶:發推、回复、轉發、和關注。它使用戶能夠在你的站點上下文中和Twitter的內容進行交互,而不需要離開頁面或者授權新的應用來交互。這裡是它的一個示例:
再充分測試之後,黑客Eric Rafaloff發現全部四個Intent類型:關注用戶、喜歡推文、轉發和發推都存在HPP漏洞。
如果創建帶有兩個screen_name參數的URL:
Twitter會處理讓第二個screen_name,它比第一個優先來處理這個請求。根據Web表單類似這樣:
form class='follow 'id='follow_btn_form'action='/intent/follow?screen_name=er\ icrtest3'method='post'input type='hidden'name='authenticity_token'value='.'
input type='hidden'name='screen_name'value='twitter'
input type='hidden'name='profile_id'value='783214'
button class='button'type='submit'
b/bstrongFollow/strong
/button
/form
受害者會看到在一個screen_name中定義的用戶資料twitter,但是點擊按鈕後,它們會關注erictest3。
與之類似,當展現intent用於喜歡時,Eric發現它能夠包含screen_name參數,雖然它和喜歡這個推文毫無關係,例如:
喜歡這個推文會向受害者展示正確的用戶資料,但是點擊“關注”之後,它仍然會關注erictest3。
###漏洞防御
1.HPP是一種新的注入型漏洞。要防止這種漏洞,除了要做好對輸入參數的格式驗證外,另外還需要意識到HTTP協議是允許同名的參數的,在整個應用的處理過程中要意識到這一點從而根據業務的特徵對這樣的情況作正確的處理。2.讓WAF或其他網關設備(比如IPS)在檢查URL時,對同一個參數被多次賦值的情況進行特殊處理。由於HTTP協議允許相同參數在URL中多次出現,因此這種特殊處理需要注意避免誤殺的情況
3.在代碼層面,編寫WEB程序時,要通過合理的$_GET方法獲取URL中的參數值,而嘗試獲取web服務器返回給程序的其他值時要慎重處理。