Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
言
今天給各位介紹下Tengine/Nginx服務(wù)器綁定多個(gè)域名多個(gè)網(wǎng)站的配置方法。
Tengine/Nginx配置文件
[root@localhost ~]# whereis nginx nginx: /usr/local/nginx [root@localhost ~]#
Nginx的配置文件
vim /usr/local/nginx/conf/nginx.conf #打開(kāi)nginx配置文件命令 你也可以使用你喜歡的編輯工具如vi emacs gedit
原文件
#以下為Nginx 配置文件nginx.conf默認(rèn)內(nèi)容,已加注解。 user www www-data; #以www會(huì)員和www-data會(huì)員組運(yùn)行nginx worker_processes 1; #最大進(jìn)程數(shù),一般設(shè)為cpu核心數(shù)量 如你是4核cpu 可以設(shè)為4 #error_log logs/error.log; #指定錯(cuò)誤日志文件路徑,默認(rèn)當(dāng)前配置文件的父級(jí)目錄logs下的error.log #error_log logs/error.log notice; #指定錯(cuò)誤日志文件路徑并指定為只記錄notice級(jí)別錯(cuò)誤 #error_log logs/error.log info; #指定錯(cuò)誤日志文件路徑并指定為只記錄info級(jí)別錯(cuò)誤 #pid logs/nginx.pid; ##記錄nginx運(yùn)行時(shí)的進(jìn)程ID events { worker_connections 1024; #允許的最大連接數(shù)即tcp連接數(shù) } # load modules compiled as Dynamic Shared Object (DSO) # 動(dòng)態(tài)模塊加載(DSO)支持。加入一個(gè)模塊不再需要重新編譯整個(gè)Tengine 這個(gè)是Tengine特有的 #dso { # load ngx_http_fastcgi_module.so; #fastcgi模塊 # load ngx_http_rewrite_module.so; #URL重寫(xiě)模塊 #} http { include mime.types; #設(shè)定mime類(lèi)型,類(lèi)型由conf目錄下mime.type文件定義 default_type application/octet-stream; #默認(rèn)為 任意的二進(jìn)制數(shù)據(jù) ## 可配置日志格式: $remote_addr訪(fǎng)客ip ## $remote_user已經(jīng)經(jīng)過(guò)Auth Basic Module驗(yàn)證的用戶(hù)名 ## $time_local訪(fǎng)問(wèn)時(shí)間 ## $request請(qǐng)求的url ## $body_bytes_sent 傳送頁(yè)面的字節(jié)數(shù) $http_referer訪(fǎng)問(wèn)來(lái)源 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; #訪(fǎng)問(wèn)記錄日志 sendfile on; #開(kāi)啟高效文件傳輸模式 注意:如果圖片顯示不正常把這個(gè)改成off。 #tcp_nopush on; #防止網(wǎng)絡(luò)阻塞 #keepalive_timeout 0; keepalive_timeout 65; #長(zhǎng)連接超時(shí)時(shí)間,單位是秒 #gzip on; #開(kāi)啟gzip壓縮 server {#虛擬主機(jī)的配置 listen 80; #監(jiān)聽(tīng)80端口 server_name localhost; #綁定域名可以有多個(gè),用空格隔開(kāi) #charset koi8-r; #字符編碼 可設(shè)為 utf-8 #access_log logs/host.access.log main; #訪(fǎng)問(wèn)記錄日志 location / { ##網(wǎng)站根目錄設(shè)置在這里 root html; #配置文件父級(jí)html目錄,可以設(shè)到其它目錄如/home/www目錄,注意目錄的所有者和權(quán)限 本文開(kāi)頭處user的信息 index index.html index.htm; #默認(rèn)索引文件,從左到右,如:index.php index.html index.htm 空格分開(kāi) } #error_page 404 /404.html; #指定404錯(cuò)誤文件位置 root指定目錄下的404.html 以下50x文件同理 # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; ##服務(wù)器50x得的錯(cuò)誤都跳轉(zhuǎn)到html/50x.html文件 location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # 配置處理php文件,需要安裝PHP #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; ##禁止使用.htaccess文件 #} } # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
修改后
###以下為修改過(guò)的nginx.conf配置文件,已加注解。 user www www-data; #以www會(huì)員和www-data會(huì)員組運(yùn)行nginx worker_processes 1; #最大進(jìn)程數(shù),一般設(shè)為cpu核心數(shù)量 如你是4核cpu 可以設(shè)為4 error_log logs/error.log; #指定錯(cuò)誤日志文件路徑,默認(rèn)當(dāng)前配置文件的父級(jí)目錄logs下的error.log #error_log logs/error.log notice; #指定錯(cuò)誤日志文件路徑并指定為只記錄notice級(jí)別錯(cuò)誤 #error_log logs/error.log info; #指定錯(cuò)誤日志文件路徑并指定為只記錄info級(jí)別錯(cuò)誤 pid logs/nginx.pid; ##記錄nginx運(yùn)行時(shí)的進(jìn)程ID events { use epoll; #新加 提高nginx的性能,限Linux下使用 worker_connections 1024; #允許的最大連接數(shù)即tcp連接數(shù) } # load modules compiled as Dynamic Shared Object (DSO) # 動(dòng)態(tài)模塊加載(DSO)支持。加入一個(gè)模塊不再需要重新編譯整個(gè)Tengine 這個(gè)是Tengine特有的 #dso { # load ngx_http_fastcgi_module.so; #fastcgi模塊 # load ngx_http_rewrite_module.so; #URL重寫(xiě)模塊 #} http { include mime.types; #設(shè)定mime類(lèi)型,類(lèi)型由conf目錄下mime.type文件定義 default_type application/octet-stream; #默認(rèn)為 任意的二進(jìn)制數(shù)據(jù) ##可配置日志格式: $remote_addr訪(fǎng)客ip ## $remote_user已經(jīng)經(jīng)過(guò)Auth Basic Module驗(yàn)證的用戶(hù)名 ## $time_local訪(fǎng)問(wèn)時(shí)間 ## $request請(qǐng)求的url ## $body_bytes_sent 傳送頁(yè)面的字節(jié)數(shù) ## $http_referer訪(fǎng)問(wèn)來(lái)源 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; #訪(fǎng)問(wèn)記錄日志 sendfile on; #開(kāi)啟高效文件傳輸模式 注意:如果圖片顯示不正常把這個(gè)改成off。 #tcp_nopush on; #防止網(wǎng)絡(luò)阻塞 #keepalive_timeout 0; keepalive_timeout 65; #長(zhǎng)連接超時(shí)時(shí)間,單位是秒 gzip on; #開(kāi)啟gzip壓縮 ## 新加 include 項(xiàng)引入/usr/local/nginx/vhosts/目錄下所有.conf結(jié)尾的虛擬機(jī)配置文件 include /usr/local/nginx/vhosts/*.conf }
建立虛擬機(jī)配置目錄
mkdir /usr/local/nginx/vhosts/
新建網(wǎng)站配置文件
vim /usr/local/nginx/vhosts/test.conf ##www.test.my 的配置文件 server { #虛擬主機(jī)的配置 listen 80; #監(jiān)聽(tīng)80端口 server_name www.test.my www.test.my; #綁定域名可以有多個(gè),用空格隔開(kāi) #charset koi8-r; #字符編碼 可設(shè)為 utf-8 charset utf-8; #access_log logs/host.access.log main; #訪(fǎng)問(wèn)記錄日志 location / { ##網(wǎng)站根目錄設(shè)置在這里 root html; #配置文件父級(jí)html目錄,可以設(shè)到其它目錄如/home/www目錄,注意目錄的所有者和權(quán)限 本文開(kāi)頭處user的信息 index index.html index.htm; #默認(rèn)索引文件,從左到右,如:index.php index.html index.htm 空格分開(kāi) } #error_page 404 /404.html; #指定404錯(cuò)誤文件位置 root指定目錄下的404.html 以下50x文件同理 # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; ##服務(wù)器50x得的錯(cuò)誤都跳轉(zhuǎn)到html/50x.html文件 location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # 配置處理php文件,需要安裝PHP #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; ##禁止使用.htaccess文件 #} }
配置多個(gè)網(wǎng)站
#如再配置一個(gè)域名為 yuntheme.com站點(diǎn)的配置文件 vim /usr/local/nginx/vhosts/yuntheme.conf #復(fù)制剛才的test.conf的內(nèi)容,只要像下面修改就行了 location / { ##網(wǎng)站根目錄設(shè)置在這里 root /usr/local/nginx/html/yuntheme; #修改此處 index index.html index.htm; }
完成配置,重啟Nginx
累點(diǎn)滴,匯成江海。咱們從最最基礎(chǔ)的PHP知識(shí)開(kāi)始學(xué)習(xí),一步一個(gè)腳印的開(kāi)啟PHP的學(xué)習(xí)旅途吧。
請(qǐng)點(diǎn)擊右上角“關(guān)注”按鈕關(guān)注我們喲:跟著木辛老師學(xué)習(xí)PHP編程知識(shí),變身快樂(lè)的編程達(dá)人吧~
同學(xué)們好呀!木辛老師又來(lái)了。
咱們?cè)陂_(kāi)始PHP的學(xué)習(xí)之前,需要先準(zhǔn)備一個(gè)可以提供PHP服務(wù)的Web服務(wù)器。我們就復(fù)用木辛老師專(zhuān)欄中的一個(gè)教程,使用Homestead本地開(kāi)發(fā)環(huán)境進(jìn)行學(xué)習(xí)唄。
傳送門(mén):《Laravel第一課:搭建Laravel開(kāi)發(fā)環(huán)境》
也可以關(guān)注木辛老師的Laravel專(zhuān)欄喲:
大家配置好本地開(kāi)發(fā)環(huán)境以后,還需要稍微設(shè)置一下,針對(duì)這個(gè)項(xiàng)目,在Homestead配置文件中作如下設(shè)置,
添加指向當(dāng)前項(xiàng)目根目錄的配置:
sites: - map: learning_php.test to: /Code/zyoo/learning_php to: /Code/zyoo/learning_php
另外還需要在本機(jī)hosts文件中添加一個(gè)域名指向:
sudo vim /etc/hosts
并添加如下記錄:
192.168.10.10 learning_php.test
最后,添加一個(gè)測(cè)試文件:
php代碼
然后,打開(kāi)瀏覽器,訪(fǎng)問(wèn)域名查看頁(yè)面結(jié)果
執(zhí)行效果
大家可以看到,我們已經(jīng)可以成功的訪(fǎng)問(wèn)到測(cè)試用的PHP文件了。
好了,萬(wàn)事俱備,只需要學(xué)習(xí)了。那么,咱們開(kāi)始吧~
幾乎絕大部分服務(wù)器端的腳本語(yǔ)言最初設(shè)計(jì)的應(yīng)用場(chǎng)景之一就是處理HTML表單。木辛老師要翻出家底,將自己最心愛(ài)的在線(xiàn)圖書(shū)商城,用來(lái)作為學(xué)習(xí)PHP基礎(chǔ)知識(shí)的場(chǎng)景吧。
通過(guò)這個(gè)表單頁(yè)面,我們可以知道顧客訂購(gòu)的商品,訂單的金額以及其他一些附屬信息。HTML代碼請(qǐng)看下方:
<html> <head> <title>木辛老師的PHP基礎(chǔ)入門(mén)教程</title> </head> <body> <form action="processorder.php" method="POST"> <table style="border: 0px;"> <tr style="background: #cccccc"> <td style="width: 150px;text-align:center;">圖書(shū)名稱(chēng)</td> <td style="width: 50px;text-align:center;">數(shù)量</td> </tr> <tr> <td>PHP入門(mén)指南</td> <td><input type="text" name=“book_name_01" size="3" maxlength="3"/></td> </tr> <tr> <td>PHP和MySQL開(kāi)發(fā)</td> <td><input type="text" name="book_name_02" size="3" maxlength="3"/></td> </tr> <tr> <td>Laravel入門(mén)</td> <td><input type="text" name="book_name_03" size="3" maxlength="3"/></td> </tr> <tr> <td colspan="2" style="text-align: center;"> <input type="submit" value="提交訂單"/> </td> </tr> </table> </form> </body> </html>
咱么直接通過(guò)瀏覽器訪(fǎng)問(wèn)這個(gè)HTML頁(yè)面,看看效果:
頁(yè)面顯示
哈,簡(jiǎn)單的頁(yè)面,我們已經(jīng)開(kāi)啟Web開(kāi)發(fā)神秘旅程了。繼續(xù)加油!
大家可能注意到了一個(gè)細(xì)節(jié):在html代碼的form表單部分,action屬性我們指向了一個(gè)php腳本:
<form action="processorder.php" method="POST”>
具體的PHP腳本的學(xué)習(xí)我們很快就能看到。這里只是稍微提一下,這個(gè)action屬性值就是用戶(hù)點(diǎn)擊“提交訂單”按鈕時(shí)將要請(qǐng)求的URL。
用戶(hù)在表單中輸入的數(shù)據(jù),會(huì)以POST的方式,發(fā)送給URL指向的PHP文件進(jìn)行處理。
那如何處理這個(gè)表單呢?又如何讓PHP代碼起作用的?
要處理這個(gè)表單,我們需要?jiǎng)?chuàng)建一個(gè)php文件,它的名字需要和form中action屬性的值保持一致。
那么,我們就創(chuàng)建一個(gè)名字叫做processorder.php的文件吧。
代碼可以先這么寫(xiě),看看是否能起作用哈:
<html> <head> <title>訂單處理結(jié)果</title> </head> <body> <h1> 木辛老師的在線(xiàn)圖書(shū)館</h1> <h2> 訂單處理結(jié)果通知</h2> <?php echo '<p>訂單已處理完成</p>'; // 這里是PHP的代碼 ?> </body> </html>
保持文件,并刷新頁(yè)面。這個(gè)時(shí)候我們點(diǎn)擊“提交訂單”按鈕,效果如下:
php執(zhí)行結(jié)果
大家可以看到,紅框部分就是通過(guò)PHP代碼輸出的結(jié)果。這樣,我們就實(shí)現(xiàn)了通過(guò)Web方式執(zhí)行了PHP代碼的需求,這么一看PHP還是非常簡(jiǎn)單的吧。
我們順便在看看這個(gè)頁(yè)面的源代碼吧,看一下PHP代碼如何在HTML頁(yè)面中完成任務(wù)的吧:
源代碼
通過(guò)頁(yè)面源碼,我們發(fā)現(xiàn)剛才寫(xiě)的PHP代碼已經(jīng)不見(jiàn)了,取而代之的是
<p>訂單已處理完成</p>
這是怎么回事呢?
這是因?yàn)镻HP解釋器在腳本運(yùn)行的時(shí)候,將該腳本的輸出替代了腳本自身的代碼,通過(guò)這種方式,就可以生成可以在任何瀏覽器上運(yùn)行的HTML頁(yè)面了。也就是說(shuō),瀏覽器是不需要學(xué)會(huì)PHP的。
通過(guò)這段代碼,我們可以學(xué)習(xí)一些PHP的基礎(chǔ)知識(shí):
第一種情況:在HTML中混寫(xiě)PHP和HTML代碼,需要為php添加標(biāo)記。PHP代碼會(huì)以“<?php”作為開(kāi)始,以“?>”作為結(jié)束。這些符號(hào)就叫做PHP標(biāo)記,它們主要用來(lái)告訴服務(wù)器PHP代碼的開(kāi)始和截止,在這兩個(gè)起止符號(hào)之間的任何代碼,服務(wù)器都會(huì)以PHP語(yǔ)法來(lái)解析。
另一種情況:之后,我們寫(xiě)純PHP的時(shí)候,每個(gè)文件也需要添加PHP標(biāo)記。不過(guò)呢,結(jié)束標(biāo)記可以省略,這也是很大一部分PHPer默認(rèn)遵守的規(guī)則。
在PHP的開(kāi)始和截止標(biāo)記之間,就是PHP語(yǔ)句了,通過(guò)這些內(nèi)容可以告訴PHP解釋器應(yīng)該進(jìn)行如何的操作,在我們這個(gè)例子里,通過(guò):
echo '<p>訂單已處理完成</p>’;
使用echo語(yǔ)句完成了一個(gè)非常簡(jiǎn)單的操作,僅是將echo后邊的字符串原樣打印到瀏覽器中。這里需要特別注意的一點(diǎn)就是每個(gè)PHP語(yǔ)句后邊都需要添加英文的分號(hào)作為語(yǔ)句的結(jié)束符,否則會(huì)出現(xiàn)錯(cuò)誤,但是在這個(gè)html頁(yè)面中,因?yàn)橹挥幸痪浯a,忽略掉分號(hào)也是不會(huì)報(bào)錯(cuò)的。
但是還是強(qiáng)烈建議大家養(yǎng)成習(xí)慣:每句PHP代碼結(jié)束都要以分號(hào)結(jié)尾喲!
一般情況下,為了讓代碼更加清晰和整潔,在編碼的過(guò)程中會(huì)添加一些空格,這些空格包括:回車(chē)換行、空格、制表符等都被認(rèn)為是空格。
當(dāng)然了,瀏覽器并不會(huì)在意你是否輸入了空格,同樣的PHP服務(wù)器端解析器也會(huì)忽略這些,這些空格僅是給編寫(xiě)代碼的人看的。
但是,木辛老師還是再次強(qiáng)烈建議,在代碼的適當(dāng)位置添加空格或者空行,這樣做可以很有效的提升代碼的可閱讀性,方便后期的維護(hù)工作。
最后在講講注釋?zhuān)碚撋显诰幊讨谐霈F(xiàn)頻率非常高的一個(gè)知識(shí)點(diǎn)。
為什么說(shuō)理論上呢,因?yàn)檫@么重要的一個(gè)要點(diǎn),在實(shí)際開(kāi)發(fā)中很容易被廣大開(kāi)發(fā)者忽略呢!
由于種種原因吧,開(kāi)發(fā)者很不習(xí)慣在開(kāi)發(fā)過(guò)程中寫(xiě)非常詳盡的注釋?zhuān)矣袝r(shí)候在Git提交時(shí)也是草草的一筆帶過(guò)。這樣做的后果就是,若干時(shí)間后,當(dāng)你再次拿到這段代碼,可能會(huì)花費(fèi)更多的時(shí)間梳理它。
所以,善于寫(xiě)注釋?zhuān)彩翘岣呱a(chǎn)效率的一種有效手段。
PHP解釋器同樣會(huì)在執(zhí)行的時(shí)候忽略掉注釋?zhuān)簿褪钦f(shuō)就好比像空格一樣,PHP解析器會(huì)跳過(guò)注釋?zhuān)回?fù)責(zé)執(zhí)行PHP代碼!
PHP腳本中的注釋比較豐富,有很多類(lèi)似C語(yǔ)言的風(fēng)格,比如:
多行注釋?zhuān)?/p>
/* 這是 一個(gè) 多行 注釋 /*
可以看出來(lái),多行注釋以 /*開(kāi)始,以*/結(jié)束。同樣的和C語(yǔ)言是一樣的,多行注釋是不能嵌套的。
當(dāng)然了,除了多行注釋之外,也支持單行注釋?zhuān)?/p>
echo '<p>訂單已處理完成</p>'; // 這里是PHP的代碼
或者這種:
echo '<p>訂單已處理完成</p>’; #這里是PHP的代碼
不論采取哪種風(fēng)格的注釋?zhuān)谧⑨尫?hào)之后的所有內(nèi)容,PHP解釋器都會(huì)認(rèn)識(shí)不需要處理的,這一點(diǎn)一定要注意呀!
好了,今天的課程咱就先講到這里。
小朋友們不要忘記關(guān)注我們喲 ,下期課程更精彩,請(qǐng)大家一起期待吧~
快樂(lè)編程,快樂(lè)成長(zhǎng),拜拜!
習(xí)網(wǎng)絡(luò)攻防技術(shù)一定離不開(kāi)靶場(chǎng)練習(xí),Dvwa是一個(gè)非常經(jīng)典的靶場(chǎng),涵蓋csrf、sql注入、文件包含等漏洞環(huán)境,并有Low、Medium、High、Impossible四種不同的安全等級(jí),適合新手練習(xí),通過(guò)該靶場(chǎng)可以由淺入深的學(xué)習(xí)漏洞原理和代碼審計(jì)。
本文是i春秋論壇版主「Adian大蟈蟈」表哥直接在Dvwa high進(jìn)行測(cè)試的完整攻略,對(duì)靶場(chǎng)練習(xí)是一個(gè)非常好的指導(dǎo),感興趣的小伙伴快來(lái)學(xué)習(xí)吧。
DVWA共有14個(gè)漏洞選項(xiàng),我們逐一來(lái)看:
Brute Force
我們先來(lái)看看high.php
<?phpif( isset( $_GET[ 'Login' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Sanitise username input $user = $_GET[ 'username' ]; $user = stripslashes( $user ); $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Sanitise password input $pass = $_GET[ 'password' ]; $pass = stripslashes( $pass ); $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass = md5( $pass ); // Check database $query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful $html .= "<p>Welcome to the password protected area {$user}</p>"; $html .= "<img src=\"{$avatar}\" />"; } else { // Login failed sleep( rand( 0, 3 ) ); $html .= "<pre><br />Username and/or password incorrect.</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}// Generate Anti-CSRF tokengenerateSessionToken();?>
High級(jí)別的猜解加了一個(gè)防止CSRF的驗(yàn)證token,使用了stripslashes( )等函數(shù)來(lái)轉(zhuǎn)義或過(guò)濾,雖然加大了猜解的難度,但是還是可以猜解的。
我們先正常抓包:
得到完整數(shù)據(jù)包之后,我們把需要猜解的參數(shù)范圍選中user_token和password,選擇Pitchfork測(cè)試類(lèi)型。
找到Redirections選中always允許重定向:
最后在Options中找到Grep-Extract模塊,點(diǎn)擊Add,并設(shè)置篩選條件,得到user_token。
然后設(shè)置payload,帶token參數(shù)的paylaod直接把token粘貼進(jìn)去就可以了,其他照常。
然后開(kāi)始猜解,關(guān)于其他文章提到的線(xiàn)程設(shè)置為1,新版本的burpsuite設(shè)置了Pitchfork之后,就默認(rèn)為1不可更改,所以這個(gè)問(wèn)題不再敘述了。
Command Injection(命令執(zhí)行)
我們先簡(jiǎn)單的試一下:
可見(jiàn)$被過(guò)濾了,在看一下代碼:
<?phpif( isset( $_POST[ 'Submit' ] ) ) { // Get input $target = trim($_REQUEST[ 'ip' ]); // Set blacklist $substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '', ); // Remove any of the charactars in the array (blacklist). $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); // Determine OS and execute the ping command. if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target ); } else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target ); } // Feedback for the end user $html .= "<pre>{$cmd}</pre>";}?>
代碼可以看見(jiàn)將$;()都進(jìn)行了轉(zhuǎn)換,轉(zhuǎn)成了空字符串,這也就導(dǎo)致了我們輸入的這些能同時(shí)執(zhí)行其他命令的符號(hào)都無(wú)法使用了。
但是仔細(xì)看過(guò)濾 "| ",如果我們把后面的空格刪去直接執(zhí)行,也是可以執(zhí)行的。
CSRF
還是看源代碼high.php
<?phpif( isset( $_GET[ 'Change' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ]; // Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Feedback for the user $html .= "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching $html .= "<pre>Passwords did not match.</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}// Generate Anti-CSRF tokengenerateSessionToken();?>
由上面的代碼可見(jiàn),High級(jí)別的代碼加入了Anti-CSRF token機(jī)制,用戶(hù)每次訪(fǎng)問(wèn)改密碼時(shí),服務(wù)器會(huì)返回一個(gè)隨機(jī)的token,提交的參數(shù)帶有正確的token才能執(zhí)行,我們可以利用burp的插件CSRFTokenTracker繞過(guò)token驗(yàn)證,這里我借用一下其他人的圖片。
裝好之后,設(shè)置好名稱(chēng)和內(nèi)容就可以直接去repeater里面測(cè)試了,每次的token會(huì)自動(dòng)刷新。
File Inclusion(文件包含)
<?php// The page we wish to display$file = $_GET[ 'page' ];// Input validationif( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit;}?
這次的代碼量很小,大概解讀一下:
if( !fnmatch( "file*", $file ) && $file != "include.php" )
如果沒(méi)有這個(gè)文件或者這個(gè)文件不是include.php,那么就不會(huì)執(zhí)行,但是我們可以使用file協(xié)議繞過(guò)。
File Upload(文件上傳)
先看一下high.php:
<?phpif( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // File information $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; // Is it an image? if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) && ( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) { // Can we move the file to the upload folder? if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { // No $html .= '<pre>Your image was not uploaded.</pre>'; } else { // Yes! $html .= "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { // Invalid file $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; }}?>
可以看到getimagesize( )函數(shù)來(lái)驗(yàn)證有沒(méi)有相關(guān)的文件頭等等,所以直接改格式不行,需要一個(gè)圖片馬兒,也會(huì)判斷最后的'.'后的內(nèi)容必須是jpg,jpeg,png三者之一。
圖片馬的制作很簡(jiǎn)單,打開(kāi)cmd:
copy shell.php/b+test.png/a hack.png
簡(jiǎn)單的用記事本打開(kāi)圖片,在里面加入一句話(huà)也可以,然后我們用00截?cái)嗟姆绞絹?lái)繞過(guò)上傳。
Insecure CAPTCHA(不安全驗(yàn)證碼)
Insecure CAPTCHA,意思是不安全的驗(yàn)證碼,CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart(全自動(dòng)區(qū)分計(jì)算機(jī)和人類(lèi)的圖靈測(cè)試)的簡(jiǎn)稱(chēng)。
recaptcha_check_answer($privkey,$remoteip, $challenge,$response)
看一下代碼:
<?phpif( isset( $_POST[ 'Change' ] ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check CAPTCHA from 3rd party $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ], $_POST['g-recaptcha-response'] ); if ( $resp || ( $_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3' && $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA' ) ){ // CAPTCHA was correct. Do both new passwords match? if ($pass_new == $pass_conf) { $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Feedback for user $html .= "<pre>Password Changed.</pre>"; } else { // Ops. Password mismatch $html .= "<pre>Both passwords must match.</pre>"; $hide_form = false; } } else { // What happens when the CAPTCHA was entered incorrectly $html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>"; $hide_form = false; return; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}// Generate Anti-CSRF tokengenerateSessionToken();?>
可以判斷出當(dāng)$resp == False以及g-recaptcha-response != hidd3n_valu3或者HTTP_USER_AGENT != reCAPTCHA的時(shí)候,驗(yàn)證碼為錯(cuò)誤,$resp的值我們控制不了,是由recaptcha_check_answer( )決定的,所以我從g-recaptcha-response和HTTP_USER_AGENT入手。
我們更改HTTP_USER_AGENT的值為reCAPTCHA
添加g-recaptcha-response的值為hidd3n_valu3
就ok了
SQL Injection(SQL注入)
<?phpif( isset( $_SESSION [ 'id' ] ) ) { // Get input $id = $_SESSION[ 'id' ]; // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user $html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }?>
和文件包含一樣的簡(jiǎn)潔,前端比low級(jí)多了一個(gè)彈出框:
由于多了一個(gè)頁(yè)面,所以我們不能直接sqlmap-u這樣的語(yǔ)法了,而且還有cookie和session的限制(可以填進(jìn)去,看看usage)。
所以我們要用到--second-order,抓個(gè)包,將內(nèi)容都放到1.txt中然后執(zhí)行。
sqlmap -r 1.txt -p id --second-order "http://192.168.242.1/dvw/vulnerabilities/sqli/" --level 2
SQL Injection (Blind)
high.php
<?phpif( isset( $_COOKIE[ 'id' ] ) ) { // Get input $id = $_COOKIE[ 'id' ]; // Check database $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $getid ); // Removed 'or die' to suppress mysql errors // Get results $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors if( $num > 0 ) { // Feedback for end user $html .= '<pre>User ID exists in the database.</pre>'; } else { // Might sleep a random amount if( rand( 0, 5 ) == 3 ) { sleep( rand( 2, 4 ) ); } // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user $html .= '<pre>User ID is MISSING from the database.</pre>'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}?>
抓包將cookie中參數(shù)id改為1’ and length(database( ))=4 #,顯示存在,說(shuō)明數(shù)據(jù)庫(kù)名的長(zhǎng)度為4個(gè)字符;
抓包將cookie中參數(shù)id改為1’ and length(substr(( select table_name from information_schema.tables where table_schema=database( ) limit 0,1),1))=9 #,顯示存在,說(shuō)明數(shù)據(jù)中的第一個(gè)表名長(zhǎng)度為9個(gè)字符;
抓包將cookie中參數(shù)id改為1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #,(0×7573657273 為users的16進(jìn)制),顯示存在,說(shuō)明uers表有8個(gè)字段。
Weak Session IDs
high.php
<?php$html = "";if ($_SERVER['REQUEST_METHOD'] == "POST") { if (!isset ($_SESSION['last_session_id_high'])) { $_SESSION['last_session_id_high'] = 0; } $_SESSION['last_session_id_high']++; $cookie_value = md5($_SESSION['last_session_id_high']); setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);}?>
看到$cookie_value就是md5加密了last_session_id_high,last_session_id_high這個(gè)值初始為0,逐個(gè)+1然后md5加密,所以這個(gè)cookie校驗(yàn)對(duì)我們無(wú)效,構(gòu)造payload使用火狐提交。
XSS (DOM)
high.php
<?php// Is there any input?if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) { # White list the allowable languages switch ($_GET['default']) { case "French": case "English": case "German": case "Spanish": # ok break; default: header ("location: ?default=English"); exit; }}?>
提交后url為:
http://192.168.159.129/vulnerabilities/xss_d/?default=English
<option value=''>English</option>
我們?cè)诶锩娌迦隞avascipt語(yǔ)句:
<option value=''>English #<script>alert(/xss/)</script></option>
這樣兩個(gè)標(biāo)簽都閉合,我們來(lái)看看效果:
XSS (Reflected)
high.php
<?phpheader ("X-XSS-Protection: 0");// Is there any input?if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Get input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); // Feedback for end user $html .= "<pre>Hello ${name}</pre>";}?>
居然直接正則把<script>過(guò)濾了,雙寫(xiě)大小寫(xiě)繞過(guò)都不可以,但是我們還可以插別的標(biāo)簽,比如img比如body。
<img src=1.jpg>
我們可以看見(jiàn),這個(gè)標(biāo)簽執(zhí)行了。
XSS (Stored)
high.php
<?phpif( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = strip_tags( addslashes( $message ) ); $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $message = htmlspecialchars( $message ); // Sanitize name input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close();}?>
和上面一樣,正則過(guò)濾<script>,還是和上面一樣,用img標(biāo)簽。
<img src=1.jpg onerror=alert(/adian/)>
Burpsuite抓包改參數(shù):
彈出
CSP Bypass
Content Security Policy(CSP),內(nèi)容(網(wǎng)頁(yè))安全策略,為了緩解潛在的跨站腳本問(wèn)題(XSS攻擊),瀏覽器的擴(kuò)展程序系統(tǒng)引入了內(nèi)容安全策略(CSP)這個(gè)概念。具體內(nèi)容可以參見(jiàn)《Content Security Policy 入門(mén)教程》,類(lèi)似白名單的一種機(jī)制。
<?php$headerCSP = "Content-Security-Policy: script-src 'self';";header($headerCSP);?><?phpif (isset ($_POST['include'])) {$page[ 'body' ] .= " " . $_POST['include'] . "";}$page[ 'body' ] .= '<form name="csp" method="POST"> <p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p> <p>1+2+3+4+5=<span id="answer"></span></p> <input type="button" id="solve" value="Solve the sum" /></form><script src="source/high.js"></script>';
high.js
function clickButton() { var s = document.createElement("script"); s.src = "source/jsonp.php?callback=solveSum"; document.body.appendChild(s);}function solveSum(obj) { if ("answer" in obj) { document.getElementById("answer").innerHTML = obj['answer']; }}var solve_button = document.getElementById ("solve");if (solve_button) { solve_button.addEventListener("click", function() { clickButton(); });}
在網(wǎng)上找到了一段代碼:
if (isset ($_POST['include'])) {$page[ 'body' ] .= " " . $_POST['include'] . "";}
來(lái)接收參數(shù),然后再構(gòu)造payload就可以了。
Javascript
high.php
<?php$page[ 'body' ] .= <<<EOF<script src="/vulnerabilities/javascript/source/high.js"></script>EOF;?>
生成token的步驟總結(jié):
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。