欧成文 發表於 2020-2-23 12:29:00

PHP弱类型漏洞学习

<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">简介</p>
<p>PHP在使用双等号(==)判断的时候,不会严格检验传入的变量类型,同时在执行过程中可以将变量自由地进行转换类型。由于弱数据类型的特点,在使用双等号和一些函数时,会造成一定的安全隐患</p>
<p>eg:</p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
    </span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>("admin"==0);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
    <span style="color: rgba(0, 128, 128, 1)">var_dump</span>("1admin"==1); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
    <span style="color: rgba(0, 128, 128, 1)">var_dump</span>("admin1"==1); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">false</span>
    <span style="color: rgba(0, 128, 128, 1)">var_dump</span>("admin1"==0); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
    <span style="color: rgba(0, 128, 128, 1)">var_dump</span>("0e123456"=="0e4456789"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true </span>
?&gt;</pre>
</div>
<p>== 在进行比较的时候,会先将字符串类型转化成相同,再比较</p>
<p>=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">Hash比较缺陷</p>
<p>研发人员在对比Hash<sup>2</sup>字符串的时候常常用到等于、不等于(!=)进行比较。如果Hash值以0e开头,后面都是数字,当与数字进行比较时,就会被解析成0x10<sup>n</sup>,会被判与0相等,攻击者可以绕过某些系统逻辑</p>
<p>PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。</p>
<p>攻击者可以利用这一漏洞,通过输入一个经过哈希后以”0E”开头的字符串,即会被PHP解释为0,如果数据库中存在这种哈希值以”0E”开头的密码的话,他就可以以这个用户的身份登录进去,尽管并没有真正的密码。</p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>("0e123456789012345678901234567890"==="0"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">false</span>
<span style="color: rgba(0, 128, 128, 1)">var_dump</span>("0e123456789012345678901234567890"=="0"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
?&gt;</pre>
</div>
<p>加密后为0E的字符</p>
<div class="cnblogs_code"><img id="code_img_closed_bceba16b-a22c-4f83-a2ff-1adbcc76c78f" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_bceba16b-a22c-4f83-a2ff-1adbcc76c78f" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_bceba16b-a22c-4f83-a2ff-1adbcc76c78f" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">QNKCDZO
</span>0e830400451993494058024219903391<span style="color: rgba(0, 0, 0, 1)">

s878926199a
</span>0e545993274517709034328855841020<span style="color: rgba(0, 0, 0, 1)">

s155964671a
</span>0e342768416822451524974117254469<span style="color: rgba(0, 0, 0, 1)">

s214587387a
</span>0e848240448830537924465865611904<span style="color: rgba(0, 0, 0, 1)">

s214587387a
</span>0e848240448830537924465865611904<span style="color: rgba(0, 0, 0, 1)">

s878926199a
</span>0e545993274517709034328855841020<span style="color: rgba(0, 0, 0, 1)">

s1091221200a
</span>0e940624217856561557816327384675<span style="color: rgba(0, 0, 0, 1)">

s1885207154a
</span>0e509367213418206700842008763514<span style="color: rgba(0, 0, 0, 1)">

s1502113478a
</span>0e861580163291561247404381396064<span style="color: rgba(0, 0, 0, 1)">

s1885207154a
</span>0e509367213418206700842008763514<span style="color: rgba(0, 0, 0, 1)">

s1836677006a
</span>0e481036490867661113260034900752<span style="color: rgba(0, 0, 0, 1)">

s155964671a
</span>0e342768416822451524974117254469<span style="color: rgba(0, 0, 0, 1)">

s1184209335a
</span>0e072485820392773389523109082030<span style="color: rgba(0, 0, 0, 1)">

s1665632922a
</span>0e731198061491163073197128363787<span style="color: rgba(0, 0, 0, 1)">

s1502113478a
</span>0e861580163291561247404381396064<span style="color: rgba(0, 0, 0, 1)">

s1836677006a
</span>0e481036490867661113260034900752<span style="color: rgba(0, 0, 0, 1)">

s1091221200a
</span>0e940624217856561557816327384675<span style="color: rgba(0, 0, 0, 1)">

s155964671a
</span>0e342768416822451524974117254469<span style="color: rgba(0, 0, 0, 1)">

s1502113478a
</span>0e861580163291561247404381396064<span style="color: rgba(0, 0, 0, 1)">

s155964671a
</span>0e342768416822451524974117254469<span style="color: rgba(0, 0, 0, 1)">

s1665632922a
</span>0e731198061491163073197128363787<span style="color: rgba(0, 0, 0, 1)">

s155964671a
</span>0e342768416822451524974117254469</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;CTF例题</p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
   </span><span style="color: rgba(128, 0, 128, 1)">$pass</span>=<span style="color: rgba(128, 0, 128, 1)">$_GET</span>['password'<span style="color: rgba(0, 0, 0, 1)">];
   </span><span style="color: rgba(128, 0, 128, 1)">$password</span>='0e342768416822451524974117254469'<span style="color: rgba(0, 0, 0, 1)">;

   </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 128, 128, 1)">md5</span>(<span style="color: rgba(128, 0, 128, 1)">$pass</span>)==<span style="color: rgba(128, 0, 128, 1)">$password</span><span style="color: rgba(0, 0, 0, 1)">) {
       </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "flag{xx-xx-xxxx-xiaohua}"<span style="color: rgba(0, 0, 0, 1)">;
   }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "error"<span style="color: rgba(0, 0, 0, 1)">;
   }

