Files
nullsecuritynet-tools/scanner/http-enum/source/http-enum
T
Levon 'noptrix' Kayan 485fad8b48 re-commit
2023-11-14 12:04:48 +02:00

334 lines
10 KiB
Python
Executable File

#!/usr/bin/env python2
################################################################################
# ____ _ __ #
# ___ __ __/ / /__ ___ ______ ______(_) /___ __ #
# / _ \/ // / / (_-</ -_) __/ // / __/ / __/ // / #
# /_//_/\_,_/_/_/___/\__/\__/\_,_/_/ /_/\__/\_, / #
# /___/ team #
# #
# http-enum.py - HTTP Enumeration #
# #
# #
# DESCRIPTION #
# Automated HTTP Enumeration v0.4 #
# #
# AUTHOR #
# TheXero - http://www.nullsecurity.net/ #
# #
# NOTES #
# - modified and updated by <noptrix@nullsecurity.net> #
################################################################################
import argparse
import re
import socket
import ssl
import sys
import time
apacheserver = 'Apache'
iisserver = 'Microsoft-IIS'
unknown = 'unknown'
stdMethods = ['GARBAGE / ', 'GET / ', 'HEAD / ', 'PUT /filetocreate.html CY', '\
TRACE / ', 'OPTIONS / ', 'DELETE /filetocreate.html ', 'POST /index.html CY', '\
CONNECT 127.0.0.1:443 ', 'PATCH /index.html CY']
iisMethods = ['BCOPY / CY', 'BDELETE / CY', 'BMOVE / CY','BPROPFIND / CY', 'BPR\
OPPATCH / CY','COPY / CY', 'LOCK / CY', 'MKCOL / CY', 'MOVE / ', 'NOTIFY / ', '\
POLL / ', 'PROPFIND / ', 'PROPPATCH / ', 'SEARCH / ', 'SUBSCRIBE / ', 'UNLOCK /\
', 'UNSUBSCRIBE / ', 'X-MS-ENUMATTS / ']
apacheMethods = ['ACL / ', 'BASELINE-CONTROL / ', 'BCOPY / ', 'BDELETE / ', 'BM\
OVE / ', 'BPROPFIND / ', 'BPROPPATCH / ', 'CHECKIN / ', 'CHECKOUT / ', 'COPY / \
', 'DEBUG / ', 'DELETE / ', 'INDEX / ', 'LABEL / ', 'LOCK / ', 'MERGE / ', 'MKA\
CTIVITY / ', 'MKCOL / ', 'MKWORKSPACE / ', 'MOVE / ', 'NOTIFY / ', 'ORDERPATCH \
/ ', 'PATCH / ', 'POLL / ', 'PROPFIND / ', 'PROPPATCH / ', 'REPORT / ', 'RPC_IN\
_DATA / ', 'RPC_OUT_DATA / ', 'SEARCH / ', 'SUBSCRIBE / ', 'UNCHECKOUT / ', 'UN\
LOCK / ', 'UNSUBSCRIBE / ', 'UPDATE / ', 'VERSION-CONTROL / ', 'X-MS-ENUMATTS /\
']
apache = []
frontpage = []
sharepoint = []
found = []
auth = []
unauth = []
result = False
content = 'Content-Type: text/plain\r\nContent-Length: 4\r\n\r\nabcd'
print ('''
____ _ __
___ __ __/ / /__ ___ ______ ______(_) /___ __
/ _ \/ // / / (_-</ -_) __/ // / __/ / __/ // /
/_//_/\_,_/_/_/___/\__/\__/\_,_/_/ /_/\__/\_, /
/___/ team
************************************************************************
Automated HTTP Enumeration v0.4
************************************************************************
\n''')
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='Examples: %(prog)s -t 192.168.0.1 -d www.example.com -p 443 -v -s -\
l 0.5')
parser.add_argument('-t', dest='target', help='Target IP / Domain', required='y\
es')
parser.add_argument('-c', dest='cookie', help='Cookie to use for enumeration')
parser.add_argument('-d', dest='domain', help='For domains with multiple IPs')
parser.add_argument('-p', dest='port', help='Target port')
parser.add_argument('-l', dest='delay', help='Delay between requests')
parser.add_argument('-s', action='store_true', help='Enable SSL')
parser.add_argument('-v', action='store_true', help='Enable verbose')
parser.add_argument('-h', action='help', help='Print this help message and exit\
')
args = parser.parse_args()
target = args.target
if args.v:
verbose = True
else:
verbose = False
if args.domain:
domain = args.domain
else:
domain = target
if args.s:
s = True
else:
s = False
if args.port:
try:
port = int(args.port)
except Exception as error:
print(error)
sys.exit()
else:
if s == True:
port = 443
else:
port = 80
if args.delay:
try:
delay = float(args.delay)
except Exception as error:
print(error)
sys.exit()
else:
delay = float(0.5)
if args.cookie:
try:
cookie = 'Cookie: ' + args.cookie
except Exception as error:
print(error)
sys.quit()
else:
cookie = ''
def run_threads():
pass
def detect():
try:
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
if s == True:
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.connect((target, port))
ssl_sock.write('HEAD / HTTP/1.1\r\n')
ssl_sock.write('Host: ' + domain + '\r\n')
if cookie != '':
ssl_sock.write(cookie + '\r\n')
ssl_sock.write('\r\n')
data = ssl_sock.read(1024)
ssl_sock.close()
else:
sock.connect((target, port))
sock.send('HEAD / HTTP/1.1\r\n')
sock.send('Host: ' + domain + '\r\n')
if cookie != '':
sock.send(cookie + '\r\n')
sock.send('\r\n')
data = sock.recv(1024)
sock.close()
for item in data.split('\n'):
if 'Server:' in item:
server = item.lower()
if iisserver.lower() in server:
print(server)
enumerate(iisserver)
sys.exit()
elif apacheserver.lower() in server:
print(server)
enumerate(apacheserver)
sys.exit()
else:
print(server)
enumerate(server)
sys.exit()
print('No Server header found!')
enumerate(unknown)
sys.exit()
except Exception as error:
print(error)
sys.exit()
def enumerate(server):
if server == iisserver:
try:
requests = open('enum/sharepoint')
for row in requests:
row = row.strip('\n')
sharepoint.append('GET /' + row + ' ')
requests = open('enum/frontpage')
for row in requests:
row = row.strip('\n')
frontpage.append('GET /' + row + ' ')
methods = stdMethods + iisMethods + frontpage + sharepoint
except Exception as error:
print(error)
print('Using Standard + IIS methods only')
methods = stdMethods + iisMethods
elif server == apacheserver:
try:
requests = open('enum/apache')
for row in requests:
row = row.strip('\n')
apache.append('GET /' + row + ' ')
methods = stdMethods + apacheMethods + apache
except Exception as error:
print(error)
print('Using Standards methods only')
methods = stdMethods
else:
methods = stdMethods
for method in methods:
i = 0
try:
required = False
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(delay)
if method.endswith(' CY'):
required = True
method = method.replace(' CY', ' ')
if s == True:
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.connect((target, port))
ssl_sock.write(method + 'HTTP/1.1\r\n')
ssl_sock.write('Host: ' + domain + '\r\n')
if cookie != '':
ssl_sock.write(cookie + '\r\n')
if required == True:
ssl_sock.write(content)
required = False
ssl_sock.write('\r\n')
data = ssl_sock.read(1024)
ssl_sock.close()
else:
sock.connect((target, port))
sock.send(method + 'HTTP/1.1\r\n')
sock.send('Host: ' + domain + '\r\n')
if cookie != '':
sock.send(cookie + '\r\n')
if required == True:
sock.send(content)
required == False
sock.send('\r\n')
data = sock.recv(1024)
sock.close()
except Exception as error:
continue
try:
rawheader = data.split(' ', 1)[1]
head = data.split('\n', 1)[0]
responce = head.split(' ', 1)[1]
request = method.split(' HTTP/1.', 1)[0]
if verbose == True:
print(request + ': ' + responce)
if responce.startswith('200'):
found.append(request)
elif responce.startswith('403'):
auth.append(request)
elif responce.startswith('401'):
unauth.append(request)
except:
print('Error in filtering the responce',method, ':', data)
if len(found) > 0:
result = True
if 'GARBAGE / ' in found:
print('\r\n\033[1mValid (Unreliable):\033[0;0m\r')
found.pop(0)
else:
print('\r\n\033[1mValid:\033[0;0m\r')
found.append('')
for item in found:
print(item)
if len(auth) > 0:
result = True
if 'GARBAGE / ' in auth:
print('\033[1mAuthentication Required (Unreliable):\033[0;0m\r')
auth.pop(0)
else:
print('\033[1mAuthentication Required:\033[0;0m\r')
auth.append('')
for item in auth:
print(item)
if len(unauth) > 0:
result = True
print('\033[1mUnauthorized:\033[0;0m\r')
unauth.append('')
for item in unauth:
print(item)
if result == False:
print('\033[1mNo Methods accepted!\033[0;0m\r')
print('Try using a cookie! [-c]')
if __name__ == '__main__':
detect()