JWT安全WebGoat实战与预编译CASE注入

发布于:2022-12-07 ⋅ 阅读:(1434) ⋅ 点赞:(1)

目录

(一)什么是预编译

1、如何绕过

BP抓包看响应报文里面有没有用到order by

(二)JWT安全

1、什么是JWT

 头部

声明

签名

2、javaweb-身份验证攻击-JWT修改伪造攻击

案例分析:

 3、javaweb-身份验证攻击-JWT密匙爆破攻击

0x01、 先进去看看描述

0x02、把它给我们的令牌进行解密

0x03、找到密匙

0x04、重新签名

 0x05 总结

4、javaweb-身份验证攻击-JWT修改伪造冒充

前置知识:

0x01、进入靶场

0x02、打开日志

思路:

0x03、 拿到refresh token

 0x04 刷新Token

 0x05 拿到刷新后的access_token 结账

0x06 总结

5、javaweb-身份验证攻击-JWT安全结合SQL注入

0x01 先用BP抓到Tom下方的Delete数据包

参考:Java代码审计入门:WebGoat8(再会) - FreeBuf网络安全行业门户


        由于笔者个人水平有限,行文如有不当,还请各位师傅评论指正,非常感谢

(一)什么是预编译


JDBC编程之预编译SQL与防注入 - 加了冰的才叫可乐 - 博客园

        在博客园找了篇不错的文章,当然也可以看看我之前整理的文章,我先简单进行总结SQL Injection 防御——预编译__Cyber的博客-CSDN博客

