美文网首页CTF
[网安中国行](misc)

[网安中国行](misc)

作者: 王一航 | 来源:发表于2017-07-11 14:56 被阅读194次

    http://115.28.90.49:23080/index.php?action=front&mode=register
    查看url , 感觉可以任意文件包含
    尝试使用 php 协议
    利用 filter 可以读取到任意文件源码

    image.png image.png
    <?php
    define("DIR_PERMITION",time());
    // phpinfo();
    
    function d_addslashes($array){
    
        foreach($array as $key=>$value){
            if(!is_array($value)){
                  !get_magic_quotes_gpc()&&$value=addslashes($value);
                  $array[$key]=$value;
            }else{
    
              $array[$key] = d_addslashes($array[$key]);
            }
        }
        return $array;
    
    }
    
    $_POST=d_addslashes($_POST);
    $_GET=d_addslashes($_GET);
    
    
    include_once('common.php');
    
    if(!isset($_GET['action'])||!isset($_GET['mode'])){
    
        header("Location: ./index.php?action=front&mode=login");
    
    }elseif(!preg_match('/\.{2}/is',$_GET['action'])&&preg_match('/^[0-9A-Za-z]+$/is',$_GET['mode'])){
        $action=$_GET['action'];
        $mode=$_GET['mode'];
        $file=$action.'/'.$mode.'.php';
        
        // echo $file;
    
    }else{
    
        die("Invalid Request!");
    }
    include($file);
    

    先把所有文件都读取下来再说

    <?php
    
    include_once("config.inc.php");
    
    function rand_str($lenth=16){
       $rand=[];
       $_str="qwertyuiopasdfghjklzxcvbnm0123456789QWERTYUIOPASDFGHJKLZXCVBNM";
       while($lenth){
       $rand[]=$_str[rand(0,strlen($_str)-1)];
       $lenth--;
       }
    
       return implode($rand);
    }
    
    // echo rand_str();
    
    if(!isset($_SESSION['SECURITY_KEY'])){
    
        $_SESSION['SECURITY_KEY']=rand_str(6);
    
    }
    if(!isset($_SESSION['CSRF_TOKEN'])){
        $_SESSION['CSRF_TOKEN']=rand_str(16);
    
    }
    
    if(!isset($_SESSION['level'])){
    
       $_SESSION['level']=null;
    }
    
    
    if(!isset($_SESSION['userid'])){
       $_SESSION['userid']=null;
    }
    
    
    
    function mysql_my_query($sql){
            global $conn;
            $res=$conn->query($sql) or die("查询数据库出错!");
            
            return $res;
            
    }
    
    function encode($str){
        return md5($_SESSION['SECURITY_KEY'].$str);
    
    }
    
    function set_login($uname,$id,$level){
         $_SESSION['userid']=$id;
         $_SESSION['level']=$level;
         
         $endata=encode($uname);
         setcookie("uid","$uname|$endata");
         
    }
    
    function check_login(){
    
        $uid=$_COOKIE['uid'];
        $userinfo=explode("|",$uid);
    
        if($userinfo[0]&&$userinfo[1]&&$userinfo[1]==encode($userinfo[0])){
            return $_SESSION['userid'];
    
        }else{
    
            return FALSE;
    
        }
    
    }
    
    function get_level(){
    
        $uid=$_COOKIE['uid'];
        $userinfo=explode("|",$uid);
    
        if($userinfo[0]&&$userinfo[1]&&$userinfo[1]==encode($userinfo[0])){
            
            if($_SESSION['level']!=="0"){
    
                return $_SESSION['level'];
            }else{
                return FALSE;
    
            }
        }else{
    
            return FALSE;
        }
    
    }
    
    
    function get_page_size(){
    
          $sql="select num from page";
          $res=mysql_my_query($sql);
          $row=$res->fetch_assoc();
          return $row['num'];
    }
    
    function set_page_size(){
        
        $sql="update page set num=20";
        $res=mysql_my_query($sql);
        
    }
    
    function get_uname($userid){
           
           $sql="select uname from user where id='$userid'";
           $res=mysql_my_query($sql);
           $row=$res->fetch_assoc();
          return  htmlspecialchars($row['uname']);
    
    }
    

    结合之前扫描到存在 admin 目录
    可以再来读取一下 admin 的文件

    image.png

    index.php

    <?php
    
    
    defined("DIR_PERMITION") or die("Permision denied!");
    
    $userid=check_login();
    $level=get_level();
    
    if($userid!==false&&$level!==false){
      
        $page_size=get_page_size();
        //默认仅仅显示 前$page_size条数据 
        $sql="select * from note  limit 0,".$page_size;
        $result=mysql_my_query($sql);
    
        set_page_size(); #设置default page size 
    
    }else{
        
        echo "<script>alert('not login!');</script>";
        echo("<script>location.href='./index.php?action=admin&mode=login'</script>");
        die();
    
        // $result=mysql_my_query($sql);
    }
    
    ?>
    
    <!DOCTYPE html>
    <html>
    <head lang="en">
      <meta charset="UTF-8">
      <title>记事本管理系统</title>
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <meta name="format-detection" content="telephone=no">
      <meta name="renderer" content="webkit">
      <meta http-equiv="Cache-Control" content="no-siteapp" />
      <link rel="alternate icon" type="image/png" href="./assets/i/favicon.png">
      <link rel="stylesheet" href="./assets/css/amazeui.min.css"/>
      <style>
        .header {
          text-align: center;
        }
        .header h1 {
          font-size: 200%;
          color: #333;
          margin-top: 30px;
        }
        .header p {
          font-size: 14px;
        }
        .content{
          width:90%;
          margin:auto auto;
    
    
        }
      </style>
    </head>
    <body>
    <div class="header">
      <div class="am-g">
        <h1>记事本管理系统后台</h1>
        <p>welcome:admin<br/>userid:1</p>
      </div>
      <hr />
    </div>
    
    <div class="content">
    
      <a class="am-btn am-btn-success" style="float:right;margin:0 0 20px 0" href="./index.php?action=admin&mode=setpagenum">前<?php echo $page_size;?>条笔记</a>
       <table class="am-table am-table-bordered am-table-radius am-table-striped am-table-hover" >
        <thead>
            <tr>
                <th>user</th>
                <th>title</th>
                <th>content</th>
            </tr>
        </thead>
        <tbody>
    
            <?php 
    
                 while($row=$result->fetch_assoc()){
                   echo "<tr>";
                   echo "<td>".get_uname($row['userid'])."</td>";
                   echo "<td>".$row['title']."</td>";
                   echo "<td>".$row['content']."</td>";
                   echo "</tr>";
                 }
    
            ?>
    
        </tbody>
    </table>
    
        <hr>
        <p>© 记事本管理系统.</p>
    </div>
    </body>
    </html>
    

    login.php

    <?php
    
    defined("DIR_PERMITION") or die("Permision denied!");
    
    if(isset($_POST['uname'])&&isset($_POST['password'])&&isset($_POST['TOKEN'])){
    
        $uname="admin";
        $password=md5($_POST['password']);
        $TOKEN=$_POST['TOKEN'];
    
        if($TOKEN!=$_SESSION['CSRF_TOKEN']){
            die("token error!");
        }
        $sql="select id,level  from  user where uname='$uname' and password='$password' and level='1'";
        
        $res=mysql_my_query($sql);
        $row=$res->fetch_assoc(); //获取第一条记录
    
        if($row['id']){
            
            set_login($uname,$row['id'],$row['level']);
            
            header("Location: ./index.php?action=admin&mode=index");
            exit();
        }else{
                    
            echo("<script>alert('username or password error!')</script>");
        }
    
    }
    
    ?>
    
    <!DOCTYPE html>
    <html>
    <head lang="en">
      <meta charset="UTF-8">
      <title>记事本管理系统</title>
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <meta name="format-detection" content="telephone=no">
      <meta name="renderer" content="webkit">
      <meta http-equiv="Cache-Control" content="no-siteapp" />
      <link rel="alternate icon" type="image/png" href="assets/i/favicon.png">
      <link rel="stylesheet" href="assets/css/amazeui.min.css"/>
      <style>
        .header {
          text-align: center;
        }
        .header h1 {
          font-size: 200%;
          color: #333;
          margin-top: 30px;
        }
        .header p {
          font-size: 14px;
        }
      </style>
    </head>
    <body>
    <div class="header">
      <div class="am-g">
        <h1>记事本管理系统后台</h1>
      </div>
      <hr />
    </div>
    <div class="am-g">
      <div class="am-u-lg-6 am-u-md-8 am-u-sm-centered">
        <h3>管理员登录</h3>
        <br>
        <br>
    
        <form method="post" class="am-form">
          <label for="uname">用户名:</label>
          <input type="text" name="uname" id="uname" value="admin" readonly>
    
          <br>
          <label for="password">密码:</label>
          <input type="password" name="password" id="password" value="">
          <br>
          <input type="hidden" name="TOKEN" id="password" value="<?php echo $_SESSION['CSRF_TOKEN'];?>">
          <br>
          <label for="remember-me">
            <input id="remember-me" type="checkbox">
            记住密码
          </label>
          <br />
          <div class="am-cf">
            <input type="submit" name="" value="登 录" class="am-btn am-btn-primary am-btn-sm am-fl">
    
          </div>
        </form>
        <hr>
        <p>© 记事本管理系统.</p>
      </div>
    </div>
    </body>
    </html>
    
    <?php
    defined("DIR_PERMITION") or die("Permision denied!");
    $userid=check_login();
    $level=get_level();
    
    if($userid!==false&&$level!==false){
          if(isset($_POST['page'])&&isset($_POST['TOKEN'])){
              $page=$_POST['page'];
              $TOKEN=$_POST['TOKEN'];
    
              if($TOKEN!=$_SESSION['CSRF_TOKEN']){
                die("token error!");
              }
    
              if(!is_numeric($page)){
                  die("page must be a number!");   
              }
              if($page<1) $page=1;
    
              $sql="update page set num=$page";
              $res=mysql_my_query($sql);
              if($res){
                    echo "<script>alert('update  success!');</script>";
                    echo("<script>location.href='./index.php?action=admin&mode=index'</script>");
    
              }else{
                   echo "<script>alert('update  fail!');</script>";
                   die();
              }
          }
    }else{
    
        echo "<script>alert('not login!');</script>";
        echo("<script>location.href='./index.php?action=admin&mode=login'</script>");
        die();
        // $result=mysql_my_query($sql);
    }
    
    ?>
    
    <!DOCTYPE html>
    <html>
    <head lang="en">
      <meta charset="UTF-8">
      <title>记事本管理系统</title>
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <meta name="format-detection" content="telephone=no">
      <meta name="renderer" content="webkit">
      <meta http-equiv="Cache-Control" content="no-siteapp" />
      <link rel="alternate icon" type="image/png" href="assets/i/favicon.png">
      <link rel="stylesheet" href="assets/css/amazeui.min.css"/>
      <style>
        .header {
          text-align: center;
        }
        .header h1 {
          font-size: 200%;
          color: #333;
          margin-top: 30px;
        }
        .header p {
          font-size: 14px;
        }
      </style>
    </head>
    <body>
    <div class="header">
      <div class="am-g">
        <h1>记事本管理系统后台</h1>
      </div>
      <hr />
    </div>
    <div class="am-g">
      <div class="am-u-lg-6 am-u-md-8 am-u-sm-centered">
        <h3>设置显示条数</h3>
        <br>
        <br>
        <form method="post" class="am-form">
          <label for="page">设置条数:</label>
          <input type="text" name="page" id="page">
          <br>
          <div class="am-cf">
            <input type="submit" name="" value="设 置" class="am-btn am-btn-primary am-btn-sm am-fl">
            <input type="hidden" name="TOKEN" id="TOKEN" value="<?php echo $_SESSION['CSRF_TOKEN'];?>">
    
          </div>
        </form>
        <hr>
        <p>© 记事本管理系统.</p>
      </div>
    </div>
    </body>
    </html>
    

    这里存在二次注入

    if($userid!==false&&$level!==false){
          if(isset($_POST['page'])&&isset($_POST['TOKEN'])){
              $page=$_POST['page'];
              $TOKEN=$_POST['TOKEN'];
    
              if($TOKEN!=$_SESSION['CSRF_TOKEN']){
                die("token error!");
              }
    
              if(!is_numeric($page)){
                  die("page must be a number!");   
              }
              if($page<1) $page=1;
    
              $sql="update page set num=$page";
              $res=mysql_my_query($sql);
              if($res){
                    echo "<script>alert('update  success!');</script>";
                    echo("<script>location.href='./index.php?action=admin&mode=index'</script>");
    
              }else{
                   echo "<script>alert('update  fail!');</script>";
                   die();
              }
          }
    }else{
    
        echo "<script>alert('not login!');</script>";
        echo("<script>location.href='./index.php?action=admin&mode=login'</script>");
        die();
        // $result=mysql_my_query($sql);
    }
    
    image.png

    通过二次注入拿到 :

    database :
    information_schema,ctf,mysql,performance_schema
    
    ctf : tables :
    flags,note,page,user
    
    flags : 
    id,flag
    
    page : 
    num
    
    note : 
    id,content,title,userid
    
    user : 
    id,uname,password,level,Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show
    

    直接获取flag的内容为 :

    image.png image.png image.png
    <tr><td>admin</td><td>管理员的笔记</td><td>此内容无法删除</td></tr><tr><td>asla</td><td>/5ebe2294ecd0e0f08eab7690d2a6ee69/reverseit</td><td>1</td></tr>
    

    好像是一个路径 , 下载得到一个 .net 的二进制程序
    逆向一下看看

    image.png

    只需要绕过这些正则匹配就可以了
    最终flag为 :

    EKO{ooOOoo_sup3r_r3g3x_challenge_OOooOO}
    

    相关文章

      网友评论

      • littleheary:大神,你第一个步骤用filter读文件的语句可以贴出来看看么?
        da28c79c7c2f:大佬,这里有人利用了一个rand猜解的方法登录了admin,中间那个二次注入的代码是从哪里得到的呢?
        王一航:这里的坑就是 action 这个参数代表文件夹 , mode 代表文件名 , 然后 php 代码里面是把这俩拼起来的 , 就像这样 :
        ```
        $file = $action.'/'.$mode.'.php';
        ```
      • littleheary:我日,从第一步就看不懂
        王一航:https://github.com/wonderkun/CTF_web/blob/master/web500-2/writeup.pdf
      • 北斗贰:🙃🙃🙃大神真厉害😭😭😭

      本文标题:[网安中国行](misc)

      本文链接:https://www.haomeiwen.com/subject/rvqmhxtx.html