常见漏洞
JWT伪造漏洞
JSON Web Token
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全的传输信息。该信息可以被验证和信任,因为它是数字签名的。
什么时候应该用JSON Web Tokens
下列场景中使用JSON Web Token是很有用的:
Authorization(授权):这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
Information Exchange(信息交换):对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
JSON Web Token 的结构
JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:
- Header
- Payload
- Signature
因此,一个典型的JWT看起来是这个样子的:
1 |
|
接下来,具体看一下每一部分:
Header
header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。
例如:
然后,用Base64对这个JSON编码就得到JWT的第一部分
Payload
JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其它数据的声明。声明有三种类型:registered,public和private。
Registered claims: 这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss(issuer),exp(expiration time), sub(subject),aud(audience)等。
Public claims: 可以随意定义。
Private claims: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。
下面是一个例子:
对payload进行Base64编码就得到JWT的第二部分
注意,不要在JWT的payload或header中放置敏感信息,除非它们是加密的。
Sinature
为了得到签名部分,你必须有编码过的header、编码过的payload、一个密钥,签名算法是header中指定的那个,然后对它们签名即可。
例如
1 |
|
签名是用于验证消息在传递过程中有没有被更改,并且,由于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。
官网解码图
官网地址https://jwt.io/
密钥的取得方法我们由一个题来引入
[CISCN2019 华北赛区 Day1 Web2]ikun
从cookies中抓出JWT数据
放到官网里分析
是我们注册的数据没错
现在要做的就是破解密钥
这里有个脚本c-jwt-cracker
我使用的是kali,攻击jwt
这样我们就获得了我们的密钥,然后将密钥填入密匙位置在官网生成一个新的JWT
原题链接
认识JWT
Python Pickle反序列化漏洞
pickle简介
与PHP类似,python也有序列化功能以长期储存内存中的数据。pickle是python下的序列化与反序列化包。
python有另一个更原始的序列化包marshal,现在开发时一般使用pickle。
与json相比,pickle以二进制储存,不易人工阅读;json可以跨语言,而pickle是python专用的;pickle能表示python几乎所有的类型(包括自定义类型),json只能表示一部分内置类型且不能表示自定义类型。
pickle实际上可以看作一种独立的语言,通过对opcode的更改编写可以执行python代码、覆盖变量等操作。直接编写的opcode灵活性比使用pickle序列化生成的代码更高,有的代码不能通过pickle序列化得到(pickle解析能力大于pickle生成能力)。
- dump和load与文件操作结合起来:
- 序列化
1 |
|
必填参数obj表示将要封装的对象,必填参数file表示obj要写入的文件对象,file必须以二进制可写模式打开,即wb。
- 反序列化
1 |
|
必填参数file必须以二进制可读模式打开,即rb,其他都为可选参数。
示例:
1 |
|
- dumps与loads则不需要输出成文件,而是以字符串(py2)或字节流(py3)的形式进行转换。
- 序列化
1 |
|
- 反序列化
1 |
|
示例
1 |
|
output
1 |
|
1 |
|
output
1 |
|
PVM操作码
要想真正的利用反序列化,我们还得从底层了解一下pickle数据的格式是什么样的。
c: 读取新的一行作为模板名module,读取下一行作为对象名object,然后将module.object压入到堆栈中。
(
:将一个标记对象插入到堆栈中。为了实现我们的目的,该指令会与t搭配使用,以产生一个元组。t: 从堆栈中弹出对象,知道一个
(
被弹出,并创建一个包含弹出对象(除了(
)的元组对象,并且这些对象的顺序必须跟它们压入堆栈时的顺序一致。然后,该元组被压入到堆栈中。S: 读取引号中的字符串直到换行符处,然后将它压入堆栈。
R: 将一个元组和一个可调用对象弹出堆栈,然后以该元组作为参数调用该可调用的对象。最后将结果压入到堆栈中。
.
:结束pickle
简单说来就是:
c: 以c开始的后面两行的作用类似os.system的调用,其中cos在第一行,system在第二行。
(
: 相当于左括号t: 相当于右括号
S: 表示本行的内容一个字符串
R: 执行紧靠自己左边的一个括号对(即
(
和t之间)的内容.
: 代表该pickle结束
举一个例子:
1 |
|
我们将上面的序列化字符串在python2下反序列化,相当于执行了os.system(‘whoami’)
1 |
|
反序列化漏洞利用
python中的类有一个__reduce__方法,类似与PHP中的wakeup,在反序列化的时候会自动调用。
这里注意,在python2中只有内置类才有__reduce__方法,即用class A(object)声明的类,而python3中已经默认都是内置类了
而我们定义的__reduce__可以返回一个元组,这个元组包含2到5个元素,主要用到前两个参数,即一个可调用的对象,用于重建对象时调用,一个参数元素(也是元组形式),供那个可调用对象使用
举个例子
1 |
|
成功执行命令
看一下真题
[CISCN2019 华北赛区 Day1 Web2]ikun
前面的步骤就不再详细描述了,这里直接从Pickle反序列化漏洞入手
在admin.py中找到后门
self.render(‘form.html’, res=p, member=1)
这段代码的意思就是找到模板文件,进行渲染,从而显示页面
来观察一下form.html页面
说明传入的是可以直接进行回显的,而且可以将自定义的类进行序列化个反序列化。因此存在Pickle反序列化漏洞,那我们就可以构造一个通过pickle.dumps序列化的payload,从而被解析读取flag或其他信息。
构造payload可以使用方法__reduce__(self),先要获取的flag文件的位置,然后进行读取
但需要注意几点:
1 |
|
这两个函数只有以print输出时才会回显,如果是以return返回的就不会显示结果。
查阅资料发现
可以使用commands.getoutput()这个函数来进行代替,构造payload
1 |
|
发现flag.txt文件,接下来读取即可
1 |
|
参考 :
Python Pickle反序列化漏洞
os.system() 和 os.popen()
浅谈python反序列化漏洞
pickle反序列化初探
php伪随机数mt_rand函数漏洞
mt_rand()函数
1 |
|
mt_srand()函数
1 |
|
在php中每一次调用mt_rand()函数,都会检查一下系统有没有播种。(播种为mt_srand()函数完成),当随机种子生成后,后面生成的随机数就会根据这个随机种子生成。所以同一个种子下,随机数的生成是相同的,这就是漏洞点,看一个例子就懂了
1 |
|
在上面的代码中,我们把随机数播种为0,每次运行都会获得相同的序列,这就是伪随机:
1 |
|
因此在知晓一串随机序列的条件下,基于序列相同的seed爆破是可能实现的。
在对seed进行爆破,我们需要使用一个工具php_mt_seed
php_mt_seed工具使用
php_mt_seed是c语言编写的爆破随机数序列种子的工具,
github地址为:https://github.com/openwall/php_mt_seed
我在这里使用的环境为kali系统
下载完成后,进入下载目录中运行make命令
程序编译完成后,使用官方文档中的使用方法
1 |
|
将我们的序列转换为php_mt_seed可识别的格式
1 |
|
后使用
1 |
|
即可得出seed值
下面看一道真题
[GWCTF 2019]枯燥的抽奖
1 |
|
通过上面的代码可以发现,首先使用rand(0,999999999);函数确认种子,然后再由种子生成了20位的随机数
现在10位序列是我们所已知的,我们需要从这10位序列爆破出它的种子值
执行上面的操作
先将我们的序列转换为php_mt_seed可以识别的格式
后使用
1 |
|
命令获得种子
然后把种子插入再执行一遍题目的源代码即可获得20位随机数
1 |
|
成功反推,获得了flag
CTF_Web:php伪随机数mt_rand()函数+php_mt_seed工具使用
文件上传漏洞–htaccess文件
htaccess概述
htaccess文件是apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件拓展名、允许/组织特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
Unix、Linux系统或者是任何版本的apache web服务器都是支持.htaccess的,但是有的主机服务商可能不允许你自定义自己的.htaccess文件。
笼统地说.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件拓展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。
漏洞原理
利用上传到服务器上的.htaccess文件修改当前目录下的解析规则
利用的前提条件
http.conf文件中设置了 AllowOverried ALL,才能使用.htaccess文件
文件上传漏洞中利用.htaccess文件
第一种:将特定后缀名当作php解析。
1 |
|
第二种:将当前目录中所有文件都使用php解析。
1 |
|
第三种:使用FilesMatch来匹配文件名,使特定文件名的文件当作php解析
1 |
|
仅sad.jpg文件被解析php代码执行