來自orange大大發表的 https://blog.orange.tw/2024/08/confusion-attacks-ch.html
apache source code
https://github.com/apache/httpd/
挑選apache的原因是,整個 Httpd 的服務需要由數百個小模組合作完成客戶端的 HTTP 請求,但是在彼此模組間實作理解上的差異及不了解,可能導致漏洞(中間那塊是模組彼此共享的大struct)
官方列出的模組:
https://httpd.apache.org/docs/2.4/mod/
首先r->filename
感覺是個檔案系統路徑,然而在 Httpd 中,有些模組會把它當成網址來處理
如下,mod_rewrite(RewriteRule 語法將路徑透過指定的規則改寫)會把它當網址處理
像是
若我們請求 http://server/user/orange
根據/user後面找到/orange放入$1
來抓到
https://github.com/apache/httpd/blob/2.4.58/modules/mappers/mod_rewrite.c#L4141
這邊看到
追進去看到 https://github.com/apache/httpd/blob/2.4.58/modules/mappers/mod_rewrite.c#L771
總之他會把?後面的參數省略掉,所以如果使用
%2F -> /
%3F -> ?
這樣會變成
問號後面被當參數省略
路徑截斷就達成了
若管理員使用了下列方式設定
如果請求附檔名是 .php 結尾則加上 mod_php 相對應的處理器
https://httpd.apache.org/docs/2.4/rewrite/flags.html
這邊設置了
[H=application/x-httpd-php]
H -> header
意思是把.php,設置內容類型(MIME 類型),伺服器應將匹配的文件作為 PHP 文件處理
那如果我把一張 1.gif 設為
如果單純請求
那理論上它是個.gif啥都不會執行
但是如果我這樣請求
因為結尾是.php所以接下來會把檔案強制解析成.php,接著?截斷把ooo.php丟棄,最後1.gif被當.php解析執行
印出
what is apache ACL?
https://httpd.apache.org/docs/2.4/howto/access.html
Filename Confusion 的第二個攻擊手法發生在 mod_proxy 身上,相較前一個攻擊是無條件將目標當成網址處理,這次則是因為模組間對 r->filename 的理解不一致所導致的認證及存取控制繞過
mod_proxy 在做的事情就是將請求導向到其它網址上
所以會把 r->filename 解析成url
https://httpd.apache.org/docs/current/mod/core.html#files
首先是可以用apache server的file對於單一檔案加上限制,在預設安裝的 PHP-FPM 環境中,這種設定可以被直接繞過
若我今天用這種方式請求
此時 r->filename 欄位是 admin.php?ooo.php 理所當然與 admin.php 不符合
再來預設 PHP-FPM 在收到請求後預設透過set-handler -> mod_proxy
https://blog.csdn.net/qq_21956483/article/details/82847744
mod_proxy 會將 r->filename 重寫成以下網址
後端在收到檔案名稱會進行特別處理
以下是處理邏輯
https://github.com/php/php-src/blob/ce51bfac759dedac1537f4d5666dcd33fbc4a281/sapi/fpm/fpm/fpm_main.c#L1044
一樣也可以看到針對 ? 進行截斷,取出實際的檔案路徑並執行 (也就是 /var/www/html/admin.php)
這樣就可以bypass file限制了
認證模組以及 mod_proxy 間對 r->filename 欄位理解的不一致 -> bypass
總結
針對這個設定
若訪問這樣
會訪問到 /var/www/html/about.html 還是 /about.html 呢?
ans: 兩個都會
因為httpd會去嘗試存取帶有 DocumentRoot 的路徑以及沒有的路徑
https://github.com/apache/httpd/blob/c3ad18b7ee32da93eabaae7b94541d3c32264340/modules/mappers/mod_rewrite.c#L4939
https://httpd.apache.org/docs/current/rewrite/remapping.html#rewrite-query
從官方範例文件可以看到一些有問題的寫法
若能控 RewriteRule 的目標前綴那我們是不是就能瀏覽作業系統上的任意檔案了嗎?
開始基於項設定做攻擊
到了這邊,或許會想說可以去讀像是/etc/passwd
等任意檔案但其實不然,原因是
https://luckymrwang.github.io/2015/06/03/Apache-AllowOverride-None-及-Option-详解/
https://github.com/apache/httpd/blob/trunk/docs/conf/httpd.conf.in#L115
apache內建把根目錄及其所有子目錄的存取禁用,他會忽略.htaccess的rewrite規則,避免了危險的rewrite
不過這邊發現了 ubuntu/debian上
https://sources.debian.org/src/apache2/2.4.62-1/debian/config-dir/apache2.conf.in/#L165
/usr/share是被允許存取的,所以可以嘗試利用這份文件中,所有的教學範例、說明文件、單元測試檔案來濫用
也就是把檔案當gadget串出各種攻擊
websocketd:
/usr/share/doc/websocketd/examples/php/ 下的範例php可以leak 敏感環境變數
https://github.com/Textalk/websocket-php/tree/master/examples
像是NGINX跟jetty也有許多可以利用,這些服務的預設 Web Root 就在 /usr/share,所以可以讀出很多敏感資訊
/usr/share/nginx/html/
/usr/share/jetty9/etc/
/usr/share/jetty9/webapps/
另外像是Davical 套件所存在的 setup.php可以讀出phpinfo
/usr/share/libreoffice/help/help.html
這是libreoffice提供的語言切換功能
這上面把version放入到index.html前,所以newURL被加入js就可以達成XSS
/usr/share/libreoffice/help/help.html??Version=javascript:aler(1)//
JpGraph、jQuery-jFeed、 WordPress 或 Moodle 外掛等自帶的教學或debug檔案可以串出LFI
/usr/share/doc/libphp-jpgraph-examples/examples/show-source.php
/usr/share/javascript/jquery-jfeed/proxy.php
/usr/share/moodle/mod/assignment/type/wims/getcsv.php
https://github.com/jfhovinne/jFeed/blob/master/proxy.php
fopen未過濾導致任意讀
MagpieRSS -> magpie_debug.php
fetch_rss可以做SSRF
https://github.com/cogdog/feed2js/blob/master/magpie_debug.php
舊版本的phpunit檔案存在可以直接用CVE-2017-9841
https://github.com/vulhub/vulhub/tree/master/phpunit/CVE-2017-9841
phpLiteAdmin預設密碼admin
接下來是跳脫出/usr/share
Httpd 發行版中預設開啟了 FollowSymLinks
https://sources.debian.org/src/apache2/2.4.62-1/debian/config-dir/apache2.conf.in/#L160
所以可以利用symlink機制來讀到以外的檔案
https://httpd.apache.org/docs/current/mod/core.html#options
Redmine的雙層symlink 到 RCE
從/usr/share跳到/var/lib/redmine,繼續跳到/etc/redmine讀取到了secret key
secret_key.txt是簽章所使用的 -> RoR
已知的金鑰將惡意 Marshal 物件簽章加密後嵌入 Cookie,接著透過伺服器端的反序列化最終實現遠端程式碼
https://drive.google.com/file/d/1UMxphxFxwRf7wbrw4_Hr56KGPzpLU3Ef/view
這兩種都可以讓php跑起來
https://github.com/apache/httpd/blob/2.4.58/server/config.c#L420
來讀讀這段code
先檢查 r->handler 是否已設置
如果 r->handler 沒有設置,代碼會嘗試根據 r->content_type 來設置它。
根據 r->content_type 設置 handler
如果 r->content_type 已設置,代碼會將其值賦給 handler。
如果 r->content_type 沒有設置,則使用默認的 handler(AP_DEFAULT_HANDLER_NAME)
調用 ap_run_handler:
最後,通過 ap_run_handler(r)
調用 handler 來處理請求。
因此兩種方法都可以找到對的handler
若 apache HTTP Server 透過 AddType 將 PHP 運行起來
呼叫
http://server/config.php
type_checker 根據 addtype 設定的附檔名將相對應的內容複製到 r->content_type
而整個http週期並未給r -> handler賦值
r->content_type在進入到ap_invoke_handler前被拿來當成模組處理器使用
看到上述的source 也可以看到會根據 r->content_type 設置 handler
但是,若進入ap_invoke_handler前r->content_type會發生甚麼問題呢
若是用了錯誤的contenet length,除了報錯外,也會回傳php source code
ModSecurity 在使用 APR 沒有檢查好回傳值
導致r -> content_type被改寫成了text/html,因為它會想要丟一個錯誤的頁面而被覆寫
這就回傳了兩個回應
一個是錯誤頁面
一個是應該用application/x-httpd-php的php頁面,被覆蓋成text/html當文字回傳
造成了double response
https://github.com/owasp-modsecurity/ModSecurity/issues/2514
然而觀察到一件事情是,其實只要能夠寫掉r -> content_type就會造成呼叫任意 Apache HTTP Server 的內部模組處理器
然而發生問題的地方位於最後段
到底要怎麼觸發
這邊基於這個來做
這是一段有問題的寫法,因為redir可控,導致了CRLF注入,從而造成了可以偽造標頭
https://ithelp.ithome.com.tw/articles/10242682
另外看一下RFC
https://datatracker.ietf.org/doc/html/rfc3875
他規定了網址轉址的規範
接下來就是開始追code
這裡檢查了Location標頭是否存在且以/開頭,並且HTTP狀態碼是200(即請求成功)。這代表伺服器希望將客戶端重定向到同一個伺服器上的不同位置
當需要進行重定向時,這行代碼會處理內部重定向。也就是說,伺服器會把當前的請求路徑替換成Location標頭指定的新路徑,然後重新處理請求
追進去ap_internal_redirect_handler看發現了關鍵
直接copy過來
所以就有一個新的http流程了
最後回來看CRLF的部分
這樣來偽造content-type
這樣任意控handler
就可以用惡意的圖片等,然後用想要的handler去把圖片當腳本用來執行
https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html
其中我最喜歡的兩個部分第一個是把檔案當gadget用,透過伺服器上現有的不管是教學檔案或是任何文件濫用,串出了RCE
另外透過symlink來跳脫出當前目錄,去濫用到其他目錄的檔案,串出了RCE
原本開發者以為安全的教學文件(因為使用者戳不到)但在因為一個?被截斷後,導致存取到了伺服器上的其他資源,以及藉由方便的symlink跳脫出目錄,十分的新穎,原本看似無害的東西,透過一連串的觸發,達成RCE,真的很酷
膜拜orange orz
這邊挖個坑,日後會來復現