</span>?&gt;</pre>
</div>
<p>payload:</p>
<div class="cnblogs_code">
<pre>http:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">127.0.0.1/index.php?password=s1885207154a</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225142248163-2044994914.png" alt="" width="247" height="144"></p>
<p><strong>预防方案 :</strong></p>
<p>PHP5.6以上使用hash_equals()函数比较Hash值,可以避免对比恶意绕过</p>
<p>低于5.6可用可以实现的函数解决</p>
<p>参考学习:https://www.freebuf.com/news/67007.html</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">bool比较缺陷</p>
<p>在使用json_decode()函数或使用unserialize()函数时,部分结构被解释成bool类型,也会造成缺陷。</p>
<p><strong>json_decode漏洞代码:</strong></p>
<div class="cnblogs_code"><img id="code_img_closed_7537f317-41b2-4ff6-88cb-99ebcfaab4c1" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_7537f317-41b2-4ff6-88cb-99ebcfaab4c1" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_7537f317-41b2-4ff6-88cb-99ebcfaab4c1" class="cnblogs_code_hide">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(128, 0, 128, 1)">$str</span>='{"user":true,"pass":true}'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$data</span>=json_decode(<span style="color: rgba(128, 0, 128, 1)">$str</span>,<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$data</span>['user']=='root' &amp;&amp; <span style="color: rgba(128, 0, 128, 1)">$data</span>['pass']=='myPass'<span style="color: rgba(0, 0, 0, 1)">){
    </span><span style="color: rgba(0, 128, 128, 1)">print_r</span>('登陆成功 获得flag{xx-ssss-xiaohua}'<span style="color: rgba(0, 0, 0, 1)">);
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(0, 128, 128, 1)">print_r</span>('登陆失败!'<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225144029323-1907404339.png" alt="" width="494" height="295"></p>
<p><strong>unserialize漏洞代码:</strong></p>
<div class="cnblogs_code"><img id="code_img_closed_d43211d0-139e-4910-aaa9-7086a88aebf6" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_d43211d0-139e-4910-aaa9-7086a88aebf6" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_d43211d0-139e-4910-aaa9-7086a88aebf6" class="cnblogs_code_hide">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(128, 0, 128, 1)">$str</span>='a:2:{s:4:"user";b:1;s:4:"pass";b:1;}'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$data</span>=<span style="color: rgba(0, 128, 128, 1)">unserialize</span>(<span style="color: rgba(128, 0, 128, 1)">$str</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$data</span>['user']=='root' &amp;&amp; <span style="color: rgba(128, 0, 128, 1)">$data</span>['pass']=='myPass'<span style="color: rgba(0, 0, 0, 1)">){
    </span><span style="color: rgba(0, 128, 128, 1)">print_r</span>('登陆成功 获得flag{xx-ssss-xiaohua}'<span style="color: rgba(0, 0, 0, 1)">);
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(0, 128, 128, 1)">print_r</span>('登陆失败!'<span style="color: rgba(0, 0, 0, 1)">);
}
</span>?&gt;</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225144343876-1638637953.png" alt="" width="507" height="313"></p>
<p>&nbsp;避免bool比较可以使用三个等号作比较即可。</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">数字转换比较缺陷</p>
<p>当赋值给PHP变量的整型超过PHP的最大值PHP_INT_MAX时,PHP将无法计算出正确的结果,攻击者可能会利用其跳过某些校验逻辑,如密码校验、账号充值校验等</p>
<div class="cnblogs_code"><img id="code_img_closed_64930d9c-0359-49cb-864f-bc7f224cb5d0" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_64930d9c-0359-49cb-864f-bc7f224cb5d0" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_64930d9c-0359-49cb-864f-bc7f224cb5d0" class="cnblogs_code_hide">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>=98869694308861098395599991222222222222<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>=98869694308861098395599992999999999999<span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span>===<span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">);


