Adding switch --jwt
Some checks are pending
/ build (macos-latest, 3.8) (push) Waiting to run
/ build (ubuntu-latest, pypy-2.7) (push) Waiting to run
/ build (windows-latest, 3.14) (push) Waiting to run

This commit is contained in:
Miroslav Štampar 2026-07-25 22:40:12 +02:00
parent b2f98b61ec
commit edbfca0b8e
12 changed files with 862 additions and 4 deletions

View file

@ -1276,6 +1276,41 @@ def heuristicCheckSqlInjection(place, parameter):
return kb.heuristicTest
def checkJWT():
"""
Passive, always-on heuristic: surface any JSON Web Token the request carries (cookie, header or
parameter) together with its offline weaknesses (alg:none, guessable HMAC secret, unsafe key
headers, missing expiry), hinting at '--jwt' for active confirmation and injection.
"""
if kb.jwtChecked or conf.jwt:
return
kb.jwtChecked = True
from lib.utils.jwt import auditJWT
from lib.utils.jwt import findJWTs
from lib.core.settings import JWT_COMMON_SECRETS
haystacks = list((conf.parameters or {}).values())
haystacks += [value for _, value in (conf.httpHeaders or [])]
seen = set()
for haystack in haystacks:
for token in findJWTs(haystack):
if token in seen:
continue
seen.add(token)
infoMsg = "heuristic (JWT) test shows that the request carries a JSON Web Token (rerun with switch '--jwt')"
logger.info(infoMsg)
for _, severity, summary, __ in auditJWT(token, secrets=JWT_COMMON_SECRETS):
logger.info("JWT weakness (%s): %s" % (severity, summary))
if conf.beep:
beep()
def checkDynParam(place, parameter, value):
"""
This function checks if the URL parameter is dynamic. If it is

View file

@ -16,6 +16,7 @@ from lib.controller.action import action
from lib.controller.checks import checkConnection
from lib.controller.checks import checkDynParam
from lib.controller.checks import checkInternet
from lib.controller.checks import checkJWT
from lib.controller.checks import checkNullConnection
from lib.controller.checks import checkSqlInjection
from lib.controller.checks import checkStability
@ -529,12 +530,14 @@ def start():
checkWaf()
if conf.mineParams and not any((conf.graphql, conf.nosql, conf.ldap, conf.xpath, conf.ssti, conf.xxe, conf.hql)):
checkJWT()
if conf.mineParams and not any((conf.graphql, conf.nosql, conf.ldap, conf.xpath, conf.ssti, conf.xxe, conf.hql, conf.jwt)):
from lib.utils.paraminer import mineParameters
mineParameters()
if any((conf.graphql, conf.nosql, conf.ldap, conf.xpath, conf.ssti, conf.xxe, conf.hql)) and (conf.reportJson or conf.resultsFile):
singleTimeWarnMessage("'--report-json'/'--results-file' do not (yet) capture non-SQL technique (--graphql/--nosql/--ldap/--xpath/--ssti/--xxe/--hql) findings; these are reported on the console only")
if any((conf.graphql, conf.nosql, conf.ldap, conf.xpath, conf.ssti, conf.xxe, conf.hql, conf.jwt)) and (conf.reportJson or conf.resultsFile):
singleTimeWarnMessage("'--report-json'/'--results-file' do not (yet) capture non-SQL technique (--graphql/--nosql/--ldap/--xpath/--ssti/--xxe/--hql/--jwt) findings; these are reported on the console only")
if conf.graphql:
from lib.techniques.graphql.inject import graphqlScan
@ -571,6 +574,11 @@ def start():
hqlScan()
continue
if conf.jwt:
from lib.techniques.jwt.inject import jwtScan
jwtScan()
continue
if conf.nullConnection:
checkNullConnection()