笔者正在上的网络攻防技术课的溯源取证课程时,恰逢老师拿陇剑杯的题目来当作业,遂详细分析了一下,其中ios部分的手机上的密钥内容由于似乎是0解题,也没有验证,故并不保证一定正确,但是应该有一定的参考价值
(1). Webshell数据包(webshell.zip)
小张单位网站被黑客挂马,请您从流量中分析出webshell,进行回答:
A. 黑客在整个过程中做了哪些操作,请简单列举出来并截图说明。
先直接找找POST,看到一个login
查看表单
果然是弱口令,去看看返回的数据
登上去了
继续看POST,306包处发现
tpl应该是骑士cms的模版注入+日志包含来getshell,这里包含了一个马上去,让日志记录错误
这样的操作显然会404,不过看到404的内容也说了是骑士CMS,显然我们之前的猜测是正确的
404之后再去包含日志,想直接执行命令
结果也是404
然后又测试了phpinfo,即不post参数a,只执行phpinfo
发现可以正常显示phpinfo
又使用a尝试了一次无果,转而黑客又去重新post一个密码为aaa的马来试尝试rce
这里传aaa来执行whoami,返回200说明正常执行
接着执行了ipconfig和ifconfig
从长度不难看出ifconfig有回显,打开能直接看到信息
所以能判定是linux系统
然后就是基础的信息搜集,pwd
显然是/var/www/html
接着以base64的形式传了一个马,用于蚁剑连接
get访问1.php成功后,看了看下一次的访问时间是19s钟后,再看流量,很明显是切换蚁剑连接shell了
然后用蚁剑简单ls了一下
接着又发了一个包
整理一下长这样
其中$f处把FBL3Zhci93d3cvaHRtbC9mcnBjLmluaQ==从第二个字符处substr变成L3Zhci93d3cvaHRtbC9mcnBjLmluaQ==,解之可得/var/www/html/frpc.ini
而$c处看似是转url然后在decode其实就是hex转ascii,结果是
所以这里是要在当前目录下把socks5的配置写入frpc.ini中,而frpc.ini是frp用来内网穿透的配置文件,故接下来黑客将进行内网穿透了
接着又通过蚁剑ls
可以看到frpc.ini已经上传完成
接着就是继续为内网渗透的部分做准备
这里也是一样,根据代码,去掉前两个字符之后解base64能得到frpc,显然这是在传frp客户端程序
且这里454C46解hex能得到ELF,相互印证可以确定后面是在传输frpc的linux的客户端可执行文件
流量包到这里就结束了,但是不难想到黑客后续会继续进行内网渗透
B. 黑客登录系统使用的密码、黑客的socks5的连接账号与密码请列举出来,并配图说明。
黑客使用弱口令登录后台,密码在101 package中
Admin123!@#
黑客的socks5连接帐号与密码是用蚁剑上传的frpc.ini中
[common]
server_addr = 192.168.239.123
server_port = 7778
token=Xa3BJf2l5enmN6Z7A8mv[test_sock5]
type = tcp
remote_port =8111
plugin = socks5
plugin_user = 0HDFt16cLQJ
plugin_passwd = JTN276Gp
use_encryption = true
use_compression = true
故帐号:0HDFt16cLQJ 密码:JTN276Gp
(2). 日志分析(日志分析.zip)
小明发现单位某应用程序被攻击后提取了对应的日志数据,请分析日志并进行作答:
A. 网络存在源码泄漏,源码文件名是什么?(请提交带有文件后缀的文件名,例如x.txt,并对流量分析进行截图)
打开txt文件,直接高亮200,不难看到访问了一个www.zip并且返回200,故源码泄露文件名就是www.zip
B. 分析攻击流量,黑客往/tmp目录写入一个文件,文件名是什么?(请对流量分析进行截图)
由于/等符号会url编码,这里先全局解码一下
解码成功后看的方便多了
找找tmp路径
可以看到写入了一个sess_car文件
C. 分析攻击流量,黑客使用的是什么漏洞读取了秘密文件?
很明显的序列化数据,故一定是通过反序列化利用SplFileObject来读取文件内容,这里是先把反序列化数据写入了tmp的sess_car文件中,接着再访问这个文件,触发反序列化,从而读取flag文件
故利用的漏洞为反序列化
攻击“苹果”注入(ios.zip)
一位苹果安全研究员在家中使用手机联网被黑,不仅被窃密还丢失比特币若干,请你通过流量和日志分析后作答:
A. 简述黑客的整个攻击过程,关键步骤请配图说明。
先简单浏览一下附件,附件中给了keylog和一个日志文件以及一个流量包,简单查看流量包,时间是
而日志分析中的时间是
[28/Aug/2021:18:44:28 +0000]
换算成东八区时间为
29/Aug/2021:02:44:28
故有
则根据时间顺序,先去看看流量包
其中存在大量的tls流量,不难想到要先使用附件中的keylog进行解密
解密后可以看到152流等的tls已经变成了明文,后面再分析
因为原来的152是加密流量
继续去看流量包,从开头看起
开局两个内网ip,其中.3发送了一个midea_ac,明显的美的空调设备,纯纯干扰项
随后又有一个外网ip220.195.22.133连接内网的.8ip
猜测.8可能就是被黑客黑入的机器,从流量包的开头可以看到有一个dns解析请求,目标是github.com,从响应包来看可以确定github.com的ip是20.205.243.166
后续.8的肉鸡与github有着大量流量,但是我们没有这一流的tls密钥,先暂时搁置
接续看,这里我先过滤了ip地址方便查看,越过大量的加密流量可以看到.8的攻击者终于有了一个明文数据包
其中262包包含一个很敏感的文件名 key.key,同时这里也能看到是在连接terminal
其实找到这一个流的更简单的方法是全局搜索github,都能定位到.8肉鸡和3.128.156.159的交互流量
可以看到这里用wget下载了一个github项目,Stowaway,且是从3.128.156.159发送的命令,不妨追踪流
可以看到这里是已经拿下shell了,ls的时候可以看到一个十分敏感的文件名key.key,这个key.key个人猜测是攻击者从受害者手机拿走的私钥文件了
且流量最后,下载下来代理后,直接连接了3.128.156.139:8081
-s参数为hack4sec
这里先去github看看项目
显然是一个专门用来渗透的代理工具,看看-s是干嘛的
显然是代理的加密秘钥,故加密秘钥为hack4sec
随后.8ip又去访问了sina
这应该是被害者访问的,显然被害者此时还不知道自己的手机已经被入侵
后续就是一大堆各种娱乐url的流量,显然小日子过得不错
结合刚才解密的tls流量,终于找到了.8开始访问同一网段的.12了
单独查看这一个流,很明显的sql注入流量
271流的http2流量,导出一下
用脚本判定一下字符
from urllib.parse import unquote
f = open(r'dump.txt', 'r').read().splitlines()
last = ''
lastnum = 1
for i in f:
if '/info?l=1&o=' in i:
tmp = unquote(i.split('/info?l=1&o=')[1].split(', WINDOW')[0])
tmpnum = int(tmp.split(',')[1])
if tmpnum == lastnum:
last = chr(int(tmp.split('"')[1], 16))
else:
lastnum = tmpnum
print(last, end='')
print('')
得到了一个uuid:746558f3-c841-456b-85d7-d6c0f2edabb2
继续翻,发现
SYN后直接返回RST,猜测是端口扫描
简单翻一下结果,从10扫到了499,还额外扫了个2222开着,猜测是jumpserver的[DirectAdmin], 后续也是通过这个2222连接了.12主机
后面就连上7777端口了,搜索得知这个端口是windows某后门程序的默认端口
显然黑客已经通过.8打入内网的.12服务器
而根据时间,同时黑客又在向内网的172.28.0.3发起攻击
这个日志信息也不是很全,但是省略的部分也是能猜出来,总体分三部分,第一部分就是文件上传,成功上传ma.php后,使用whoami进行了一个测试,成功之后后续就连接木马了
B. 黑客所控制的C&C服务器IP是什么?
详细分析过程已经在A中叙述,这个ip就是一直和192.168.1.8互动的有着大量加密tcp流量的ip
3.128.156.159
C. 被害者手机上被拿走了的私钥文件内容是什么?
私钥文件是说key.key
但是后续黑客使用了代理,故考虑解密流量
这里先定位一下解密部分在哪,首先项目中有一个crypto文件夹
里面有一个AES,用vscode全局搜一下AES的调用
在raw.go中调用的
定位到了DeconstructData()函数中
首先是把数据的前34字节解析成了一个头部,可以来对应一下
可以看到 IAMNEWHERE
和 IAMADMINXD
均为10字节,符合sender和accepter的长度
注意到Stowaway的加密流量都在pcap的177stream中,进而过滤,方便查看
经过颅内fuzz以及查看代码,得到的流量包最终结果是这样
换言之,我们只需要知道datalen,然后aes解之即可
不过还是得注意aes的模式,由于流量包是8月份的,而该项目在10月份对aes进行了修改
故要使用AES-CBC模式来进行解密
虽然这部分只是解析了192.168.1.8发送到C&C服务器的数据,但是这已经足够了
这里直接回滚到老版本的aes解密
package crypto
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"errors"
)
func KeyPadding(key []byte) ([]byte, error) {
// if no key,just return
if string(key) == "" {
return nil, nil
}
// if key is set,padding it
keyLength := float32(len(key))
if keyLength/8 >= 4 {
return nil, errors.New("key too long! Should be shorter than 32 bytes")
}
padding := 32 - len(key)
padText := bytes.Repeat([]byte{byte(0)}, padding)
return append(key, padText...), nil
}
func AESDecrypt(cryptedData, key []byte) []byte {
if key == nil {
return cryptedData
}
block, _ := aes.NewCipher(key)
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(cryptedData))
blockMode.CryptBlocks(origData, cryptedData)
origData = PKCS7UnPadding(origData)
return origData
}
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:length-unpadding]
}
func AESEncrypt(origData, key []byte) []byte {
if key == nil {
return origData
}
block, _ := aes.NewCipher(key)
origData = PKCS7Padding(origData, block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted
}
func PKCS7Padding(origData []byte, blockSize int) []byte {
padding := blockSize - len(origData)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(origData, padText...)
}
加密部分就是一个简单的AESCBC
密码已经知道了是hack4sec,但是不是16/24/32字节,先去看padding部分
可以看到也是在这进行了padding,方法也很简单,就是尾部加00
简单写一个python脚本对第一个包的10字节数据进行解密验证是否正确
from Crypto.Cipher import AES
data = bytes.fromhex('51be7388e89c91cfde2a9e684ec5457e8c188fdcab3cc31d6ae49cb74a75b6f008b7320f6f720fab1453fb79d75f4acb')
key = b'hack4sec' + b'\x00' * (32 - len(b'hack4sec'))
cipher = AES.new(key, AES.MODE_CBC)
result = cipher.decrypt(data)
print(result)
得到
b"\xb7\xc5'\x0en\x1e\xc0X?\xd9X&}/\x1f=\x00\x00\x00\x04root\x00\x00\x00\x00\x00\x00\x00\x04Null\x00\x00\x00\x00\x00\x00\x00\x00\x04\x04\x04\x04"
可以看到root和Null,可以认为解密成功,然后完善脚本,使得对整个流量包进行解密
调了半天都不对,发现iv设置错误,iv取的是前16字节
修改后正常解密
继续浏览代码,可以看message type中有一个filedata的类型
而前面我们已经知道,filedata是在tcp的payload中的第20~22字节,这里直接进行判定,遇到filedata了就结束程序
得到了一个test.key,这应该就是被害者手机上的私钥文件内容了
而filedata的流量包格式如下
故长度是ord('4')=52
5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWj1sn
刚好是52个字符
则最终私钥文件内容
5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWj1s