mirror of
https://github.com/nullsecuritynet/tools
synced 2026-06-08 16:27:39 +00:00
334 lines
10 KiB
Python
Executable File
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()
|