源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php
hint("will exec the arg specified in the GET parameter \"cmd\"");
?>
<form action="/CMD-1/index.php" method="GET">
<input type="text" name="cmd">
</form>
<?php
system($_GET["cmd"]);
?>
即直接執行get請求從參數cmd得到的信息。
解決方法
在進入該站點時傳入參數cmd為我們想要的執行的命令。即?cmd=whoami
得到如下結果
CMD-2
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php hint("will exec the arg specified in the POST parameter \"cmd\""); ?>
<form action="/CMD-2/index.php" method="POST">
<input type="text" name="cmd">
</form>
<?php
system($_POST["cmd"]);
?>
與cmd-1略微有不同也就是接受post請求來的變量。
解決方法
借用hackbar來傳遞參數,勾選Post data
用POST傳參cmd=whoami
執行命令
點擊Execute執行
CMD-3
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php
hint("will exec 'whois' with the arg specified in the GET parameter \"domain\"");
?>
<form action="/CMD-3/index.php" method="GET">
Whois: <input type="text" name="domain">
</form>
<pre>
<?php
system("/usr/bin/whois " . $_GET["domain"]);
?>
</pre>
注意,由於我們是在Windows的環境下做的實驗,所以這里的源代碼要更/usr/bin/whois
顯然時Linux中的命令執行路徑。這里我們直接將其更換為nslookup
、ping
和其他后面可以帶參數的 windows環境下可執行的系統命令都可以,由system()函數調起即可執行,注意后面有空格,因為后面跟的時命令的選項。
tip:
-
whois命令是Linux/Unix環境下的命令,按字面意思就是問“他是誰?”,通過對域名的檢索, 可以反饋回域名的注冊信息,包括持有人,管理資料以及技術聯絡資料, 也包括該域名的域名服務器。
-
nslookup命令用於查詢DNS的記錄,查看域名解析是否正常,在網絡故障的時候用來診斷網絡問題。域名解析用。
回到上面的源代碼,其含義就是執行一個系統里並帶上用GET方法得到的參數。
解決原理
-
cmd1|cmd2:無論cmd1是否為真,cmd2都會被執行
-
cmd1||cmd2:如果cmd1為假,則執行cmd2;
-
cmd1&&cmd2:如果cmd1為真才執行cmd1。
解決方法流程
直接url傳入參數domain=www.baidu.com|whoami
得到我們想要執行的命令
CMD-4
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php hint("will exec 'whois' with the arg specified in the POST parameter \"domain\""); ?>
<form action="/CMD-4/index.php" method="POST">
<input type="text" name="domain">
</form>
<pre>
<?php
system("whois " . $_POST["domain"]);
?>
</pre>
這里也要改一下源代碼,因為windows沒有whois這條命令。改為ping吧這次。
解決方法流程
與cmd3差不多,只是用post傳參
CMD-5
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php hint("not everything you need to inject is in a text input field ..."); ?>
<form action="/CMD-5/index.php" method="GET">
<input type="text" name="domain">
<input type="hidden" name="server" value="whois.publicinterestregistry.net">
</form>
<pre>
<?php
if (preg_match('/^[-a-z0-9]+\.a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|t[cdfghjklmnoprtvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]|biz|cat|com|edu|gov|int|mil|net|org|pro|tel|aero|arpa|asia|coop|info|jobs|mobi|name|museum|travel|arpa|xn--[a-z0-9]+$/', strtolower($_GET["domain"])))
{ system("whois -h " . $_GET["server"] . " " . $_GET["domain"]); }
else
{echo "malformed domain name";}
?>
</pre>
preg_match 函數用於執行一個正則表達式匹配。搜索 subject 與 pattern 給定的正則表達式的一個匹配。返回 pattern 的匹配次數。 它的值將是 0 次(不匹配)或 1 次,因為 preg_match() 在第一次匹配后 將會停止搜索。preg_match_all() 不同於此,它會一直搜索subject 直到到達結尾。 如果發生錯誤preg_match()返回 FALSE。
preg_match函數對用get方法請求的domain中的字符串進行判斷是否在匹配名單中,匹配成功才會執行命令whois,否則會提示域名不完整。該匹配名單的要求域名是完全合法合規的才可以執行命令
system("whois -h " . GET["server"] . " " . $GET["domain"]);發現不僅接受domian參數還接受server,而server是沒有過濾規則的,利用這一點可以繞過該過濾機制。
解決方法流程
記得源碼里的whois命令要修改,像上面一樣。
所以server里帶上我們想要執行的命令
?server=127.0.0.1|whoami||&domain=baidu.com
?domain=baidu.com&server=127.0.0.1|whoami||
這樣構造出的命令語句是:whois -h 127.0.0.1|whoami|| baidu.com,后面的baidu.com也就忽略了
CMD-6
源代碼審計
這里就不貼源碼了,就是把GET請求換為了POST請求
解決方法流程
記得不要忘記改源代碼中的函數名不然你會找半天錯卻不知道錯在哪。
用POST傳參。
在進行下面的實驗之前,如果文件目錄下沒有phpinfo這類php文件的話,最好將phpinfo()寫入到一個php文件中,方便我們驗證結果
LFI-1
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from https://pentesterlab.com/exercises/php_include_and_post_exploitation/course -->
<?php hint("will include the arg specified in the GET parameter \"page\""); ?>
<form action="/LFI-1/index.php" method="GET">
<input type="text" name="page">
</form>
<?php
include($_GET["page"]);
?>
出現了include()文件包含函數,並且使用GET方法接受參數。
解決方法流程
直接在url中傳參。我們訪問在上一級結構目錄中的phpinfo.php文件驗證結果。
?page=../phpinfo.php //../表示上一級目錄
當然想試一下其他文件也可以。當然得是文件系統里有的
LFI-2
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ -->
<?php hint("will include the arg specified in the GET parameter \"library\", appends .php to end, escape with NULL byte %00"); ?>
<form action="/LFI-2/index.php" method="GET">
<input type="text" name="library">
</form>
<?php
include("includes/".$_GET['library'].".php");
?>
由於不知道includes/../../啥意識就在靶機上試驗了一下
-
includes/../
還是在本級目錄 -
includes/../../
上一級目錄 -
includes/../../../
上上級目錄
所以這里我們就是要跳出includes。而且只能執行后綴PHP文件
解決方法流程
傳參
?library=../../phpinfo
LFI-3
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ -->
<?php hint("will include the arg specified in the GET parameter \"file\", looks for .php at end - bypass by apending /. (slash plus dot)"); ?>
<form action="/LFI-3/index.php" method="GET">
<input type="text" name="file">
</form>
<?php
if (substr($_GET['file'], -4, 4) != '.php')
echo file_get_contents($_GET['file']);
else
echo 'You are not allowed to see source files!'."\n";
?>
兩個函數
-
substr():字符串裁剪,返回字符串的一部分,其用法substr(string,start,length),如果start為負數就是從末尾開始返回長度為length的字符串。
-
file_get_contents():把整個文件讀入一個字符串中。
所以這段源代碼是對get請求到的file查看其文件后綴,如果文件后綴與php相同就會禁止查看源碼,如果后綴不是php才能查看其源碼,也就是文件上傳漏洞里的黑名單嘛。
解決方法流程
黑名單繞過,包括但不局限於
-
大小寫繞過:php->PHp
-
空格繞過:php->php<空格>,這個得抓包后在hex中修改
-
加點饒工:php->php.
-
特殊字符繞過:php->php::$DATA
-
使用'.ph<'進使用'.ph<'進行
.php
拓展過濾滲出行.php
拓展過濾滲出
LFI-4
源代碼審計
<?php include("../common/header.php"); ?>
<!-- from http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ -->
<?php hint("will include the arg specified in the GET parameter \"class\", appends .php to end, defeat with NULL byte %00"); ?>
<form action="/LFI-4/index.php" method="GET">
<input type="text" name="class">
</form>
<?php
include('includes/class_'.addslashes($_GET['class']).'.php');
?>
addslashes()函數返回在預定義字符之前添加反斜杠的字符串。以下是預定義字符單引號(‘)雙引號(“)反斜杠(\)和NULL
由於又不知道includes/class_/
是啥我又做了一下實驗
解決方法流程
也就是說,這個過濾函數對我們要寫入的url根本沒影響。
寫入class的值
?class=/../../../phpinfo
LFI-5
源代碼審計
<!-- from http://hakipedia.com/index.php/Local_File_Inclusion -->
<?php include("../common/header.php"); ?>
<?php hint("will include the arg specified in the GET parameter \"file\", strips prepended \"../\" strings, must encode / with %2f"); ?>
<form action="/LFI-5/index.php" method="GET">
<input type="text" name="file">
</form>
<?php
$file = str_replace('../', '', $_GET['file']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
兩個函數
-
str_replace():將接收到的字符串中的../替換為NULL
-
isset():函數用於檢測變量是否已設置並且非 NULL。如果指定變量存在且不為 NULL,則返回 TRUE,否則返回 FALSE。
解決方法流程
話說這個pages/又是啥,我又在靶機上做了個實驗
雙寫繞過即可
?file=..../..../phpinfo.php
LFI-6到LFI-10
全都用post傳參就可以
LFI-11
源代碼審計(關鍵部分)
<?php include($_POST['stylepath']); ?>
解決方法流程
還是post傳參
LFI-12
跟上面一樣,只是用GET傳參
LFI-13和LFI-14跟LFI-5和LFI-10一樣
HDR-1
源代碼審計(關鍵部分)
<?php
$template = 'blue.php';
if ( array_key_exists( $_COOKIE['TEMPLATE'] ) )
$template = $_COOKIE['TEMPLATE'];
include ( dirname(FILE) . "/" . $template );
?>
兩個函數和一個接收變量
-
array_key_exists():檢查某個數組中是否存在指定的鍵名,如果鍵名存在則返回 true,如果鍵名不存在則返回 false。array_key_exists(key,array)且key和array都是必須的
-
dirname():返回路徑中的目錄部分
-
$_COOKIE[]接受請求中cookie傳過來的數據。
也就是說本題目源代碼有點問題......缺少函數關鍵變量。