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

python之Thread初体验

发布时间:July 27, 2015 // 分类:工作日志,开发笔记,运维工作,代码学习,python,windows,生活琐事 // No Comments

最开始的原因是因为某个哥们在拿着burp反复的提交着某个页面的某个参数

看不下去了。建议拿脚本写一个来提交。然后要求使用多线程进行

#!python
#-*- coding:utf8 -*-
#Author saline
#Email nophacker@gmail.com

import requests,threading
from time import sleep, ctime

class MyThread(threading.Thread):
#创建MyThread类,用于继承threading.Thread类。
    def __init__(self,func,args,name=''):
    #使用类的初始化方法对func、args、name等参数进行初始化。
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args
    
    def run(self):
        apply(self.func,self.args)
    #apply(func [, args [, kwargs ]]) 函数用于当函数参数已经存在于一个元组或字典中时,间接地调用函数。args是一个包含将要提供给函数的按位置传递的参数的元组。如果省略了args,任何参数都不会被传递,kwargs是一个包含关键字参数的字典。    

def post():
    header = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
       'Origin':'http://support.0day5.com',
       'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36',
       'Content-Type':'multipart/form-data; boundary=----WebKitFormBoundaryuOYBiRdLALEyGT1o',
       'Referer':'http://support.0day5.com/request/new/',
       'Cookie':'SERVER_ID=yyyyyyyyyyyyyyyyyy; request_ticket_view=list; PHPSESSID=xxxxxxxxxxxxxxxxxxxxxxx',
       'Accept-Language':'zh-CN,zh;q=0.8',
       'Accept-Encoding':'gzip, deflate',
       'X-client-IP':'127.0.0.1'}#好麻烦的。直接不打算继续使用了
    posturl = "http://support.0day5.com/request/new/"
    postdata='------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"yform_ticket_form\"\r\n\r\n1<\">testetstetst\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"TicketForm[requester_id]\"\r\n\r\n486347\">testetstetst\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"TicketForm[title]\"\r\n\r\n##\">testetstetst\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"TicketForm[field_1910]\"\r\n\r\nwww.0cx.cc\">testetstetst\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"TicketForm[content]\"\r\n\r\n<p>\r\n</p><p><br/>testetstetst</p>\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryuOYBiRdLALEyGT1o--'
    r = requests.post(posturl,postdata,headers = header)
    print r.history
    #打印状态码
threads = []
for i in xrange(20):
    t = MyThread(post,())
    threads.append(t)
    t.start()
    print 'end:%s' %ctime()
        

赶紧去看看自己的邮箱提醒

整合了最近整理的东西

发布时间:July 27, 2015 // 分类:工作日志,开发笔记,运维工作,代码学习,python,windows,生活琐事 // No Comments

最近整理了下几个扫描器的命令行运行的东西。

appscan

AppScanCMD.exe /e /su http://127.0.0.1 /pf d:\\self.policy /st d:\\self.scant /msev Low /tt Application /rt Html /rf d:\localhost.Html
比较有效的


AppScanCMD.exe /e /su http://127.0.0.1 /pf d:\\self.policy /st d:\\self.scant /msev Low /tt Infrastructure /rt Html /rf d:\localhost.Html

AppScanCMD.exe /e /su http://127.0.0.1 /pf d:\\self.policy /st d:\\self.scant /msev Low /tt All /rt Html /rf d:\localhost.Html

AppScanCMD.exe /e /su http://127.0.0.1 /pf d:\\self.policy /st d:\\self.scant /msev Medium /tt All /rt Html /rf d:\localhost.Html

AppScanCMD.exe /e /su http://127.0.0.1 /pf d:\\self.policy /st d:\\self.scant /msev High /tt All /rt Html /rf d:\localhost.Html

然后是AWVS

