Projects STRLCPY pentest-tools Commits e64d60b0
🤬
  • ■ ■ ■ ■ ■ ■
    mput.py
     1 +#!/usr/bin/python3
     2 + 
     3 +# I don't believe in license.
     4 +# You can do whatever you want with this program.
     5 + 
     6 +import os
     7 +import sys
     8 +import re
     9 +import time
     10 +import copy
     11 +import random
     12 +import argparse
     13 +import requests
     14 +import urllib.parse
     15 +from functools import partial
     16 +from threading import Thread
     17 +from queue import Queue
     18 +from multiprocessing.dummy import Pool
     19 +from colored import fg, bg, attr
     20 + 
     21 +MAX_EXCEPTION = 100
     22 +MAX_VULNERABLE = 100
     23 + 
     24 +# disable "InsecureRequestWarning: Unverified HTTPS request is being made."
     25 +from requests.packages.urllib3.exceptions import InsecureRequestWarning
     26 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
     27 + 
     28 +t_history = []
     29 + 
     30 +def banner():
     31 + print("""
     32 + _
     33 + _ __ ___ _ __ _ _ | |_ _ __ _ _
     34 + | '_ ` _ \ | '_ \ | | | | | __| | '_ \ | | | |
     35 + | | | | | | | |_) | | |_| | | |_ _ | |_) | | |_| |
     36 + |_| |_| |_| | .__/ \__,_| \__| (_) | .__/ \__, |
     37 + |_| |_| |___/
     38 + 
     39 + by @gwendallecoguic
     40 + 
     41 +""")
     42 + pass
     43 + 
     44 + 
     45 +def rebuiltQuery( t_params ):
     46 + query = ''
     47 + for pname,t_values in t_params.items():
     48 + for k in range(len(t_values)):
     49 + query = query + pname+'='+t_values[k] + '&'
     50 + return query.strip('&')
     51 + 
     52 + 
     53 +def _parse_qs( query ):
     54 + t_params = {}
     55 + tmptab = query.split('&')
     56 + 
     57 + for param in tmptab:
     58 + t_param = param.split('=')
     59 + pname = t_param[0]
     60 + if not pname in t_params:
     61 + t_params[pname] = []
     62 + pvalue = '' if len(t_param) < 2 else t_param[1]
     63 + t_params[pname].append( pvalue )
     64 + 
     65 + return t_params
     66 + 
     67 + 
     68 +def testPath( t_urlparse ):
     69 + path = ''
     70 + t_path = ['/'] + t_urlparse.path.split('/')
     71 + # print(t_urlparse)
     72 + # print(t_path)
     73 + # return
     74 + for dir in t_path:
     75 + # print("> "+dir)
     76 + if len(dir):
     77 + # print(dir)
     78 + if not dir == '/':
     79 + path = path + dir + '/'
     80 + else:
     81 + path = path + dir
     82 + # else:
     83 + # path = path.replace('//','/')
     84 + 
     85 + if '.' in dir and dir == t_path[len(t_path)-1]:
     86 + path = path.rstrip('/')
     87 + 
     88 + new_value = path
     89 + # new_value = path + '/'
     90 + # new_value = new_value.replace('//','/')
     91 + t_urlparse = t_urlparse._replace(path=new_value)
     92 + url = urllib.parse.urlunparse(t_urlparse)
     93 + doTest( url )
     94 + 
     95 + 
     96 +def testPayload( url, tmp ):
     97 + # print(url)
     98 + t_urlparse = urllib.parse.urlparse( url )
     99 + 
     100 + testPath( t_urlparse )
     101 + 
     102 + 
     103 +def testURL( url ):
     104 + time.sleep( 0.01 )
     105 + t_multiproc['n_current'] = t_multiproc['n_current'] + 1
     106 + 
     107 + if _verbose <= 1:
     108 + sys.stdout.write( 'progress: %d/%d\r' % (t_multiproc['n_current'],t_multiproc['n_total']) )
     109 + # t_multiproc['n_current'] = t_multiproc['n_current'] + 1
     110 + 
     111 + # testPayload(url,0)
     112 + pool = Pool( 1 )
     113 + pool.map( partial(testPayload,url), 'dummy' )
     114 + pool.close()
     115 + pool.join()
     116 + 
     117 + 
     118 +def doTest( url, method='GET', post_params='' ):
     119 + 
     120 + # with open('generated_urls', 'a+') as fp:
     121 + # fp.write(url+"\n")
     122 + # return
     123 + 
     124 + # t_realdotest.append( [url,method,post_params] )
     125 + realDoTest( [url,method,post_params] );
     126 + return
     127 + 
     128 + 
     129 +def realDoTest( t_params ):
     130 + 
     131 + vuln = '-'
     132 + status_code = 0
     133 + content_type = '-'
     134 + method_found = []
     135 + url = t_params[0]
     136 + # print(url)
     137 + method = t_params[1]
     138 + post_params = t_params[2]
     139 + 
     140 + if url in t_history:
     141 + return
     142 + 
     143 + t_history.append(url)
     144 + 
     145 + if _verbose <= 1:
     146 + sys.stdout.write( 'progress: %d/%d\r' % (t_multiproc['n_current'],t_multiproc['n_total']) )
     147 + # t_multiproc['n_current'] = t_multiproc['n_current'] + 1
     148 + 
     149 + t_urlparse = urllib.parse.urlparse(url)
     150 + u = t_urlparse.scheme + '_' + t_urlparse.netloc
     151 + 
     152 + # if not u in t_exceptions:
     153 + # t_exceptions[u] = 0
     154 + # if t_exceptions[u] >= MAX_EXCEPTION:
     155 + # if _verbose >= 3 and _verbose < 4:
     156 + # print("skip too many exceptions %s" % t_urlparse.netloc)
     157 + # return
     158 + 
     159 + # if not u in t_vulnerable:
     160 + # t_vulnerable[u] = 0
     161 + # if t_vulnerable[u] >= MAX_VULNERABLE:
     162 + # if _verbose >= 3 and _verbose < 4:
     163 + # print("skip already vulnerable %s" % t_urlparse.netloc)
     164 + # return
     165 + 
     166 + try:
     167 + r = requests.request( 'OPTIONS', url, data=post_params, headers=t_custom_headers, timeout=5, verify=False )
     168 + except Exception as e:
     169 + # t_exceptions[u] = t_exceptions[u] + 1
     170 + if _verbose >= 3 and _verbose < 4:
     171 + sys.stdout.write( "%s[-] error occurred: %s%s\n" % (fg('red'),e,attr(0)) )
     172 + return
     173 + 
     174 + status_code = r.status_code
     175 + 
     176 + # print(r.headers)
     177 + if 'Content-Type' in r.headers:
     178 + content_type = r.headers['Content-Type']
     179 + 
     180 + if 'Allow' in r.headers and 'PUT' in r.headers['Allow']:
     181 + r_fail = False
     182 + method_found.append('PUT')
     183 + post_params = 'test=test'
     184 + try:
     185 + r_put = requests.request( 'PUT', url, data=post_params, headers=t_custom_headers, timeout=5, verify=False )
     186 + except Exception as e:
     187 + # t_exceptions[u] = t_exceptions[u] + 1
     188 + r_fail = True
     189 + if _verbose >= 3 and _verbose < 4:
     190 + sys.stdout.write( "%s[-] error occurred: %s%s\n" % (fg('red'),e,attr(0)) )
     191 + 
     192 + if not r_fail:
     193 + # print(r_put.headers)
     194 + # print(r_put.status_code)
     195 + status_code = r_put.status_code
     196 + 
     197 + if 'Content-Type' in r_put.headers:
     198 + content_type = r_put.headers['Content-Type']
     199 + else:
     200 + content_type = '-'
     201 + 
     202 + if r_put.status_code >= 200 and r_put.status_code < 300:
     203 + vuln = 'VULNERABLE'
     204 + 
     205 + if 'Allow' in r.headers and 'DELETE' in r.headers['Allow']:
     206 + method_found.append('DELETE')
     207 + 
     208 + output = '%s\t\tC=%d\t\tT=%s\t\tM=%s\t\tV=%s\n' % (url,status_code,content_type,','.join(method_found),vuln)
     209 + 
     210 + fp = open( t_multiproc['f_output'], 'a+' )
     211 + fp.write( output )
     212 + fp.close()
     213 + 
     214 + if vuln == 'VULNERABLE' or (_verbose >= 2 and _verbose < 4):
     215 + if vuln == 'VULNERABLE':
     216 + sys.stdout.write( '%s%s%s' % (fg('light_red'),output,attr(0)) )
     217 + else:
     218 + if len(method_found):
     219 + sys.stdout.write( '%s%s%s' % (fg('light_yellow'),output,attr(0)) )
     220 + else:
     221 + sys.stdout.write( output )
     222 + 
     223 + 
     224 +parser = argparse.ArgumentParser()
     225 +parser.add_argument( "-a","--path",help="set paths list" )
     226 +parser.add_argument( "-d","--header",help="custom headers, example: cookie1=value1;cookie2=value2...", action="append" )
     227 +parser.add_argument( "-o","--hosts",help="set host list (required or -u)" )
     228 +# parser.add_argument( "-r","--redirect",help="follow redirection" )
     229 +parser.add_argument( "-s","--scheme",help="scheme to use, default=http,https" )
     230 +parser.add_argument( "-t","--threads",help="threads, default 10" )
     231 +parser.add_argument( "-u","--urls",help="set url list (required or -o)" )
     232 +parser.add_argument( "-v","--verbose",help="display output, 0=nothing, 1=only vulnerable, 2=all requests, 3=full debug, 4=only vulnerable,no extra text like banner, default: 1" )
     233 +parser.parse_args()
     234 +args = parser.parse_args()
     235 + 
     236 +if args.verbose:
     237 + _verbose = int(args.verbose)
     238 +else:
     239 + _verbose = 1
     240 + 
     241 +if _verbose < 4:
     242 + banner()
     243 + 
     244 +if args.scheme:
     245 + t_scheme = args.scheme.split(',')
     246 +else:
     247 + t_scheme = ['http','https']
     248 + 
     249 +t_custom_headers = {}
     250 +if args.header:
     251 + for header in args.header:
     252 + if ':' in header:
     253 + tmp = header.split(':')
     254 + t_custom_headers[ tmp[0].strip() ] = tmp[1].strip()
     255 + 
     256 +t_hosts = []
     257 +if args.hosts:
     258 + if os.path.isfile(args.hosts):
     259 + fp = open( args.hosts, 'r' )
     260 + t_hosts = fp.read().strip().split("\n")
     261 + fp.close()
     262 + else:
     263 + t_hosts.append( args.hosts )
     264 +n_hosts = len(t_hosts)
     265 +if _verbose < 4:
     266 + sys.stdout.write( '%s[+] %d hosts found: %s%s\n' % (fg('green'),n_hosts,args.hosts,attr(0)) )
     267 + 
     268 +t_urls = []
     269 +if args.urls:
     270 + if os.path.isfile(args.urls):
     271 + fp = open( args.urls, 'r' )
     272 + t_urls = fp.read().strip().split("\n")
     273 + fp.close()
     274 + else:
     275 + t_urls.append( args.urls )
     276 +else:
     277 + while True:
     278 + try:
     279 + url = input()
     280 + except EOFError:
     281 + break
     282 + else:
     283 + t_urls.append( url )
     284 + 
     285 +n_urls = len(t_urls)
     286 +if _verbose < 4:
     287 + sys.stdout.write( '%s[+] %d urls found: %s%s\n' % (fg('green'),n_urls,args.urls,attr(0)) )
     288 + 
     289 +if n_hosts == 0 and n_urls == 0:
     290 + parser.error( 'hosts/urls list missing' )
     291 + 
     292 +t_path = [ '' ]
     293 +if args.path:
     294 + if os.path.isfile(args.path):
     295 + fp = open( args.path, 'r' )
     296 + t_path = fp.read().strip().split("\n")
     297 + fp.close()
     298 + else:
     299 + t_path.append( args.path )
     300 +n_path = len(t_path)
     301 +if _verbose < 4:
     302 + sys.stdout.write( '%s[+] %d path found: %s%s\n' % (fg('green'),n_path,args.path,attr(0)) )
     303 + 
     304 +if args.threads:
     305 + _threads = int(args.threads)
     306 +else:
     307 + _threads = 10
     308 + 
     309 +t_totest = []
     310 +u_max_length = 0
     311 +d_output = os.getcwd()+'/mput'
     312 +f_output = d_output + '/' + 'output'
     313 +if not os.path.isdir(d_output):
     314 + try:
     315 + os.makedirs( d_output )
     316 + except Exception as e:
     317 + sys.stdout.write( "%s[-] error occurred: %s%s\n" % (fg('red'),e,attr(0)) )
     318 + exit()
     319 + 
     320 +if _verbose < 4:
     321 + sys.stdout.write( '%s[+] options are -> threads:%d, verbose:%d%s\n' % (fg('green'),_threads,_verbose,attr(0)) )
     322 + 
     323 +for scheme in t_scheme:
     324 + for host in t_hosts:
     325 + for path in t_path:
     326 + u = scheme + '://' + host.strip() + path
     327 + t_totest.append( u )
     328 + l = len(u)
     329 + if l > u_max_length:
     330 + u_max_length = l
     331 + 
     332 +for url in t_urls:
     333 + for path in t_path:
     334 + u = url.strip() + path
     335 + t_totest.append( u )
     336 + l = len(u)
     337 + if l > u_max_length:
     338 + u_max_length = l
     339 + 
     340 +n_totest = len(t_totest)
     341 + 
     342 +# random.shuffle(t_totest)
     343 +# print("\n".join(t_totest))
     344 +# exit()
     345 + 
     346 +t_realdotest = []
     347 +t_exceptions = {}
     348 +t_vulnerable = {}
     349 +t_multiproc = {
     350 + 'n_current': 0,
     351 + 'n_total': n_totest,
     352 + 'u_max_length': u_max_length+5,
     353 + 'd_output': d_output,
     354 + 'f_output': f_output,
     355 +}
     356 + 
     357 +def doWork():
     358 + while True:
     359 + url = q.get()
     360 + testURL( url )
     361 + q.task_done()
     362 + 
     363 +q = Queue( _threads*2 )
     364 + 
     365 +for i in range(_threads):
     366 + t = Thread( target=doWork )
     367 + t.daemon = True
     368 + t.start()
     369 + 
     370 +try:
     371 + for url in t_totest:
     372 + q.put( url )
     373 + q.join()
     374 +except KeyboardInterrupt:
     375 + sys.exit(1)
     376 + 
     377 + 
Please wait...
Page is in error, reload to recover