Bugku CTF 代码审计 writeup(未完待续)

Bugku CTF 代码审计 writeup

0x01extract变量覆盖

Bugku CTF 代码审计 writeup(未完待续)
extract()函数功能:从数组中将变量导入到当前的符号表。使用数组键名作为变量名,使用数组键值作为变量值。
extract(array,extract_rules,prefix)
题中给出extract($_GET),相当于:
$shiyan = $_GET[‘shiyan’]
$flag = $_GET[‘flag’]。
另外,isset()函数判断$shiyan变量是否设置,
Bugku CTF 代码审计 writeup(未完待续)
像这样,即使变量为空,isset()函数也为true。
payload:?shiyan=&flag=
或者利用php://伪协议:payload:?shiyan=&flag=php://input

0x02strcmp比较字符串

Bugku CTF 代码审计 writeup(未完待续)
strcmp(str1, str2)比较两个字符串大小,若是非字符串(例如数组)比较,则会出错。在5.3之前的php中,显示了报错的警告信息后,将return 0。
payload:?a[]=1

0x03urldecode二次编码绕过

Bugku CTF 代码审计 writeup(未完待续)
eregi()在一个字符串中搜索指定的模式的字符串,搜索不区分大小的正则匹配。
urldecode()解码以编码的URL字符串,但是$_GET[]会将参数解码一次。
Bugku CTF 代码审计 writeup(未完待续)
若本题将“hackerDJ”进行两次URL编码,在eregi()中比较”hackerDJ”与$_GET[id]是否相同,$_GET会解码一次,从二次URL编码变成一次URL编码;urldecode()会将$_GET[id]从二次URL编码变成一次URL编码,赋值给$_GET[id],当$_GET[id]与“hackerDJ”比较时,$_GET[id]再从一次URL编码解码,最后比较相等得到flag。
将“hackerDJ”进行两次URL编码。
payload:?id=%25%36%38%25%36%31%25%36%33%25%36%62%25%36%35%25%37%32%25%34%34%25%34%61

0x04md5()函数

Bugku CTF 代码审计 writeup(未完待续)
md5()计算字符串的MD5散列值。
md5()函数不能处理数组,使用数组绕过,md5(array)会返回null。
payload1:?username[]=1&password=2

0x05数组返回NULL绕过

Bugku CTF 代码审计 writeup(未完待续)
strpos(string, find[, start])查找字符串在另一字符串中第一次出现的位置。
ereg()正则匹配,需使password中只含有英文字母和数字,又因为strpos()需要匹配“–”才能得到flag,可以使用数组绕过ereg()和strpos()。
ereg()只能处理字符,而password是数组,所以返回的是null,三个等号的时候不会进行类型转换。所以null!==false。
strpos()的参数同样不能够是数组,所以返回的依旧是null,null!==false也是正确。
payload:?password[]=1
思路二:ereg()可以进行%00截断,绕过正则匹配。
payload:?password=1%00--

0x06弱类型整数大小比较绕过

Bugku CTF 代码审计 writeup(未完待续)
is_numeric(var)检测变量是否为数字或数字字符串,是则返回true,否则返回false。
is_numeric()对于空字符%00,无论%00放在前面还是后面都可以判断为非数值,而空格%20只能放在数值后面,实质上都是弱类型转换。
payload1:?password=1337%00
payload2:?password=1337%20
payload3:?password=1337a

0x07sha()函数比较绕过

Bugku CTF 代码审计 writeup(未完待续)
同md5()一样,sha1()函数也无法处理数组,因此可以构造数组绕过。
payload:?name[]=1&password=2

0x08md5加密相等绕过

Bugku CTF 代码审计 writeup(未完待续)
md5生成的以“0e”开头的哈希值都解释为0,所以PHP在判断时会认为相同。
payload:?a=240610708

0x09十六进制与数字比较

Bugku CTF 代码审计 writeup(未完待续)
ord()返回字符串中首个字符的ASCII值。
题目中会要求输入的password中不能有0~9数字,并且还需要判断$number==$_GET[password]。所以将$number=3735929054转换为16进制“deadc0de”,再在前面加上0x表示16进制。
payload:?password=0xdeadc0de

0x10ereg正则%00截断

Bugku CTF 代码审计 writeup(未完待续)
题目通过ereg()函数判断password中是否只含有字母或数字,进而限制password长度小于8,并且值小于9999999;在此前提下用strpos()函数搜索password中是否含有“-”,若是则输出flag。
解法一,利用数组绕过strpos()函数。
payload:?password[]=9999999999
解法二,利用ereg()%00截断漏洞,在用科学记数法来构造1e9满足strlen($_GET[‘password’]) < 8 && $_GET[‘password’]> 9999999这个条件,再加上“-”来满足strpos()的条件。
payload:?password=1e9%00*-*

0x11strpos数组绕过

Bugku CTF 代码审计 writeup(未完待续)
构造数组绕过,并且值含有数字。
payload:?ctf[]=1

0x12数字验证正则绕过

Bugku CTF 代码审计 writeup(未完待续)
直接POST一个password就可以,并且小于12个字符。
payload: POST:password=1