wvs_console /Scan http://127.0.0.1  /Profile ws_default /saveFolder d:\ --GetFirstOnly=false --FetchSubdirs=true --RestrictToBaseFolder=true --ForceFetchDirindex=true --SubmitForms=true --RobotsTxt=true --CaseInsensitivePaths=false --UseCSA=true --UseAcuSensor=true --EnablePortScanning=false --UseSensorDataFromCrawl=revalidate --ScanningMode=Heuristic --TestWebAppsOnAllDirs=false --ManipHTTPHeaders=true /GenerateReport /ReportFormat pdf

于是稍微整理下

#!python
#-*- coding:utf8 -*-
#Author saline
#Email nophacker@gmail.com
import sys,os
from optparse import OptionParser 

appscancmd = r'D:\\"Program Files"\\IBM\\"AppScan Standard"\\AppScanCMD.exe'
wvs_console = r'D:\\"Program Files"\\Acunetix\\"Scanner"\\wvs_console.exe'
saveFolder = r'D:\\work\\'

def init_parser():
    usage = "Usage: %prog --host http://www.example.com --scan awvs"
    parser = OptionParser(usage=usage, description="AppScanCMD AND AWVS_console scan")
    parser.add_option("--host", type="str", dest="host", help="remote host name")
    parser.add_option("--scan", type="str", dest="command", help="chose what scan.just appscan and wvscmd")
    return parser

def scan(url,scan):
        if 'http' in url:
                name = url.split('//')[1].replace('/','')
                url = url
        else:
                name = url.replace('\n','')
                url = 'http://'+url
        #appcmd = ('%s /e /su %s /pf d:\\self.policy /st d:\\self.scant /msev Medium /tt All /rt pdf /rf d:\\work\\%s\\appscan.pdf')%(appscancmd,url,name)
        appcmd = ('%s /e /su %s /st d:\\self.scant /msev Medium /tt All /rt pdf /rf %s%s\\appscan.pdf')%(appscancmd,url,saveFolder,name)
        wvscmd =('%s /Scan %s  /Profile ws_default /saveFolder %s%s --GetFirstOnly=false --FetchSubdirs=true --RestrictToBaseFolder=true --ForceFetchDirindex=true --SubmitForms=true --RobotsTxt=true --CaseInsensitivePaths=false --UseCSA=true --UseAcuSensor=true --EnablePortScanning=false --UseSensorDataFromCrawl=revalidate --ScanningMode=Heuristic --TestWebAppsOnAllDirs=false --ManipHTTPHeaders=true /GenerateReport /ReportFormat pdf')%(wvs_console,url,saveFolder,name)
        if 'appscan' in scan:
            cmd = appcmd
        else:
            cmd = wvscmd
        os.system(cmd)

def main():
    parser = init_parser()
    option, _ = parser.parse_args()
    domain = option.host
    command  = option.command

    if not domain:
        parser.print_help()
        sys.exit(0)

    domain = domain if domain.startswith('http') else "http://{domain}".format(domain=domain)
    domain = domain if not domain.endswith('/') else domain[:-1]
    return scan(domain,command)


if __name__ == "__main__":
        main()

使用的方法也是很简单

python scan.py
Usage: scan.py --host http://www.example.com --scan awvs

AppScanCMD AND AWVS_console scan

Options:
  -h, --help      show this help message and exit
  --host=HOST     remote host name
  --scan=COMMAND  chose what scan.just appscan and wvscmd

awvs

发现野生的设计一枚.

扫描核心为awvs console,用nginx反向代理+DNSsever解决了,登录认证问题(大部分情况)

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 模式下才能使用该特性,图形界面下暂不支持这功能。

About Acunetix WVS Console

发布时间:July 24, 2015 // 分类:开发笔记,工作日志,运维工作,python,windows,生活琐事 // 6 Comments

今天看到一个大牛在弄一个基于windows和linux下各自扫描器的分布式的系统。由于不同的扫描工具,所运行的环境有所不同,导致我们的扫描系统有必要兼容不同的系统。比如hydra, openvas等工具,它们是比较适合运行在Linux上,而WVS,appscan等工具是运行在Windows上,所以我们有必要同时兼容这两大类系统。如果再深入一点,Linux也分为很多种不同的系统,比如CentOS, Ubuntu,Redhat等,而且即便相同的系统,内核版本不同的话,运行环境也是有很大的区别。

