PHP代码审计分段讲解(4)
08 SESSION验证绕过
源代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php $flag = "flag" ; session_start(); if (isset ( $_GET [ 'password' ])) { if ( $_GET [ 'password' ] == $_SESSION [ 'password' ]) die ( 'Flag: ' . $flag ); else print '<p>Wrong guess.</p>' ; } mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)); ?> |
以GET方式传入password,并且与SESSION中的password比较是否相等,相等则返回flag,否则输出提示
SESSION中的password是我们能够看到但是难以解密的。
与此同时,我们也可以随意修改PHPSESSION里面的值,虽然在服务端极大概率不能将SESSION中的password正确获取,但是这正是我们要做的。
将GET传入的password设置为空,将PHPSESSION删除掉,两者即可相等,获得flag
如图
09 密码md5比较绕过
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 | <?php //配置数据库 if ( $_POST [user] && $_POST [pass]) { $conn = mysql_connect( "********, " ***** ", " ********"); mysql_select_db( "phpformysql" ) or die ( "Could not select database" ); if ( $conn ->connect_error) { die ( "Connection failed: " . mysql_error( $conn )); } //赋值 $user = $_POST [user]; $pass = md5( $_POST [pass]); //sql语句 // select pw from php where user='' union select 'e10adc3949ba59abbe56e057f20f883e' # // ?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456 $sql = "select pw from php where user='$user'" ; $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 [pw]) && (! strcasecmp ( $pass , $row [pw]))) { //如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。 echo "<p>Logged in! Key:************** </p>" ; } else { echo ( "<p>Log in failure!</p>" ); } } ?> |
因为要链接数据库,进行相关配置,作者比较懒,直接分析代码吧
这里是配置链接数据库
1 2 3 4 5 6 7 | //配置数据库 if ( $_POST [user] && $_POST [pass]) { $conn = mysql_connect( "********, " ***** ", " ********"); mysql_select_db( "phpformysql" ) or die ( "Could not select database" ); if ( $conn ->connect_error) { die ( "Connection failed: " . mysql_error( $conn )); } |
接着POST方式传入user和password
1 2 | $user = $_POST [user]; $pass = md5( $_POST [pass]); |
使用SQL语句查询数据库
1 2 3 4 5 6 7 | $sql = "select pw from php where user='$user'" ; $query = mysql_query( $sql ); if (! $query ) { printf( "Error: %s\n" , mysql_error( $conn )); exit (); } $row = mysql_fetch_array( $query , MYSQL_ASSOC); |
取出用户名为输入$user的密码,若密码存在且与输入的密码相同,登录成功,输出flag
1 2 3 4 5 6 | if (( $row [pw]) && (! strcasecmp ( $pass , $row [pw]))) { //如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。 echo "<p>Logged in! Key:************** </p>" ; |
总的流程就是,需要让数据库取出来的数据$row[pw]和md5($_POST[pass])相等
我们可以发现sql语句并没有进行过滤,所以可以使用union select 组合结果到$query里面去
payload最后为:
1 | ?user= ' union select ' e10adc3949ba59abbe56e057f20f883e' #&pass=123456 |
前一个查询为空,后一个查询为已知的123456的md5值,与传入的pass相等,获得flag
10 urldecode二次编码绕过
源代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php if ( eregi ( "hackerDJ" , $_GET [id])) { echo ( "<p>not allowed!</p>" ); exit (); } $_GET [id] = urldecode( $_GET [id]); if ( $_GET [id] == "hackerDJ" ) { echo "<p>Access granted!</p>" ; echo "<p>flag: *****************} </p>" ; } ?> |
GET方式传入id值,使用eregi函数对其进行hackerDJ的匹配搜索,匹配到的话立即退出,即输入id中不能含有hackerDJ。
接着读id进行urldecode解码,再比较id与hackerDJ是否相等,相等则输出flag
PHP本身在处理提交的数据之前会进行一次编码,在代码里面又进行了一次编码:
1 | $_GET [id] = urldecode( $_GET [id]); |
所以我们只需要将hackerDJ URL编码两次,就能够绕过比较获取flag
为了方便,只对h进行URL编码
最终的payload为:
1 | ?id=%2568ackerDJ |
__EOF__

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