目錄
一、nginx解析php的流程
1.原理? ?
2.CGI、FastCGI、PHP-FPM、PHP-CG、WrapperI的定義
二、Fastcgi協(xié)議
1.Fastecgi Record
2.Fastcgi Type
3.PHP-FPM(FastCGI進程管理器)
4.總結(jié)FastCGI解析的流程
三、nginx配置錯誤導(dǎo)致的漏洞
1.CRLF注入漏洞($uri解碼漏洞,換行符導(dǎo)致的注入漏洞)
(1)原理
(2)利用CRLF修改頭部信息
(3)CRLF+Bottle HTTP造成的反射性xss漏洞
(4)防御
2.目錄穿越漏洞
(1)原理
(2)漏洞復(fù)現(xiàn)
(3)防御
3.Http add_header被覆蓋的問題
(1)原理
(2)CSP(Content-Security-Policy)
(3)漏洞的復(fù)現(xiàn)
(4)防御
四、nginx文件名邏輯漏洞(Nginx 0.8.41 ~ 1.4.3 /1.5.0 ~ 1.5.7 )
1.原理
2.文件名邏輯漏洞的復(fù)現(xiàn)
(1)首先創(chuàng)建一個文本,里面輸入php代碼
(2)修改文件后綴名為1.gif
(3)打開瀏覽器輸入
(4)選擇我們1.gif文件
(5)打開抓包工具,之后上傳文件抓包
(6)找到文件名給他加成1.gifaa.php
(7)進入到hex也就是編碼數(shù)字的部分,修改文件名,將aa改成20和00,主要是讓他生成 \0(也就是一個空格和階段符號)。
(8)將修改的數(shù)據(jù)包放行提交到端
(9)查看我們上傳圖片的目錄
?(10)打開抓包工具抓取該網(wǎng)頁,出現(xiàn)以下問題,是因為我們禁止了抓包工具抓取圖片,我們點擊開啟就可以了。
?(11)抓包
?(13)修改我們的文件名為1.gifaa.php
?(14)進入到hex下,修改我們的aa編碼為20和00,就是空格和截斷符,這里主要是為了和我們上傳的文件名一樣
?(15)將我們修改過的數(shù)據(jù)包發(fā)送就會看到我們注意的php頁面
?3.防御
五、nginx的解析漏洞
1.原理
2.nginx解析漏洞復(fù)現(xiàn)
(1)先看我們php-fpm配置文件,發(fā)現(xiàn)我們的后綴名安全策略為空的
(2)訪問http://192.168.191.129/uplocalfiles/nginx.png
(3)在上面路徑后面隨意添加一個以.php結(jié)尾的文件
?(4)觸發(fā)我們的php惡意代碼
(5)還有一種方法和上面nginx邏輯名漏洞一樣上傳php惡意文件,修改名稱,第二次直接訪問就會觸發(fā)
一、nginx解析php的流程
1.原理? ?
????????首先瀏覽器對nginx進行傳輸數(shù)據(jù),nginx接收到瀏覽器傳過來的數(shù)據(jù)之后,通過fastcgi協(xié)議將數(shù)據(jù)格式化成fastcgi規(guī)定的形式,格式完之后通過php-fpm進程管理工具,格式成n多個的phpcgi,從而處理成fastcgi規(guī)范的數(shù)據(jù),處理完的數(shù)據(jù)交給我們的php,然后PHP將數(shù)據(jù)傳遞給我們的nginx。
2.CGI、FastCGI、PHP-FPM、PHP-CG、WrapperI的定義
-
CGI:CGI是一種協(xié)議,它定義了Nginx或者其他Web Server傳遞過來的數(shù)據(jù)格式,全稱是(Common Gateway Interface,CGI),CGI是一個獨立的程序,獨立與WebServer之外,任何語言都可以寫CGI程序,例如C、Perl、Python等。
-
FastCGI:FastCGI是一種協(xié)議,它的前身是CGI,可以簡單的理解為是優(yōu)化版的CGI,擁有更夠的穩(wěn)定性和性能。
-
PHP-CGI:只是一個PHP的解釋器,本身只能解析請求,返回結(jié)果,不會做進程管理。
-
PHP-FPM:全稱FastCGI Process Manager,看名稱就可以知道,PHP-FPM是FastCGI進程的管理器,但前面講到FastCGI是協(xié)議并不是程序,所以它管理的是PHP-CGI,形成了一個類似PHP-CGI進程池的概念。
-
Wrapper:字母意思是包裝的意思,包裝的是誰呢?包裝的是FastCGI,通過FastCGI接口,Wrapper接收到請求后,會生成一個新的線程調(diào)用PHP解釋器來處理數(shù)據(jù)。
二、Fastcgi協(xié)議
1.Fastecgi Record
????????Fastcgi其實是一個通信協(xié)議,fastcgi協(xié)議則是服務(wù)器中間件和某個語言后端進行數(shù)據(jù)交換的協(xié)議。Fastcgi協(xié)議由多個record組成,record也有header和body一說,服務(wù)器中間件將這二者按照fastcgi的規(guī)則封裝好發(fā)送給語言后端,語言后端解碼以后拿到具體數(shù)據(jù),進行指定操作,并將結(jié)果再按照該協(xié)議封裝好后返回給服務(wù)器中間件。其結(jié)構(gòu)如下
typedef struct {
? /* Header */
? unsigned char version; // 版本
? unsigned char type; // 本次record的類型
? unsigned char requestIdB1; // 本次record對應(yīng)的請求id
? unsigned char requestIdB0;
? unsigned char contentLengthB1; // body體的大小
? unsigned char contentLengthB0;
? unsigned char paddingLength; // 額外塊大小
? unsigned char reserved;?? /* Body */
? unsigned char contentData[contentLength];
? unsigned char paddingData[paddingLength];
} FCGI_Record;
????????頭由8個uchar類型的變量組成,每個變量1字節(jié)。其中,requestId
占兩個字節(jié),一個唯一的標志id,以避免多個請求之間的影響;contentLength
占兩個字節(jié),表示body的大小。
????????語言端解析了fastcgi頭以后,拿到contentLength
,然后再在TCP流里讀取大小等于contentLength
的數(shù)據(jù),這就是body體。
我們需要注意的是typre類型
2.Fastcgi Type
????????type是用來編輯fastcgi的主要作用,最主要的是1、4、6
????????值得注意的是,當(dāng)我們的type是4的時候,就會按照對應(yīng)的結(jié)構(gòu)解析成我們的key-value,結(jié)構(gòu)如下
typedef struct {
? unsigned char nameLengthB0; ?/* nameLengthB0 ?>> 7 == 0 */
? unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
? unsigned char nameData[nameLength];
? unsigned char valueData[valueLength];
} FCGI_NameValuePair11;typedef struct {
? unsigned char nameLengthB0; ?/* nameLengthB0 ?>> 7 == 0 */
? unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
? unsigned char valueLengthB2;
? unsigned char valueLengthB1;
? unsigned char valueLengthB0;
? unsigned char nameData[nameLength];
? unsigned char valueData[valueLength
? ? ? ? ? ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
} FCGI_NameValuePair14;typedef struct {
? unsigned char nameLengthB3; ?/* nameLengthB3 ?>> 7 == 1 */
? unsigned char nameLengthB2;
? unsigned char nameLengthB1;
? unsigned char nameLengthB0;
? unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
? unsigned char nameData[nameLength
? ? ? ? ? ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
? unsigned char valueData[valueLength];
} FCGI_NameValuePair41;typedef struct {
? unsigned char nameLengthB3; ?/* nameLengthB3 ?>> 7 == 1 */
? unsigned char nameLengthB2;
? unsigned char nameLengthB1;
? unsigned char nameLengthB0;
? unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
? unsigned char valueLengthB2;
? unsigned char valueLengthB1;
? unsigned char valueLengthB0;
? unsigned char nameData[nameLength
? ? ? ? ? ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
? unsigned char valueData[valueLength
? ? ? ? ? ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
} FCGI_NameValuePair44;
????????我們需要注意的是上述我標紅的部分,當(dāng)為44的部分時候,會將我們的key-value,傳遞到我們的php-fpm解析成我們真正的數(shù)據(jù)。
3.PHP-FPM(FastCGI進程管理器)
????????FPM其實是一個fastcgi協(xié)議解析器,Nginx等服務(wù)器中間件將用戶請求按照fastcgi的規(guī)則打包好通過TCP傳給FPM,F(xiàn)PM按照fastcgi的協(xié)議將key-value解析成真正的數(shù)據(jù)。結(jié)構(gòu)如下
{
? ? 'GATEWAY_INTERFACE': 'FastCGI/1.0',
? ? 'REQUEST_METHOD': 'GET',
? ? 'SCRIPT_FILENAME': '/var/www/html/index.php',
? ? 'SCRIPT_NAME': '/index.php',
? ? 'QUERY_STRING': '?a=1&b=2',
? ? 'REQUEST_URI': '/index.php?a=1&b=2',
? ? 'DOCUMENT_ROOT': '/var/www/html',
? ? 'SERVER_SOFTWARE': 'php/fcgiclient',
? ? 'REMOTE_ADDR': '127.0.0.1',
? ? 'REMOTE_PORT': '12345',
? ? 'SERVER_ADDR': '127.0.0.1',
? ? 'SERVER_PORT': '80',
? ? 'SERVER_NAME': "localhost",
? ? 'SERVER_PROTOCOL': 'HTTP/1.1'
}
最后執(zhí)行SCRIPT_FILENAM的指向的PHP文件,將這個數(shù)據(jù)返回給我們的瀏覽器。
4.總結(jié)FastCGI解析的流程
????????首先nginx接收到數(shù)據(jù)后,會被fastcgi處理,會按照type為4,構(gòu)造出我們的key-value,然后傳遞給我們的php-fpm,php-fpm會將key-value對解析成我們真正的數(shù)據(jù),這個數(shù)據(jù)中包含我們的版本,傳參方式,請求文件根目錄路徑,請求的文件,請求參數(shù)等。然后根據(jù)數(shù)據(jù)請求我們的php,完成我們的nginx+php的請求。
三、nginx配置錯誤導(dǎo)致的漏洞
注意:1.先下載好文件(漏洞文件下載地址)
? ? ? ? 2.進入到vulhub/nginx/insecure-configuration/這個目錄下
? ? ? ? 3.啟用docker加載環(huán)境(docker-compose up -d)
1.CRLF注入漏洞($uri解碼漏洞,換行符導(dǎo)致的注入漏洞)
(1)原理
????????在我們訪問http://example.com/abc時,我們的網(wǎng)頁會自動的跳轉(zhuǎn)到http://www.example.com/abc,但是在跳轉(zhuǎn)的過程之中需要保持我們的uri(也就是網(wǎng)址后面的部分,比如abc)不變,在nginx配置中有三種配置uri的方法$uri、$document_uri、$request_uri,在這里面$uri和$document_uri是解碼后的請求路徑,而$request_uri并沒進行解碼,正是因為uri解碼,我們可以利用%0d%0a(換行符),在我們的uri后面寫入我們惡意代碼,從而插入到我們的referer的頭部,從而修改我們的頭部信息。
(2)利用CRLF修改頭部信息
a.nginx運維的錯誤配置
?
b.注入一個set-cookie
curl -I?http://127.0.0.1:8080%0d%0aset-cookie:%20jiege666
?
?
(3)CRLF+Bottle HTTP造成的反射性xss漏洞
a.bottle搭建起來的環(huán)境,利用python運行下面代碼
import bottle from bottle import route, run, template, request, response @route('/') def index(): server = request.query.get('server') response.add_header('Server',server) return response if __name__ == '__main__': bottle.debug(True) run(host='localhost', port=8081)
?
b.在瀏覽器輸入以下的請求
http://localhost:8081/server=jiege%0d%0aX-XSS-Protection:0%0d%0a%0d%0a<script>alert(location.href)</script>
?
c.結(jié)果
?
d.原理
????????我們分析代碼,發(fā)現(xiàn)server接收我們的內(nèi)容,我們隨意賦值,加入一個%0d%0a(換行符)先給他換行,然后在他的referer頭部插入X-XSS-Protection:0,這個是瀏覽用來防止我們進行xss注入的,所以我們拆入頭部將他關(guān)閉,然后%0d%0a%0d%0a之所以是兩個換行符,是為了讓后面的內(nèi)容插入到我們的body也就是我們的html里面的,后面跟上我們<script>alert(location.href)</script>,就可以造成我們的xss反射性漏洞彈窗,從而獲取我們的路徑,也可以是其他惡意代碼。以上就完成我們的CRLF+Bottle HTTP的xss漏洞
e.防御CRLF+Bottle HTTP
????????第一種就是使用CSP禁止iframe跳轉(zhuǎn),第二種是將跳轉(zhuǎn)的url端口設(shè)置<80
(4)防御
????????我們可以在配置nginx的uri的跳轉(zhuǎn)的時候,配置成$request_uri這樣就可以防止瀏覽器自己解碼了,從而防御住了我們的CRLF(換行符漏洞)
2.目錄穿越漏洞
(1)原理
????????nginx在配置別名(alias)的時候忘記加了/,讓原本訪問某個目錄下的文件,攻擊者多加../就會返回到根目錄,從而造成了目錄穿越漏洞。
(2)漏洞復(fù)現(xiàn)
a.出現(xiàn)錯誤的配置文件
?
b.在瀏覽器輸入
http://192.168.191.129:8081/files../
?
c.結(jié)果
?
d.漏洞利用
????????我們可以進入到/usr/local/nginx/html/下,下載我們的config.php也就是我們的數(shù)據(jù)庫連接文件,獲得數(shù)據(jù)庫的用戶名和密碼,登陸數(shù)據(jù)庫阻止其他人的連接,或者獲取數(shù)據(jù)。
(3)防御
????????給location /files 和alias? /home的后面同時加/,或者都不加
?
?
3.Http add_header被覆蓋的問題
(1)原理
????????nginx在配置子模塊(server location if)的add_header的時候,將會覆蓋父模塊的add_header頭部,從而造成的隱患。
(2)CSP(Content-Security-Policy)
????????主要是為了防止XSS的存在,阻止入侵者插入存在第三方跳轉(zhuǎn)的鏈接
(3)漏洞的復(fù)現(xiàn)
a.后端出現(xiàn)配置錯誤的文件
????????我們不難發(fā)現(xiàn)在我們的子模塊中出現(xiàn)了add_header,而我們的父模塊是只允許我們內(nèi)部引用js,而我們的字模塊卻可以引用外部js,又因為我們的子模塊會覆蓋父模塊,這就導(dǎo)致了漏洞的存在。
?
b.我們正常訪問頁面test1,發(fā)現(xiàn)頁面存在csp只允許加載本地js
?
c.我們在訪問test2,發(fā)現(xiàn)csp被覆蓋了可以訪問外部js,我們利用這一點進行攻擊
?
d.在瀏覽器插入以下的請求
http://192.168.191.129:8082/test2#<img src=1 οnerrοr=alert(jiege666)>
?
e.我們查看頁面彈出彈窗就可以進行xss漏洞的注入
?
? ? ? ? ?一般情況下會出現(xiàn)一個彈窗的,可能由于我們的瀏覽器版本可能太高了,可以降低瀏覽器版本就可以實現(xiàn)彈窗了
(4)防御
????????在配置子模塊的時候,不要重復(fù)去添加父模塊所含有的add_header頭部
四、nginx文件名邏輯漏洞(Nginx 0.8.41 ~ 1.4.3 /1.5.0 ~ 1.5.7 )
1.原理
????????因為我們上傳了一個文件名為1.gif \0.php文件,首先我們的nginx解析到他是php結(jié)尾的文件,之后將他發(fā)送給我們的fastcgi,我們的fastcgi將這個數(shù)據(jù)解析完成后,又由于1.gif \0.php,\0也就是c語言的結(jié)束符的意思,之后我們的通過我們的\0將這個文件名截斷成我們的fastcgi認為他到1.gif就結(jié)束了,之后對上傳的文件進行檢查,發(fā)現(xiàn)他沒有以php結(jié)尾,就將這個文件上傳上去,然后我們的php-fpm.conf的安全后綴策略(security.limit_extensions = )是空的,之后他就會執(zhí)行我們上傳的1.gif \0.php文件。
?
2.文件名邏輯漏洞的復(fù)現(xiàn)
(1)首先創(chuàng)建一個文本,里面輸入php代碼
<?php phpinfo(); ?>
(2)修改文件后綴名為1.gif
(3)打開瀏覽器輸入
http://192.168.191.129:8080
(4)選擇我們1.gif文件
(5)打開抓包工具,之后上傳文件抓包
(6)找到文件名給他加成1.gifaa.php
(7)進入到hex也就是編碼數(shù)字的部分,修改文件名,將aa改成20和00,主要是讓他生成 \0(也就是一個空格和階段符號)。
(8)將修改的數(shù)據(jù)包放行提交到端
(9)查看我們上傳圖片的目錄
http://192.168.191.129:8080/uploadfiles/1.gif
?(10)打開抓包工具抓取該網(wǎng)頁,出現(xiàn)以下問題,是因為我們禁止了抓包工具抓取圖片,我們點擊開啟就可以了。
?(11)抓包
?(13)修改我們的文件名為1.gifaa.php
?(14)進入到hex下,修改我們的aa編碼為20和00,就是空格和截斷符,這里主要是為了和我們上傳的文件名一樣
?(15)將我們修改過的數(shù)據(jù)包發(fā)送就會看到我們注意的php頁面
?3.防御
????????我們在配置php-fpm.conf的安全后綴策略(security.limit_extensions = jpg gif)盡量不要設(shè)置為空,這樣就可以防御我們的nginx文件名邏輯漏洞。
五、nginx的解析漏洞
1.原理
????????我們在配置php.ini的時候,開啟了我們的自動修復(fù)路徑(cgi.fix_pathinfo=1),也就是我們訪問http://127.0.0.1/test.jpg/test.php,由于沒有test.php這個文件我們服務(wù)器會自動到上一個路徑,發(fā)現(xiàn)有test.jpg于是就自己執(zhí)行了這個文件,但是由于我們在配置php-fpm.conf的安全后綴策略(security.limit_extensions = jpg php )為空或者就只有jpg和php,我們的服務(wù)就會執(zhí)行jpg和php,我們的test.jpg里面就是我們的惡意的php代碼,之后通過解析為php文件就導(dǎo)致了我們執(zhí)行該文件,從而產(chǎn)生了我們的漏洞。
2.nginx解析漏洞復(fù)現(xiàn)
(1)先看我們php-fpm配置文件,發(fā)現(xiàn)我們的后綴名安全策略為空的
(2)訪問http://192.168.191.129/uplocalfiles/nginx.png
http://192.168.191.129/uplocalfiles/nginx.png
(3)在上面路徑后面隨意添加一個以.php結(jié)尾的文件
http://192.168.191.129/uplocalfiles/nginx.png/nginx.php
文章來源:http://www.zghlxwxcb.cn/news/detail-492846.html
?(4)觸發(fā)我們的php惡意代碼
文章來源地址http://www.zghlxwxcb.cn/news/detail-492846.html
(5)還有一種方法和上面nginx邏輯名漏洞一樣上傳php惡意文件,修改名稱,第二次直接訪問就會觸發(fā)
到了這里,關(guān)于安全中級2:nginx的中間件漏洞的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!