然而今天思考的问题是在windows下进行的AWVS扫描。主要调用了Awvs的命令行wvs_console.exe

>> USAGE: wvs_console /Scan [URL]  OR  /Crawl [URL]  OR  /ScanFromCrawl [FILE]
                      OR  /ScanWSDL [WSDL URL]

>> PARAMETERS                                                                        //参数
       /Scan [URL]               : Scan specified URL                                //扫描特定的URL
       /Crawl [URL]              : Crawl specified URL                               //检索指定的url
       /ScanFromCrawl [FILE]     : Scan from crawling results                        //扫描检索的结果
       /ScanWSDL [WSDL URL]      : Scan web services from WSDL URL                   //扫描来自wsdl的参数URL

       /Profile [PROFILE_NAME]   : Use specified scanning profile during scanning    //使用指定的扫描配置进行扫描
       /Settings [FILE]          : Use specified settings template during scanning   //使用指定的设置模板进行扫描
       /LoginSeq [FILE]          : Use specified login sequence                      //使用指定的登录序列
       /Import [FILE(s)]         : Import files during crawl                         //导入检索的地址进行爬行
       /Run [command line]       : Run this command during crawl                     //
       /Selenium [FILE]          : Execute selenium script during crawl              //执行selenium脚本进行爬行

       /Save                     : Save scan results                                 //保存结果
       /SaveFolder [DIR]         : Specify the folder were all the saved data will be stored //保存记录的目录
       /GenerateZIP              : Compress all the saved data into a zip file       //对所有的数据进行zip压缩
       /ExportXML                : Exports results as XML                            //将结果以XML方式导出
       /ExportAVDL               : Exports results as AVDL                           //将结果以AVDL方式导出
       /SavetoDatabase           : Save alerts to the database                       //把警告数据保存进数据库
       /SaveLogs                 : Save scan logs                                    //保存扫描日志
       /SaveCrawlerData          : Save crawler data (.CWL file)                     //保存检索(爬行)数据
       /GenerateReport           : Generate a report after the scan was completed    //扫描完成后生成报告
       /ReportFormat [FORMAT]    : Generated report format (REP, PDF, RTF, HTML)     //生成报告的格式
       /ReportTemplate [TEMPLATE]: Specify the report template                       //特定的报告模板
       /Timestamps               : Print current timestamp with each line.           //打印每行的时间戳
       /SendEmail                : Send email notification when scan is completed, using scheduler settings. //扫描结束后发送电子邮件
       /EmailAddress [EMAIL]     : Send email notification to this email address, override scheduler settings. //邮件地址会把之前设置的给覆盖掉

       /Verbose                  : Enable verbose mode                               //开启细节模式。也就是发送的具体参数
       /Password                 : Application password (if required)                //如果有需要写入密码
       /?                        : Show this help screen                             //没得说,帮助

>> OPTIONS [ ? = TRUE or FALSE ]                                                   //选项  =true 或者是=false
       --GetFirstOnly=?          : Get only the first URL                            //仅仅获取第一个url
       --RestrictToBaseFolder=?  : Do not fetch anything above start folder          //不扫描当前目录以上的其他目录(扫描二级目录有效)
       --FetchSubdirs=?          : Fetch files bellow base folder                    //
       --ForceFetchDirindex=?    : Fetch directory indexes even if not linked        //扫描目录,即使该目录不再链接里面(就是目录匹配)
       --RobotsTxt=?             : Retrieve and process robots.txt                   //从robots.txt里面获取目录进行爬行
       --CaseInsensitivePaths=?  : Use case insensitive paths                        //
       --UseWebKit=?             : Use WebKit based browser for discovery            //使用基于WebKit的浏览器
       --ScanningMode=*          : Scanning mode (* = Quick, Heuristic, Extensive)   //扫描模式(快速、启发式、广泛的)
       --ManipHTTPHeaders=?      : Manipulate HTTP headers                           //http头可以修改(个人暂时理解为可以修改http头进行提交)
       --UseAcuSensor=?          : Use AcuSensor technology                          //使用AcuSensor 技术(不明所以)
       --EnablePortScanning=?    : Enable port scanning                              //启用端口扫描
       --UseSensorDataFromCrawl=*: Use sensor data from crawl(* = Yes, No, Revalidate) //抓取fuzz提交的数据( = 是,否,重新验证)
       --HtmlAuthUser=?          : Username for HTML based authentication            //基于HTTP认证的用户名
       --HtmlAuthPass=?          : Password for HTML based authentication            //基于HTTP认证的密码
       --ToolTimeout=?           : Timeout for testing tool in seconds               //设置提交的超时时间

