Arjun 1.3 (Improved logic and --include option)
This commit is contained in:
79
arjun.py
79
arjun.py
@@ -10,11 +10,11 @@ from urllib.parse import unquote
|
|||||||
from core.prompt import prompt
|
from core.prompt import prompt
|
||||||
from core.requester import requester
|
from core.requester import requester
|
||||||
from core.colors import red, green, white, end, info, bad, good, run
|
from core.colors import red, green, white, end, info, bad, good, run
|
||||||
from core.utils import e, d, stabilize, flattenParams, randomString, slicer, joiner, unityExtracter
|
from core.utils import e, d, stabilize, randomString, slicer, joiner, unityExtracter, getParams, flattenParams, removeTags
|
||||||
|
|
||||||
print ('''%s _
|
print ('''%s _
|
||||||
/_| _ '
|
/_| _ '
|
||||||
( |/ /(//) %sv1.2-beta%s
|
( |/ /(//) %sv1.3%s
|
||||||
_/ %s''' % (green, white, green, end))
|
_/ %s''' % (green, white, green, end))
|
||||||
|
|
||||||
|
|
||||||
@@ -27,12 +27,14 @@ parser.add_argument('-f', help='file path', dest='file')
|
|||||||
parser.add_argument('--get', help='use get method', dest='GET', action='store_true')
|
parser.add_argument('--get', help='use get method', dest='GET', action='store_true')
|
||||||
parser.add_argument('--post', help='use post method', dest='POST', action='store_true')
|
parser.add_argument('--post', help='use post method', dest='POST', action='store_true')
|
||||||
parser.add_argument('--headers', help='http headers prompt', dest='headers', action='store_true')
|
parser.add_argument('--headers', help='http headers prompt', dest='headers', action='store_true')
|
||||||
|
parser.add_argument('--include', help='include this data in every request', dest='include')
|
||||||
args = parser.parse_args() #arguments to be parsed
|
args = parser.parse_args() #arguments to be parsed
|
||||||
|
|
||||||
url = args.url
|
url = args.url
|
||||||
file = args.file or './db/params.txt'
|
file = args.file or './db/params.txt'
|
||||||
headers = args.headers
|
headers = args.headers
|
||||||
delay = args.delay or 0
|
delay = args.delay or 0
|
||||||
|
include = args.include or {}
|
||||||
threadCount = args.threads or 2
|
threadCount = args.threads or 2
|
||||||
|
|
||||||
def extractHeaders(headers):
|
def extractHeaders(headers):
|
||||||
@@ -51,13 +53,15 @@ def extractHeaders(headers):
|
|||||||
|
|
||||||
if headers:
|
if headers:
|
||||||
headers = extractHeaders(prompt())
|
headers = extractHeaders(prompt())
|
||||||
|
else:
|
||||||
|
headers = {}
|
||||||
|
|
||||||
if args.GET:
|
if args.GET:
|
||||||
GET = True
|
GET = True
|
||||||
else:
|
else:
|
||||||
GET = False
|
GET = False
|
||||||
|
|
||||||
headers = {}
|
include = getParams(include)
|
||||||
|
|
||||||
paramList = []
|
paramList = []
|
||||||
try:
|
try:
|
||||||
@@ -92,59 +96,70 @@ def heuristic(response, paramList):
|
|||||||
url = stabilize(url)
|
url = stabilize(url)
|
||||||
|
|
||||||
print ('%s Analysing the content of the webpage' % run)
|
print ('%s Analysing the content of the webpage' % run)
|
||||||
firstResponse = requester(url, '', headers, GET, delay)
|
firstResponse = requester(url, include, headers, GET, delay)
|
||||||
|
|
||||||
print ('%s Now lets see how target deals with a non-existent parameter' % run)
|
print ('%s Now lets see how target deals with a non-existent parameter' % run)
|
||||||
|
|
||||||
originalFuzz = randomString(6)
|
originalFuzz = randomString(6)
|
||||||
data = {originalFuzz : originalFuzz[::-1]}
|
data = {originalFuzz : originalFuzz[::-1]}
|
||||||
|
data.update(include)
|
||||||
response = requester(url, data, headers, GET, delay)
|
response = requester(url, data, headers, GET, delay)
|
||||||
reflections = response.text.count(originalFuzz[::-1])
|
reflections = response.text.count(originalFuzz[::-1])
|
||||||
print ('%s Reflections: %s%i%s' % (info, green, reflections, end))
|
print ('%s Reflections: %s%i%s' % (info, green, reflections, end))
|
||||||
|
|
||||||
originalHTML = response.text
|
originalResponse = response.text
|
||||||
originalResponse = response.text.replace(originalFuzz + '=' + originalFuzz[::-1], '')
|
|
||||||
originalCode = response.status_code
|
originalCode = response.status_code
|
||||||
print ('%s Response Code: %s%i%s' % (info, green, originalCode, end))
|
print ('%s Response Code: %s%i%s' % (info, green, originalCode, end))
|
||||||
|
|
||||||
newLength = len(response.text) - len(flattenParams(data))
|
newLength = len(response.text)
|
||||||
|
plainText = removeTags(originalResponse)
|
||||||
|
plainTextLength = len(plainText)
|
||||||
print ('%s Content Length: %s%i%s' % (info, green, newLength, end))
|
print ('%s Content Length: %s%i%s' % (info, green, newLength, end))
|
||||||
|
print ('%s Plain-text Length: %s%i%s' % (info, green, plainTextLength, end))
|
||||||
|
|
||||||
|
factors = {'sameHTML': False, 'samePlainText': False}
|
||||||
|
if len(firstResponse.text) == len(originalResponse):
|
||||||
|
factors['sameHTML'] = True
|
||||||
|
elif len(removeTags(firstResponse.text)) == len(plainText):
|
||||||
|
factors['samePlainText'] = True
|
||||||
|
|
||||||
print ('%s Parsing webpage for potenial parameters' % run)
|
print ('%s Parsing webpage for potenial parameters' % run)
|
||||||
heuristic(firstResponse.text, paramList)
|
heuristic(firstResponse.text, paramList)
|
||||||
|
|
||||||
fuzz = randomString(8)
|
fuzz = randomString(8)
|
||||||
data = {fuzz : fuzz[::-1]}
|
data = {fuzz : fuzz[::-1]}
|
||||||
responseMulti = requester(url, data, headers, GET, delay)
|
data.update(include)
|
||||||
multiplier = int((len(responseMulti.text.replace(fuzz + '=' + fuzz[::-1], '')) - len(response.text.replace(originalFuzz + '=' + originalFuzz[::-1], ''))) / 2)
|
|
||||||
print ('%s Content Length Multiplier: %s%i%s' % (info, green, multiplier, end))
|
|
||||||
|
|
||||||
def quickBruter(params, originalResponse, originalCode, delay, headers, url, GET):
|
def quickBruter(params, originalResponse, originalCode, factors, include, delay, headers, url, GET):
|
||||||
newResponse = requester(url, joiner(params), headers, GET, delay)
|
newResponse = requester(url, joiner(params, include), headers, GET, delay)
|
||||||
if newResponse.status_code != originalCode:
|
if newResponse.status_code != originalCode:
|
||||||
return params
|
return params
|
||||||
elif originalResponse and originalResponse != newResponse.text:
|
elif not factors['sameHTML'] and len(newResponse.text) != (len(originalResponse)):
|
||||||
|
return params
|
||||||
|
elif not factors['samePlainText'] and len(removeTags(originalResponse)) != len(removeTags(newResponse.text)):
|
||||||
return params
|
return params
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def bruter(param, originalResponse, originalCode, multiplier, reflections, delay, headers, url, GET):
|
def bruter(param, originalResponse, originalCode, factors, include, reflections, delay, headers, url, GET):
|
||||||
fuzz = randomString(6)
|
fuzz = randomString(6)
|
||||||
data = {param : fuzz}
|
data = {param : fuzz}
|
||||||
|
data.update(include)
|
||||||
response = requester(url, data, headers, GET, delay)
|
response = requester(url, data, headers, GET, delay)
|
||||||
newReflections = response.text.count(fuzz)
|
newReflections = response.text.count(fuzz)
|
||||||
|
reason = False
|
||||||
if response.status_code != originalCode:
|
if response.status_code != originalCode:
|
||||||
print ('%s Found a valid parameter: %s%s%s' % (good, green, param, end))
|
reason = 'Different response code'
|
||||||
print ('%s Reason: Different response code' % info)
|
|
||||||
elif reflections != newReflections:
|
elif reflections != newReflections:
|
||||||
print ('%s Found a valid parameter: %s%s%s' % (good, green, param, end))
|
reason = 'Different number of reflections'
|
||||||
print ('%s Reason: Different number of reflections' % info)
|
elif not factors['sameHTML'] and len(response.text) != (len(originalResponse)):
|
||||||
elif len(response.text.replace(param + '=' + fuzz, '')) != (len(originalResponse.text.replace(originalFuzz + '=' + originalFuzz[::-1], '')) + (len(param) * multiplier)):
|
reason = 'Different content length'
|
||||||
print ('%s Found a valid parameter: %s%s%s' % (good, green, param, end))
|
elif not factors['samePlainText'] and len(removeTags(response.text)) != (len(removeTags(originalResponse))):
|
||||||
print ('%s Reason: Different content length' % info)
|
reason = 'Different plain-text content length'
|
||||||
|
if reason:
|
||||||
if firstResponse.text != originalHTML:
|
return {param : reason}
|
||||||
originalHTML = False
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
print ('%s Performing heuristic level checks' % run)
|
print ('%s Performing heuristic level checks' % run)
|
||||||
|
|
||||||
@@ -152,7 +167,7 @@ def narrower(oldParamList):
|
|||||||
newParamList = []
|
newParamList = []
|
||||||
potenialParameters = 0
|
potenialParameters = 0
|
||||||
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
|
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
|
||||||
futures = (threadpool.submit(quickBruter, part, originalHTML, originalCode, delay, headers, url, GET) for part in oldParamList)
|
futures = (threadpool.submit(quickBruter, part, originalResponse, originalCode, factors, include, delay, headers, url, GET) for part in oldParamList)
|
||||||
for i, result in enumerate(concurrent.futures.as_completed(futures)):
|
for i, result in enumerate(concurrent.futures.as_completed(futures)):
|
||||||
if result.result():
|
if result.result():
|
||||||
potenialParameters += 1
|
potenialParameters += 1
|
||||||
@@ -172,8 +187,16 @@ if foundParams:
|
|||||||
print ('%s Heuristic found %i potenial parameters.' % (info, len(foundParams)))
|
print ('%s Heuristic found %i potenial parameters.' % (info, len(foundParams)))
|
||||||
paramList = foundParams
|
paramList = foundParams
|
||||||
|
|
||||||
|
finalResult = []
|
||||||
|
|
||||||
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
|
threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=threadCount)
|
||||||
futures = (threadpool.submit(bruter, param, originalResponse, originalCode, multiplier, reflections, delay, headers, url, GET) for param in paramList)
|
futures = (threadpool.submit(bruter, param, originalResponse, originalCode, factors, include, reflections, delay, headers, url, GET) for param in foundParams)
|
||||||
for i, _ in enumerate(concurrent.futures.as_completed(futures)):
|
for i, result in enumerate(concurrent.futures.as_completed(futures)):
|
||||||
|
if result.result():
|
||||||
|
finalResult.append(result.result())
|
||||||
print('%s Progress: %i/%i' % (info, i + 1, len(paramList)), end='\r')
|
print('%s Progress: %i/%i' % (info, i + 1, len(paramList)), end='\r')
|
||||||
print('\n%s Scan Completed' % info)
|
print('%s Scan Completed' % info)
|
||||||
|
for each in finalResult:
|
||||||
|
for param, reason in each.items():
|
||||||
|
print ('%s Valid parameter found: %s%s%s' % (good, green, param, end))
|
||||||
|
print ('%s Reason: %s' % (info, reason))
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import re
|
import re
|
||||||
|
import json
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
from core.colors import bad
|
from core.colors import bad
|
||||||
|
|
||||||
def unityExtracter(arrayOfArrays, usable):
|
def unityExtracter(arrayOfArrays, usable):
|
||||||
|
"extracts the value from single valued list from a list of lists"
|
||||||
remainingArray = []
|
remainingArray = []
|
||||||
for array in arrayOfArrays:
|
for array in arrayOfArrays:
|
||||||
if len(array) == 1:
|
if len(array) == 1:
|
||||||
@@ -14,16 +16,20 @@ def unityExtracter(arrayOfArrays, usable):
|
|||||||
return remainingArray
|
return remainingArray
|
||||||
|
|
||||||
def slicer(array, n=2):
|
def slicer(array, n=2):
|
||||||
|
"divides a list into n parts"
|
||||||
k, m = divmod(len(array), n)
|
k, m = divmod(len(array), n)
|
||||||
return list(array[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in range(n))
|
return list(array[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in range(n))
|
||||||
|
|
||||||
def joiner(array):
|
def joiner(array, include):
|
||||||
|
"converts a list of parameters into parameter and value pair"
|
||||||
params = {}
|
params = {}
|
||||||
for element in array:
|
for element in array:
|
||||||
params[element] = randomString(6)
|
params[element] = randomString(6)
|
||||||
|
params.update(include)
|
||||||
return params
|
return params
|
||||||
|
|
||||||
def stabilize(url):
|
def stabilize(url):
|
||||||
|
"picks up the best suiting protocol if not present already"
|
||||||
if 'http' not in url:
|
if 'http' not in url:
|
||||||
try:
|
try:
|
||||||
requests.get('http://%s' % url) # Makes request to the target with http schema
|
requests.get('http://%s' % url) # Makes request to the target with http schema
|
||||||
@@ -42,9 +48,11 @@ def stabilize(url):
|
|||||||
return url
|
return url
|
||||||
|
|
||||||
def removeTags(html):
|
def removeTags(html):
|
||||||
|
"removes all the html from a webpage source"
|
||||||
return re.sub(r'(?s)<.*?>', '', html)
|
return re.sub(r'(?s)<.*?>', '', html)
|
||||||
|
|
||||||
def lineComparer(response1, response2):
|
def lineComparer(response1, response2):
|
||||||
|
"compares two webpage and finds the non-matching lines"
|
||||||
response1 = response1.split('\n')
|
response1 = response1.split('\n')
|
||||||
response2 = response2.split('\n')
|
response2 = response2.split('\n')
|
||||||
num = 0
|
num = 0
|
||||||
@@ -55,8 +63,17 @@ def lineComparer(response1, response2):
|
|||||||
num += 1
|
num += 1
|
||||||
return dynamicLines
|
return dynamicLines
|
||||||
|
|
||||||
def randomString(length):
|
def randomString(n):
|
||||||
return ''.join(random.choice(string.ascii_lowercase) for i in range(length))
|
"generates a random string of length n"
|
||||||
|
return ''.join(random.choice(string.ascii_lowercase) for i in range(n))
|
||||||
|
|
||||||
|
def e(string):
|
||||||
|
"utf encodes a string"
|
||||||
|
return string.encode('utf-8')
|
||||||
|
|
||||||
|
def d(string):
|
||||||
|
"utf decodes a string"
|
||||||
|
return string.decode('utf-8')
|
||||||
|
|
||||||
def flattenParams(params):
|
def flattenParams(params):
|
||||||
flatted = []
|
flatted = []
|
||||||
@@ -64,8 +81,19 @@ def flattenParams(params):
|
|||||||
flatted.append(name + '=' + value)
|
flatted.append(name + '=' + value)
|
||||||
return '?' + '&'.join(flatted)
|
return '?' + '&'.join(flatted)
|
||||||
|
|
||||||
def e(string):
|
def getParams(data):
|
||||||
return string.encode('utf-8')
|
params = {}
|
||||||
|
try:
|
||||||
def d(string):
|
params = json.loads(str(data).replace('\'', '"'))
|
||||||
return string.decode('utf-8')
|
return params
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
if data.startswith('?'):
|
||||||
|
data = data[1:]
|
||||||
|
parts = data.split('&')
|
||||||
|
for part in parts:
|
||||||
|
each = part.split('=')
|
||||||
|
try:
|
||||||
|
params[each[0]] = each[1]
|
||||||
|
except IndexError:
|
||||||
|
params = None
|
||||||
|
return params
|
||||||
|
|||||||
@@ -25887,4 +25887,4 @@ zzv
|
|||||||
zzw
|
zzw
|
||||||
zzx
|
zzx
|
||||||
zzy
|
zzy
|
||||||
zzz
|
zzz
|
||||||
Reference in New Issue
Block a user