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.png

与此同时,我们也可以随意修改PHPSESSION里面的值,虽然在服务端极大概率不能将SESSION中的password正确获取,但是这正是我们要做的。

将GET传入的password设置为空,将PHPSESSION删除掉,两者即可相等,获得flag

如图

phpsession2.png

 

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编码

https://baike.baidu.com/item/URL%E7%BC%96%E7%A0%81/3703727?fr=aladdin

最终的payload为:

1
?id=%2568ackerDJ

获得flag


__EOF__

本文作者春告鳥
本文链接https://www.cnblogs.com/Cl0ud/p/13246007.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   春告鳥  阅读(569)  评论(0编辑  收藏  举报
编辑推荐:
· 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 让容器管理更轻松!
点击右上角即可分享
微信分享提示