</span>?&gt;</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225151047413-1233475376.png" alt="" width="357" height="215"></p>
<p>&nbsp;再实际的业务逻辑中,一定要对最大值进行限制,避免数据越界而导致错误的执行结果。</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">switch比较缺陷</p>
<p>当再switch中使用case判断数字时,switch会将其中的参数转换为int类型进行计算</p>
<div class="cnblogs_code"><img id="code_img_closed_0921fb60-bc0a-40ab-83b4-01aae07fd190" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_0921fb60-bc0a-40ab-83b4-01aae07fd190" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_0921fb60-bc0a-40ab-83b4-01aae07fd190" class="cnblogs_code_hide">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(128, 0, 128, 1)">$num</span>='2xiaohua'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">switch</span>(<span style="color: rgba(128, 0, 128, 1)">$num</span><span style="color: rgba(0, 0, 0, 1)">){
    </span><span style="color: rgba(0, 0, 255, 1)">case</span> 0:<span style="color: rgba(0, 0, 255, 1)">echo</span> '000000'<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">case</span> 1:<span style="color: rgba(0, 0, 255, 1)">echo</span> '1111'<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">case</span> 2:<span style="color: rgba(0, 0, 255, 1)">echo</span> '2222222'<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">case</span> 3:<span style="color: rgba(0, 0, 255, 1)">echo</span> '333333'<span style="color: rgba(0, 0, 0, 1)">;
}

</span>?&gt;

  </pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225152526465-1781218476.png" alt="" width="349" height="310"></p>
<p>&nbsp;最终输出2222&nbsp;&nbsp;</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">数组比较缺陷</p>
<p>当使用in_array()或array_search()函数时,如果$strict参数吗有设置为true,则in_array()或array_search()将使用松散来判断$needle是否存在$haystack中</p>
<div class="cnblogs_code">
<pre>bool <span style="color: rgba(0, 128, 128, 1)">in_array</span> ( <span style="color: rgba(0, 0, 255, 1)">mixed</span> <span style="color: rgba(128, 0, 128, 1)">$needle</span> , <span style="color: rgba(0, 0, 255, 1)">array</span> <span style="color: rgba(128, 0, 128, 1)">$haystack</span> [, bool <span style="color: rgba(128, 0, 128, 1)">$strict</span> = <span style="color: rgba(0, 0, 255, 1)">FALSE</span> ] )<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">strict默认为false</span>
miixed<span style="color: rgba(0, 128, 128, 1)">array_search</span>( <span style="color: rgba(0, 0, 255, 1)">mixed</span> <span style="color: rgba(128, 0, 128, 1)">$needle</span> , <span style="color: rgba(0, 0, 255, 1)">array</span> <span style="color: rgba(128, 0, 128, 1)">$haystack</span> [, bool <span style="color: rgba(128, 0, 128, 1)">$strict</span> = <span style="color: rgba(0, 0, 255, 1)">FALSE</span> ] )<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">strict默认为false</span></pre>
</div>
<p>漏洞代码:</p>
<div class="cnblogs_code"><img id="code_img_closed_ba5db4e1-efc5-4496-81ca-88549d41fb8b" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_ba5db4e1-efc5-4496-81ca-88549d41fb8b" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_ba5db4e1-efc5-4496-81ca-88549d41fb8b" class="cnblogs_code_hide">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
    </span><span style="color: rgba(128, 0, 128, 1)">$array</span>=;
    </span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(0, 128, 128, 1)">in_array</span>('abc',<span style="color: rgba(128, 0, 128, 1)">$array</span><span style="color: rgba(0, 0, 0, 1)">));
    </span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(0, 128, 128, 1)">array_search</span>('abc',<span style="color: rgba(128, 0, 128, 1)">$array</span><span style="color: rgba(0, 0, 0, 1)">));
   
</span>?&gt;</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/i-beta/967964/202002/967964-20200225153819628-1009649966.png" alt="" width="434" height="277"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p style="font-weight: bold; color: rgba(255, 255, 255, 1); font-family: 微软雅黑, 宋体, 黑体, Arial; min-height: 25px; line-height: 25px; opacity: 0.8; background: rgba(0, 221, 221, 1); border-radius: 6px; padding: 8px; border: 1px dashed rgba(0, 221, 221, 1); margin: 18px 5px !important">2222</p>
<p>参考学习:《php安全之道》</p><br><br>
来源:https://www.cnblogs.com/xhds/p/12349189.html
頁: [1]
查看完整版本: PHP弱类型漏洞学习