Snort中pcre和正则表达式的使用详解
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 题目描述</a></li><li><a href="#_label1">2. 解决方案</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">2.1 第一条检测规则</a></li><li><a href="#_lab2_1_1">2.2 第二条检测规则</a></li></ul><li><a href="#_label2">3. 检测规则</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>1. 题目描述</h2><p>If snort see two packets in a TCP flow with</p>
<p>first packet has “login” or “Initial” in payload, destination port is 3399;and second packet has a “IPv4Address:Port”string(E.g. 123.45.6.7:8080) in payload. destination port is 3399;output an alert with msg “bot founded” and sid 1000001</p>
<p class="maodian"><a name="_label1"></a></p><h2>2. 解决方案</h2>
<p>题目要求检测包含两个包的特定流,需要通过设置标记位,即flowbits来实现。另外,题目中均要求检测特定的字符串或模式,所以还需要在pcre字段中通过正则表达式实现。</p>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>2.1 第一条检测规则</h3>
<p>匹配特定字符串</p>
<div class="jb51code"><pre class="brush:bash;">pcre:"/login|Initial/";</pre></div>
<p>正则表达式的两端需要加上限界符<code>/</code>。</p>
<p>设置标志位,同时不发出警报。</p>
<div class="jb51code"><pre class="brush:bash;">flowbits:set,login_Initial;flowsbits:noalert;</pre></div>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2.2 第二条检测规则</h3>
<p>2.2.1 匹配模式<code>IPv4Address:Port</code></p>
<p>IPv4Address</p>
<p>IPv4地址使用点分十进制表示时,分为4组,每组的范围均为。即从0.0.0.0到255.255.255.255。</p>
<p>我们先分析单独一组的特点:</p>
<table><tbody><tr><th>区间</th><th>限制</th><th>表示</th></tr><tr><td>0~99</td><td>没有任何限制</td><td><code>\d{1,2}</code></td></tr><tr><td><strong>1</strong>00~<strong>1</strong>99</td><td>后两位也没有任何限制</td><td><code>1\d{2}</code></td></tr><tr><td><strong>2</strong>00~<strong>2</strong>49</td><td>十位限制在0~4,个位没有限制</td><td><code>2\d</code></td></tr><tr><td><strong>25</strong>0~<strong>25</strong>5</td><td>个位限制在0~5</td><td><code>25</code></td></tr></tbody></table>
<p>可以发现表格中前两种情况可以合并为<code>1?\d{1,2}</code>,所以可以用<code>25|2\d|1?\d{1,2}</code>来匹配0~255;</p>
<p>将其作为一个分组,再考虑到<code>.</code>,我们可以写出如下正则表达式匹配IPv4地址:</p>
<blockquote><p>((25|2\d|1?\d{1,2})\.){3}(25|2\d|1?\d{1,2})</p></blockquote>
<p>值得说明的是:</p>
<p>这里我们认为数字前出现填充<code>0</code>的情况与非填充状态等价:</p>
<p>如:<code>192.01.00.1</code>等价于<code>192.1.0.1</code>。</p>
<p>这种情况下才能使用<code>\d{1,2}</code>,因为可能会出现<code>00</code>的情况。</p>
<p>正则表达式的短路性质:</p>
<p>当<code>|</code>运算符分隔的多个表达式有一个匹配成功时,该表达式之后的表达式将不会继续匹配。</p>
<p>如:<code>A|B|C|D</code>,<code>B</code>匹配成功了,将不会再看<code>C</code>和<code>D</code>。</p>
<p>所以上面匹配IPv4地址时,我们单独一个分组写成<code>25|2\d|1?\d{1,2}</code>而不是<code>1?\d{1,2}|2\d|25</code>。</p>
<p>后者匹配<code>255</code>时,只会匹配到<code>25</code>和<code>5</code>,而不会匹配到<code>255</code>:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202203/202203300826051.png" /></p>
<p>同样后者构造的正则表达式去匹配<code>255.255.255.255</code>,只会匹配到<code>255.255.255.25</code>,缺少最后一个<code>5</code>:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202203/202203300826062.png" /></p>
<p>因为它匹配到最后一组的<code>25</code>时就判定匹配成功,直接跳到末尾,结束匹配。而前面几组<code>255</code>正确匹配的原因是:如果只匹配<code>25</code>,发现剩下的<code>5</code>和<code>.</code>不匹配,之后会进行回溯,继续检查后面的条件,发现<code>255</code>匹配成功且<code>.</code>也匹配成功,不再回溯。</p>
<ul><li>Port</li></ul>
<p>端口号的范围是0~65535,我们同样可以分成不同的区间来匹配端口号。</p>
<table><tbody><tr><th>区间</th><th>限制</th><th>表示</th></tr><tr><td>0~9999</td><td>没有任何限制</td><td><code>\d{1,4}</code></td></tr><tr><td><strong>1</strong>0000~<strong>5</strong>9999</td><td>后四位没有任何限制</td><td><code>\d{4}</code></td></tr><tr><td><strong>6</strong>0000~<strong>6</strong>4999</td><td>千位限制在0~4,后三位没有任何限制</td><td><code>6\d{3}</code></td></tr><tr><td><strong>65</strong>000~<strong>65</strong>499</td><td>百位限制在0~4,后两位没有任何限制</td><td><code>65\d{2}</code></td></tr><tr><td><strong>655</strong>00~<strong>655</strong>29</td><td>十位限制在0~4,个位没有任何限制</td><td><code>655\d</code></td></tr><tr><td><strong>6553</strong>0~<strong>6553</strong>5</td><td>个位限制在0~5</td><td><code>6553</code></td></tr></tbody></table>
<p>同样,我们可以将表格前两种情况合并为<code>?\d{1,4}</code>。结合上面提到的短路性质,我们可以写出最终用于匹配端口号的正则表达式:</p>
<blockquote><p>6553|655\d|65\d{2}|6\d{3}|?\d{1,4}</p></blockquote>
<p>2.2.2 检查标志位</p>
<div class="jb51code"><pre class="brush:plain;">flowbits:isset,bot_founded;</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3. 检测规则</h2>
<p>通过上述分析,我们可以写出如下检测规则:</p>
<div class="jb51code"><pre class="brush:plain;">alert tcp any any -> any 3399 (pcre:"/login|Initial/";flowbits:set,login_Initial;flowbits:noalert;sid:1000000)
alert tcp any any -> any 3399 (msg:"bot founded";pcre:"/((25|2\d|1?\d{1,2})\.){3}(25|2\d|1?\d{1,2}):(6553|655\d|65\d{2}|6\d{3}|?\d{1,4})/";flowbits:isset,bot_founded;sid:1000001)
</pre></div>
頁:
[1]