BruteXss工具介绍及源码解读

最近在学xss,碰巧在github上发现了这个xss注入检测工具.

github地址:https://github.com/shawarkhanethicalhacker/BruteXSS-1


关于xss的原理可以参考下面这篇文章,我感觉写的挺好。

https://www.cnblogs.com/phpstudy2015-6/p/6767032.html


下面我们就来看看这个工具的源代码,顺便学习下别人是怎么写的。

1.环境

环境:python2.7

2.代码结构

|--brutexss()
|------|again()
|------|wordlistimport(file,lst)
|------|bg(p,status)
|------|complete(p,r,c,d)
|------|GET()
|------|POST()

3.导入的包及用处

mechanize和colorama是下载的,其他都是python自带的。

#代码导入的包
from string import whitespace #用string里的whitespace方法去掉字符串里的空格__
import httplib #一个对http协议进行封装的模块
import urllib    #接受url相关请求的模块
import socket 
import urlparse #主要是用于解析url中的参数  对url按照一定格式进行 拆分或拼接 
import os #关于路径的模块
import sys #用来获取操作系统的一些配置和设置
import time 
from colorama import init , Style, Back,Fore #是一个python专门用来在控制台、命令行输出彩色文字的模块,可以跨平台使用。
import mechanize #模拟浏览器登陆的模块

4.下面来说说这些函数

  • again():
def again():
       inp = raw_input("[?] [E]xit or launch [A]gain? (e/a)").lower()
       if inp == 'a':
           brutexss()
       elif inp == 'e':
           exit()
       else:
           print("[!] Incorrect option selected")
           again()

输入a在再次运行工具,输入e退出,输入其他重新调用函数。

  • wordlistimport(file,lst):
    def wordlistimport(file,lst):
        try:
            with open(file,'r') as f: #Importing Payloads from specified wordlist.
                print(Style.DIM+Fore.WHITE+"[+] Loading Payloads from specified wordlist..."+Style.RESET_ALL)
                for line in f:
                    final = str(line.replace("\n",""))
                    lst.append(final)
        except IOError:
            print(Style.BRIGHT+Fore.RED+"[!] Wordlist not found!"+Style.RESET_ALL)
            again()

打开字典,将字典里的语句放到列表里面,若有异常则执行again()方法。

  • bg(p,status)
        try:
            b = ""
            l = ""
            lostatus = ""
            num = []
            s = len(max(p, key=len)) #list
            if s < 10:
                s = 10
            for i in range(len(p)): num.append(i)
            maxval = str(len(num)) #number
            for i in range(s) : b = b + "-"
            for i in range(len(maxval)):l = l + "-"
            statuslen = len(max(status, key=len))
            for i in range(statuslen) : lostatus = lostatus + "-"
            if len(b) < 10 :
                b = "----------"
            if len(lostatus) < 14:
                lostatus="--------------"
            if len(l) < 2 :
                l = "--"
            los = statuslen
            if los < 14:
                los = 14
            lenb=len(str(len(b)))
            if lenb < 14:
                lenb = 10
            else:
                lenb = 20
            upb = ("+-%s-+-%s-+-%s-+")%(l,b,lostatus)
            print(upb)
            st0 = "Parameters"
            st1 = "Status"
            print("| Id | "+st0.center(s," ")+" | "+st1.center(los," ")+" |")
            print(upb)
            for n,i,d in zip(num,p,status):
                string = (" %s | %s ")%(str(n),str(i));
                lofnum = str(n).center(int(len(l))," ")
                lofstr = i.center(s," ")
                lofst = d.center(los," ")
                if "Not Vulnerable" in lofst:
                    lofst = Fore.GREEN+d.center(los," ")+Style.RESET_ALL
                else:
                    lofst = Fore.RED+d.center(los," ")+Style.RESET_ALL
                print("| "+lofnum+" | "+lofstr+" | "+lofst+" |")
                print(upb)
            return("")
        except(ValueError):
            print(Style.BRIGHT+Fore.RED+"[!] Uh oh! No parameters in URL!"+Style.RESET_ALL)
            again()

命令提示行里的表格

  • complete(p,r,c,d):
    def complete(p,r,c,d):
        print("[+] Bruteforce Completed.")
        if c == 0:
            print("[+] Given parameters are "+Style.BRIGHT+Fore.GREEN+"not vulnerable"+Style.RESET_ALL+" to XSS.")
        elif c ==1:
            print("[+] %s Parameter is "+Style.BRIGHT+Fore.RED+"vulnerable"+Style.RESET_ALL+" to XSS.")%c
        else:
            print("[+] %s Parameters are "+Style.BRIGHT+Fore.RED+"vulnerable"+Style.RESET_ALL+" to XSS.")%c
        print("[+] Scan Result for %s:")%d
        print bg(p,r)
        again()