>> EXAMPLES
wvs_console /Scan http://testphp.vulnweb.com  /SaveFolder c:\temp\scanResults\ /Save
wvs_console /ScanWSDL http://test/WS.asmx?WSDL /Profile ws_default /Save
wvs_console /Scan http://testphp.vulnweb.com /Profile default /Save --UseWebKit=false --ScanningMode=Heuristic]]

那么扫描的命令我就这样子使用了

wvs_console.exe /Scan http://testphp.vulnweb.com /Profile ws_default /save /savetodatabase --GetFirstOnly=false --FetchSubdirs=true --Re
strictToBaseFolder=true --ForceFetchDirindex=true --SubmitForms=true --RobotsTxt=true --CaseInsensitivePaths=false --UseCSA=true --Us
eAcuSensor=true --EnablePortScanning=false --UseSensorDataFromCrawl=revalidate --ScanningMode=Heuristic --TestWebAppsOnAllDirs=false
--ManipHTTPHeaders=true

既然如此,那么批量扫描也是就是顺理成章的事情了

#!/usr/bin/python
# coding: UTF-8
'''
wvs_console 批量扫描脚本
'''

import sys,os,time

urllist = r'd:\\urllist.txt'    #需扫描网站列表文件
savefolder = r'd:\\result\\'    #扫描结果保存路劲
wvs_console = r'F:\\"Program Files (x86)"\\Acunetix\\"Scanner 10"\\wvs_console.exe' #wvs_console路径


def scan(url,folder):
    if 'http' in url:
        name = url.split('//')[1].replace('/','')
        url = url
    else:
        name = url.replace('\n','')
        url = 'http://'+url
    name = name.replace('\n','')
    url = url.replace('\n','')
    if name in os.listdir(folder):
        print '%s has scaned'%name
    else:
#       os.system('%s'%wvs_console)
        os.system('%s /Scan %s /Profile ws_default /saveFolder %s%s --GetFirstOnly=false --FetchSubdirs=true --RestrictToBaseFolder=true --ForceFetchDirindex=true --SubmitForms=true --RobotsTxt=true --CaseInsensitivePaths=false --UseCSA=true --UseAcuSensor=true --EnablePortScanning=false --UseSensorDataFromCrawl=revalidate --ScanningMode=Heuristic --TestWebAppsOnAllDirs=false --ManipHTTPHeaders=true'%(wvs_console,url,folder,name))



if __name__ == '__main__':
    if not os.path.exists(urllist):
        print r'需扫描的网站文件不存在'
    if os.path.exists(savefolder) == False:
        os.mkdir(savefolder)
    for i in open(urllist):
        scan(i,savefolder)

再然后就是对数据的处理上来了

默认保存的位置为:C:\ProgramData\Acunetix WVS 10\Data\Database\vulnscanresults.mdb

Awvs扫描结果数据库中有一个Wvs_scans表,保存的都是扫描过的url,以及扫描开始时间和结束时间。可以将当天下载的url保存到一个list中,然后在扫描之前先将之前所有扫描过的URL查询出来,同样保存在list中,读取list中的url,判断是否在扫描过的URL list中,如果存在将之从url list中删除掉;如果不存在则再进行扫描。

