httpoxy 是一系列影響到以 cgi 或類 cgi 方式運作的應用的漏洞名稱。簡單的來說,它就是一個名字空間的沖突問題。
rfc 3875 (cgi)中定義了從 http 請求的 <code>proxy</code> 頭部直接填充到環境變量 <code>http_proxy</code> 的方式
<code>http_proxy</code> 是一個常用于配置外發代理的環境變量
這個缺陷會導緻遠端攻擊。如果你正在運作着 php 或 cgi 程式,你應該馬上封擋 proxy 頭部!馬上! 具體做法參見下面。httpoxy 是一個伺服器端 web 應用漏洞,如果你沒有在伺服器端部署這些代碼,則不用擔心。
<a target="_blank"></a>
當一個利用了此漏洞的 http 用戶端發起請求時,它可以做到:
通過你的 web 應用去代理請求别的 url
直接讓你的伺服器打開指定的遠端位址及端口
浪費伺服器的資源,替攻擊者通路指定的資源
httpoxy 漏洞非常容易利用。希望安全人員盡快掃描該漏洞并快速修複。
以下情況會存在安全漏洞:
代碼運作在 cgi 上下文中,這樣 <code>http_proxy</code> 就會變成一個真實的或模拟的環境變量
一個信任 <code>http_proxy</code>的 http 用戶端,并且支援代理功能
該用戶端會在請求内部發起一個 http(或 https)請求
下列情形是已經發現存在該缺陷的環境:
語言
環境
http 用戶端
php
php-fpm
mod_php
guzzle 4+
artax
python
wsgiref.handlers.cgihandler
twisted.web.twcgi.cgiscript
requests
go
net/http/cgi
net/http
肯定還有很多我們沒有确定是否存在缺陷的語言和環境。
是否存在缺陷依賴于你的應用代碼和 php 庫,但是影響面看起來似乎非常廣泛
隻要在處理使用者請求的過程中使用了一個帶有該缺陷的庫,就可能被利用
如果你使用了有該缺陷的庫,該缺陷會影響任意 php 版本
甚至會影響到替代的 php 運作環境,比如部署在 fastcgi 模式下的 hhvm
确認影響 guzzle、artax 等庫,可能還有很多很多的庫也受影響
guzzle 4.0.0rc2 及其以後版本受影響,guzzle 3 及更低版本不受影響
其它的例子還有 composer 的 streamcontextbuilder 工具類
舉個例子說,如果你在 drupal 中使用 guzzle 6 子產品發起外發請求(比如請求一個天氣 api),該子產品發起的請求就存在這個 httpoxy 缺陷。
python 代碼隻有部署在 cgi 模式下才存在缺陷,一般來說,存在缺陷的代碼會使用類似<code>wsgiref.handlers.cgihandler</code> 的 cgi 控制器
正常方式部署的 python web 應用不受影響(大多數人使用 wsgi 或 fastcgi,這兩個不受影響),是以受到影響的 python 應用要比 php 少得多
wsgi 不受影響,因為 os.environ 不會受到 cgi 資料污染
存在缺陷的 requests 庫必須信任和使用 <code>os.environ['http_proxy']</code>,并且不做内容檢查
go 代碼必須部署在 cgi 下才受影響。一般來說受到影響的代碼會使用 <code>net/http/cgi</code> 包
像 python 一樣,這并不是部署 go 為一個 web 應用的通常方式。是以受到影響的情形很少
相較而言,go 的 <code>net/http/fcgi</code> 包并不設定實際的環境變量,是以不受影響
存在缺陷的 <code>net/http</code> 版本需要在外發請求中信任并使用 <code>http_proxy</code> ,并不做内容檢查
最好的修複方式是在他們攻擊你的應用之前盡早封擋 <code>proxy</code> 請求頭部。這很簡單,也很安全。
符合标準的 http 用戶端和伺服器絕不應該讀取和發送這個頭部
你可以從請求中去掉這個頭部或者幹脆整個封擋使用它的請求
你可以在上遊沒有釋出更新檔時自己來解決這個問題
當 http 請求進來時就檢查它,這樣可以一次性修複好許多存在缺陷的應用
在反向代理和應用防火牆之後的應用剔除 <code>proxy</code> 請求頭部是安全的
如何封擋 <code>proxy</code> 請求頭部依賴于你的配置。最容易的辦法是在你的 web 應用防火牆上封擋該頭部,或者直接在 apache 和 nginx 上做也行。以下是一些如何做的指導:
使用如下語句封擋傳遞給 php-fpm、php-pm 的請求頭,這個語句可以放在 fastcgi.conf 或 fastcgi_param 中(視你使用了哪個配置檔案):
<code>fastcgi_param http_proxy "";</code>
在 fastcgi 模式下,php 存在缺陷(但是大多數使用 nginx fastcgi 的其它語言則不受影響)。
如果你在 apache http 伺服器中使用 <code>mod_cgi</code>來運作 go 或 python 寫的腳本,那麼它們會受到影響(這裡 <code>http_proxy</code> 環境變量是“真實的”)。而 <code>mod_php</code> 由于用于 php 腳本,也存在該缺陷。
如果你使用 mod_headers 子產品,你可以通過下述配置在進一步處理請求前就 unset 掉 <code>proxy</code> 請求頭部:
<code>requestheader unset proxy early</code>
如果你使用 mod_security 子產品,你可以使用一個 <code>secrule</code> 規則來拒絕帶有 <code>proxy</code> 請求頭部的請求。下面是一個例子,要確定 <code>secruleengine</code> 打開了。你可以根據自己的情況調整。
<code>secrule &request_headers:proxy "@gt 0" "id:1000005,log,deny,msg:'httpoxy denied'"</code>
通過下述配置剔除該請求頭部:
<code>http-request del-header proxy</code>
通過下述語句取消該頭部,請将它放到已有的 vcl_recv 小節裡面:
<code>sub vcl_recv {</code>
<code>[...]</code>
<code>unset req.http.proxy;</code>
<code>}</code>
使用如下語句移除該頭部。把它放到已有的過濾器裡面:
<code>http protocol httpfilter {</code>
<code>match request header remove "proxy"</code>
彈回包含 <code>proxy</code> 頭部的請求。
建立一個 <code>/path/to/deny-proxy.lua</code>檔案,讓它對于 lighttpd 隻讀,内容如下:
<code>if (lighty.request["proxy"] == nil) then return 0 else return 403 end</code>
修改 <code>lighttpd.conf</code> 以加載 <code>mod_magnet</code> 子產品,并運作如上 lua 代碼:
<code>server.modules += ( "mod_magnet" )</code>
<code>magnet.attract-raw-url-to = ( "/path/to/deny-proxy.lua" )</code>
從請求中剔除 <code>proxy</code> 頭部。加入如下語句到 <code>lighttpd.conf</code>中:
<code>req_header.remove "proxy";</code>
使用者端的修複不能解決該缺陷,是以不必費勁:
使用 <code>unset($_server['http_proxy'])</code> 并不會影響到 <code>getenv() </code>傳回的值,是以無用
使用 <code>putenv('http_proxy=')</code> 也沒效果(putenv 隻能影響到來自實際環境變量的值,而不是來自請求頭部的)
原文釋出時間為:2016-07-19
本文來自雲栖社群合作夥伴“linux中國”