1 sqLIniection(mitigation)
2防御sq1注入,其实就是session,参数绑定,存储过程这样的注入。
3//利用session防御,session内容正常情况下是用户无法修改的select *
from users where user=""+session.getAttribute("UserID"
+"!";
4//参数绑定方式,利用了sq1的预编译技术
5 String query = "SELECT * FROM users WHERE last name =?";
6 Preparedstatement statement =
connection.prepareStatement(query);

7 statement.setstring(1, accountName);
8 ResultSet results =statement.executeQuery();
9上面说的方式也不是能够绝对的进行sq1注入防御,只是减轻。

1、如何绕过


上述参数指定方式可以通过如下绕过:

通过使用case when语句可以将order by后的orderExpression表达式中添加select语句

BP抓包看响应报文里面有没有用到order by

        我们把column的字段值修改为i,发现order by语句刚好拼接上去了,case when语法.

(二)JWT安全


1、什么是JWT


        JSON Web Token(JSON Web令牌)是一种跨域验证身份的方案。JWT不加密传输的数据,但是能够通过数字签名来验证数据未被篡改。

        JWT分为三部分,头部(Header),声明(Claims),签名(Signature),三个部分以英文句号.隔开,JWT的内容以Base64URL进行了编码。如图一

图一

 头部

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

声明

JWT固定参数有:

  • iss:发行人
  • exp:到期时间
  • sub:主题
  • aud:用户
  • nbf:在此之前不可用
  • iat:发布时间
  • jc:JWT ID用于标识该JWT

签名

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

1、用户端登录,用户名和密码在请求中被发往服务器
2、(确认登录信息正确后)服务器生成JSON头部和声明,将登录信息写入JSON的声明中(通常不应写入密码,因为JWT是不加密的),并用secret用指定算法进行加密,生成该用户的JWT。此时,服务器并没有保存登录状态信息。
3.服务器将JWT(通过响应)返回给客户端
4、用户下次会话时,客户端会自动将JWT写在HTTP请求头部的Authrzretion字段中
5、服务器对JWT进行验证,若验证成功,则确认此用户的登录状态
6、服务器返回响应

2、javaweb-身份验证攻击-JWT修改伪造攻击


        我们知道JWT的声明内容变了,因此签名需要重新生成,生成签名又需要密码,我们尝试把Header改为None,实现身份绕过。

案例分析:
 

我这里是把webgoat放在kali里面,配置比较简单安装看这个,直接打开此关卡即可

抓到Tom的数据包

        把access_token的值复制到JSON Web Tokens - jwt.io

 进行解密,看数据包内容

 我们要明白alg的value值最终决定了数字签名使用的何种算法,我们如果说把它改为None,就相当于明文,它这一关的要求就得到管理员权限,我们把admin的value改为true就可以了。

改none

 改true

    在HTTP传输过程中,Base64编码的"=","+","/"等特殊符号通过URL编码通常容易产生歧义,因此产生了与URL兼容的Base64 URL编码,所以我们把它们去掉即可。

 发送数据:

 3、javaweb-身份验证攻击-JWT密匙爆破攻击


        如果签名算法,加密后的载荷和最终得到的加密字符串都已知,且密钥不够复杂的话,使用暴力破解便有可能将密钥解出,可以看看这位大佬写的好文章全程带阻:记一次授权网络攻防演练(上) - FreeBuf网络安全行业门户

0x01、 先进去看看描述

0x02、把它给我们的令牌进行解密

0x03、找到密匙

         理清一下思路,我们要找到这个令牌的密匙,现在知道使用密匙加密后的数据,我们用python进行爆破,用github上相应的字典。

import jwt
import termcolor
if __name__ == "__main__":
    jwt_str = R'eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1Njk3MjI2NDQsImFkbWluIjoiZmFsc2UiLCJ1c2VyIjoiVG9tIn0.Y2WgbXt9wjv4p4BdM_tA9f05sG-_n1ugojijOZMXx2_Gld_Ip4dOazj9K3iWVC68W_7_HEyu2_c0qSjtqDC0Vg'
    with open('/YOUR-PATH/Top1000.txt') as f:
        for line in f:
            key_ = line.strip()
            try:
                jwt.decode(jwt_str, verify=True, key=key_)
                print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
                break
            except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
                print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
                break
            except jwt.exceptions.InvalidSignatureError:
                print('\r', ' ' * 64, '\r\btry', key_, end='', flush=True)
                continue
        else:
            print('\r', '\bsorry! no key be found.')

0x04、重新签名

找到了密钥我们就要按照要求把用户名Tom改为WebGoat,同时修改它对对应的时间戳。

 0x05 总结


想要爆破成功有二个因素

  1. 正确高效的字典
  2. 已经得到它的令牌

防御:

  1. 开发人员不应在JWT中暴露敏感信息,可使用工具将截获的JWT解析查看是否包含敏感信息。
  2. JWT弱口令爆破可以离线进行。
  3. JWT的安全性非常依赖密钥的长度及复杂度,建议密钥设置为32位及以上长度的随机字符。

4、javaweb-身份验证攻击-JWT修改伪造冒充


         我认为这是逻辑漏洞的一种方式,其中包含了JWT令牌的相关技术,这一关目的是修改令牌,让Tom进行付款。JWT Refresh Token Manipulation – Mikail's Blog

前置知识:

        就如同session会有存活时长一样,JWT的access_token也是有相类似的机制。session失活后,系统会要求用户再次身份验证,通过则重新颁发session;JWT则可使用refresh token去刷新access token而无需再次身份验证。

WebGoat中提到:

        应在服务器端存储足够的信息,以验证用户是否仍然受信任。您可以考虑的事情有很多,比如存储IP地址,跟踪使用refresh token的次数(在access token的有效时间窗口中多次使用刷新令牌可能表示奇怪的行为,您可以撤销所有token,让用户再次进行身份验证)。还要跟踪哪个access token属于哪个refresh token,否则攻击者可能会使用攻击者的refresh token为其他用户获取新的access token

        这段话中关键信息是,服务器中可能存在:未校验access token和refresh token是否属于同一个用户,导致A用户可使用自己的refresh token去刷新B用户的access token。

0x01、进入靶场

         先用BP抓包,我们可以看到刚开始Authorization的value值为Bearer null,我们的目的是把它改为Tom的令牌

0x02、打开日志


        可以看到有一条token,和一些与refresh相关的url信息。拿token去https://jwt.io/#debugger,可以看到: 

是属于Tom,exp的时间是2018年(已过期)

 我们查看有问题的代码:

  //仅校验是否存在user和refreshToken,未校验两者对应关系,存在漏洞
        if (user == null || refreshToken == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        } else if (validRefreshTokens.contains(refreshToken)) {
            validRefreshTokens.remove(refreshToken);
            //返回JWT user的新token
            return ResponseEntity.ok(createNewTokens(user));
        } else {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }
    }

思路:

  1. 从logfile中获取到Tom到过期JWT
  2. 利用账号密码:Jerry/bm5nhSkxCXZkKRy4 拿到Jerry账号的refresh token
  3. 利用Jerry的refresh token 和Tom的过期access token去刷新一下
  4. 拿到刷新后的token 结账
  5. 从logfile中获取到Tom到过期JWT 

0x03、 拿到refresh token


利用账号密码:Jerry/bm5nhSkxCXZkKRy4 拿到refresh token   

账号密码从源码中可得

 0x04 刷新Token


 0x05 拿到刷新后的access_token 结账


这个签名我们是不知道的,改为nono,再修改时间戳,同上 

0x06 总结


当使用refresh_token机制时,服务器端存储足够的信息,以验证用户是否仍然受信任。(存储IP地址,跟踪使用refresh token的次数及是否在access_token过期后使用等等的信息)

当存在JWT泄漏和越权刷新JWT漏洞时,漏洞发生。

5、javaweb-身份验证攻击-JWT安全结合SQL注入


        本关相对于把SQL注入和JWT认证相结合,实现身份验证失效。

0x01 先用BP抓到Tom下方的Delete数据包


 把JWT数据放到https://jwt.io/#debugger解析一下:

 这个题要有一定代码审计的能力,鄙人说不清楚,感兴趣的可以看看下面文章。

参考:Java代码审计入门:WebGoat8(再会) - FreeBuf网络安全行业门户


网站公告

今日签到

点亮在社区的每一天
去签到