Awvs会自动将扫描结果保存到本地的access数据库中,具体的表是Wvs_alerts,也可以设置保存到Mssql数据库中,具体的是在Application Setting进行设置。结果入库模块的功能是从access数据库筛选出危害等级大于0的漏洞。然后用正则表达式对request中的host,漏洞文件,get或post提交的请求进行筛选拼凑,获取到完整的漏洞测试url。

其实可以发现:需要的东西都是保存到WVS_alerts

severity为危害等级,分为0,1,2,3分别是无影响,低位,中危,高危

algroup 为漏洞的类型

affects 为漏洞文件

根据某个这些思路。大约可以这么定义

 conn = win32com.client.Dispatch(r'ADODB.Connection')
    DSN = 'PROVIDER=Microsoft Access Driver (*.mdb, *.accdb)'
    conn.Open('awvs')
    cur=conn.cursor()
    rs = win32com.client.Dispatch(r'ADODB.Recordset')
 
    rs.Open('[WVS_alerts]', conn, 1, 3) 
    if rs.recordcount == 0:
        exit()
    #遍历WVS_alerts所有的结果,cmp进行筛选危害等级为3的,也就是高危
    while not rs.eof:
        severity = str(rs('severity'))
        if cmp('3', severity):
            rs.movenext
            continue
        vultype = rs('algroup')
        vulfile=rs('affects')
        #由于mysql库中要求的漏洞类型和access的名称有点差别,所以还需要对漏洞类型和危害等级进行二次命名,sql注入和xss为例
        xss='Cross site'
        sqlinject='injection'
        if xss in str(vultype):
            vultype='XSS'
            level='低危'
        elif sqlinject in str(vultype):
            vultype="SQL注入"
            level='高危'
        else:
            level='中危'
        #拼凑出漏洞测试url,用了正则表达式, post和get类型的request请求是不同的
        params = rs('parameter')
        ss = str(rs('request'))
        str1 = ss[0:4]
 
        if 'POST'== str1:
            requestType = 'POST'
            regex = 'POST (.*?) HTTP/1\.\d+'
            str1 = re.findall(regex, ss);
        else:
            requestType = 'GET'
            regex = 'GET (.*?) HTTP/1\.\d+'
            str1 = re.findall(regex, ss);
        regex = 'Host:(.*?)\r\n'
        host = re.findall(regex, ss);
        if host == []:
            host = ''
        else:
            host = host[0].strip()
        if str1 == []:
            str1 = ''
        else:
            str1 = str1[0]
        url =host + str1
        timex=time.strftime('%Y-%m-%d',time.localtime(time.time()))

晚上到家,重新装了office里面的套件.access,重新打开mdb数据库。然后重新思考了下整个流程

1.用户输入网址进行扫描
 

os.system('%s /Scan %s /Profile ws_default /saveFolder %s%s --GetFirstOnly=false --FetchSubdirs=true --RestrictToBaseFolder=true --ForceFetchDirindex=true --SubmitForms=true --RobotsTxt=true --CaseInsensitivePaths=false --UseCSA=true --UseAcuSensor=true --EnablePortScanning=false --UseSensorDataFromCrawl=revalidate --ScanningMode=Heuristic --TestWebAppsOnAllDirs=false --ManipHTTPHeaders=true'%(wvs_console,url,folder,name))

然后会根据url会在WVS_scans创建一个scid。同时写入当前创建的时间。结束后写入结束的时间

result = "select scid,starttime,finishtime from WVS_scans where starturl="+%d (url)
id=result[scid]
start = result[starttime]
end = result[finishtime]

耗时:time = end -start

再根据scid来查询WVS_alerts里面的信息

result1 = select severity,algroup,affects,parameter,request from WVS_alerts where severity>0 and scid=result[scid]

漏洞级别 result1[severity]
漏洞类型 result1[algroup]
具体文件 result1[affects]
问题参数 result1[parameter]
请求过程 result1[request]