扫描完成时输出扫描结果。

  • GET() :
    def GET():
            try:
                try:
                    grey = Style.DIM+Fore.WHITE
                    site = raw_input("[?] Enter URL:\n[?] > ") #输入url
                    # 没输入https或http就帮你加上
                    if 'https://' in site:
                        pass
                    elif 'http://' in site:
                        pass
                    else:
                        site = "http://"+site
                    #解析url返回的对象:ParseResult(scheme='https', netloc='www.baidu.com', path='', params='', query='user=1', fragment='')
                    finalurl = urlparse.urlparse(site)
                    # 提取queery里的参数放在一个列表里,[('user', '1')]
                    urldata = urlparse.parse_qsl(finalurl.query)
                    # domain0 : 'https://www.baidu.com/'
                    domain0 = '{uri.scheme}://{uri.netloc}/'.format(uri=finalurl)
                    # domain: 'baidu.com'
                    domain = domain0.replace("https://","").replace("http://","").replace("www.","").replace("/","")
                    print (Style.DIM+Fore.WHITE+"[+] Checking if "+domain+" is available..."+Style.RESET_ALL)
                    # 看网页能不能打开
                    connection = httplib.HTTPConnection(domain)
                    connection.connect()
                    print("[+] "+Fore.GREEN+domain+" is available! Good!"+Style.RESET_ALL)
                    url = site
                    paraname = []
                    paravalue = []
                    # 输入wordlist名称
                    wordlist = raw_input("[?] Enter location of Wordlist (Press Enter to use default wordlist.txt)\n[?] > ")
                    if len(wordlist) == 0:
                        wordlist = 'wordlist.txt'
                        print(grey+"[+] Using Default wordlist..."+Style.RESET_ALL)
                    else:
                        pass
                    payloads = []
                    # 导入wordlist
                    wordlistimport(wordlist,payloads)
                    lop = str(len(payloads))
                    grey = Style.DIM+Fore.WHITE
                    print(Style.DIM+Fore.WHITE+"[+] "+lop+" Payloads loaded..."+Style.RESET_ALL)
                    print("[+] Bruteforce start:") 
                    o = urlparse.urlparse(site)
                    # parse_qs:返回的是字典形式
                    parameters = urlparse.parse_qs(o.query,keep_blank_values=True) #{'user': ['123']}
                    # path:'https://www.baidu.com'
                    path = urlparse.urlparse(site).scheme+"://"+urlparse.urlparse(site).netloc+urlparse.urlparse(site).path
                    # paraname保存的是参数名称,paravalue保存的是参数的值。
                    # paraname['user'],paravalue['123']
                    for para in parameters: #Arranging parameters and values.
                        for i in parameters[para]:
                            paraname.append(para)
                            paravalue.append(i)
                    total = 0
                    c = 0
                    fpar = []
                    fresult = []
                    progress = 0
                    # 构建语句,尝试注入
                    for pn, pv in zip(paraname,paravalue): #Scanning the parameter.
                        print(grey+"[+] Testing '"+pn+"' parameter..."+Style.RESET_ALL)
                        fpar.append(str(pn))
                        for x in payloads: 
                            # 去除x中的所有空格
                            validate = x.translate(None, whitespace)
                            if validate == "":
                                progress = progress + 1
                            else:
                                sys.stdout.write("\r[+] %i / %s payloads injected..."% (progress,len(payloads)))
                                sys.stdout.flush() #在linux里也能一秒输出一个
                                progress = progress + 1
                                enc = urllib.quote_plus(x)# 将url数据进行编码,使之能打印和web服务器接受
                                # data:https://www.baidu.com?user=123+enc
                                data = path+"?"+pn+"="+pv+enc
                                # 打开网址,查看注入的script语句有没有被过滤掉
                                # 若存在网址源代码中,则说明存在xss漏洞
                                page = urllib.urlopen(data)
                                sourcecode = page.read()
                                if x in sourcecode:
                                    print(Style.BRIGHT+Fore.RED+"\n[!]"+" XSS Vulnerability Found! \n"+Fore.RED+Style.BRIGHT+"[!]"+" Parameter:\t%s\n"+Fore.RED+Style.BRIGHT+"[!]"+" Payload:\t%s"+Style.RESET_ALL)%(pn,x)
                                    fresult.append("  Vulnerable  ")
                                    c = 1
                                    total = total+1
                                    progress = progress + 1
                                    break
                                else:
                                    c = 0
                        #  运行完,发现没有漏洞
                        if c == 0:
                            print(Style.BRIGHT+Fore.GREEN+"\n[+]"+Style.RESET_ALL+Style.DIM+Fore.WHITE+" '%s' parameter not vulnerable."+Style.RESET_ALL)%pn
                            fresult.append("Not Vulnerable")
                            progress = progress + 1
                            pass
                        progress = 0
                    complete(fpar,fresult,total,domain)
                # 网址无法访问
                except(httplib.HTTPResponse, socket.error) as Exit:
                    print(Style.BRIGHT+Fore.RED+"[!] Site "+domain+" is offline!"+Style.RESET_ALL)
                    again()
            # 没找到wordlist
            except(KeyboardInterrupt) as Exit:
                print("\nExit...")
  • POST():post不同在于模拟浏览器post请求.代码和GET()差不多,就不贴了。

总结

*1.代码不难,刚好可以用来学习,用了下感觉效率不高,下次可以考虑用多线程等提高效率。
2.扫描的检测不太准确,当然也可能是字典太小的原因。

后记

最近发现了xsser这个梗更好用的工具,接下来准备研究下,嘿嘿嘿。

你可能感兴趣的:(BruteXss工具介绍及源码解读)