再把相关的数据整合就好了

#!/usr/bin/python
#-*- coding: utf-8 -*-
#Author:saline
#Email:nophacker@gmail.com
import pypyodbc

connection_string = 'Driver={Microsoft Access Driver (*.mdb)};DBQ=D:\\phpStudy\\WWW\\vulnscanresults.mdb'
connection = pypyodbc.connect(connection_string)
#使用Access的ODBC连接字符串,通过pypyodbc模块获得一个可以连接到vulnscanresults.mdb数据库的ODBC连接对象connection:
cur = connection.cursor()
#并从这个连接对象中,获取一个数据库操作游标cur:
sql='select scid,starttime,finishtime from WVS_scans where scid =1'
cur.execute(sql)
#首先,传递SQL查询语句至Access数据库:
for row in cur.fetchall():
    id =row[0]
    start = row[1]
    end = row[2]
    time = end -start
    print '消耗的时间为:'+ str(time)
    sql1 = 'select alid,algroup,severity,affects,parameter,request from WVS_alerts where severity>0 and scid=%d'%(id)
    cur.execute(sql1)
    for raw in cur.fetchall():
        print '第'+str(raw[0]+1)+'问题'
        print raw[1]
        print '危害等级:'+str(raw[2])
        print raw[3]
        print raw[4]
        print raw[5]

connection.close()

至此,一个简单的demo已经完成了。虽然是一些片段

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

Zookeeper常用命令

发布时间:July 15, 2015 // 分类:开发笔记,运维工作,linux,python,windows // No Comments

zk客户端命令

ZooKeeper命令行工具类似于Linux的shell环境,不过功能肯定不及shell啦,但是使用它我们可以简单的对ZooKeeper进行访问,数据创建,数据修改等操作.  使用 zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息。

命令行工具的一些简单操作如下:

如下示例:

  • 1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
  • 2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
  • 3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
  • 4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
  • 5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
  • 6. 删除文件: delete /zk 将刚才创建的 znode 删除
  • 7. 退出客户端: quit
  • 8. 帮助命令: help

429306093

429329789

 

ZooKeeper 常用四字命令:

      ZooKeeper 支持某些特定的四字命令字母与其的交互。它们大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息。用户在客户端可以通过 telnet 或 nc 向 ZooKeeper 提交相应的命令

传递四个字母的字符串给ZooKeeper,ZooKeeper会返回一些有用的信息。

ZooKeeper 四字命令

功能描述

conf

输出相关服务配置的详细信息。

cons

列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。

dump

列出未经处理的会话和临时节点。

envi

输出关于服务环境的详细信息(区别于 conf 命令)。

reqs

列出未经处理的请求

ruok

测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。

stat

输出关于性能和连接的客户端的列表。

wchs

列出服务器 watch 的详细信息。

wchc

通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。

wchp

通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。

 

如下示例:

  • 1. 可以通过命令:echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
  • 2. 使用echo ruok|nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动。
  • 3. echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
  • 4. echo kill | nc 127.0.0.1 2181 ,关掉server
  • 5. echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
  • 6. echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
  • 7. echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
  • 8. echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
  • 9. echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
  • 10. echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
  • 11. echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。

273847384

273799725

写个脚本来搞定


import sys
from kazoo.client import KazooClient
​
host = sys.argv[1]
conn = KazooClient(host)
conn.start()
sysinfo = conn.command('envi')
print sysinfo

 

分类
最新文章
最近回复
  • 没穿底裤: 直接在hosts里面.激活的时候访问不到正确的地址
  • Sfish: 屏蔽更新是在控制台设置一下就可以了,还是说要在其他层面做一下限制,比如配置一下hosts让他升...
  • 没穿底裤: 激活,或者屏蔽地址禁止升级
  • 没穿底裤: 呃..这个思路不错啊..
  • Sfish: 博主好,想问一下,wvs11的破解版,是不是每隔一段时间就要重新激活一次才可以?有没有什么解决...