<div style="font-size:16px;">
<p>摘要:</p>
<p>虽然PHP是世界上最好的语言,但是也有一些因为弱类型语言的安全性问题出现。WordPress历史上就出现过由于PHP本身的缺陷而造成的一些安全性问题,如CVE-2014-0166 中的cookie伪造就是利用了PHP Hash比较的缺陷。 当然一般这种情况实战中用到的不是很多,但是在CTF竞赛中却是一个值得去考察的一个知识点,特此记录总结之。</p>
<p>一、精度绕过缺陷</p>
<p>理论</p>
<p>在用PHP进行浮点数的运算中,经常会出现一些和预期结果不一样的值,这是由于浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。下面看一个有趣的例子:</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif"></p>
<p>以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的8,因为该结果内部的表示其实是类似 7.9999999999999991118…。</p>
<p>实践</p>
<p>问鼎杯2017 老眼昏花网上很多write-up感觉就像是看着答案写write-up,个人感觉真正的write-up中应该体现自己的思考在里面。</p>
<p>题目描述</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif"></p>
<p>题目言简意赅,让我们把2017这个值传递给服务器。</p>
<p>考察点PHP浮点精确度</p>
<p>write-up</p>
<p>what year is this?所以第一反应是直接给year参数赋值为2017:?year=2017</p>
<p align="center">然而结果如下:<img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif">有提示了,说明year这个参数是对的,但是2017中不可以出现7,这里如果不了解php精度的话,肯定是对2017进行各种编码绕过,但是这里对编码也进行过滤了:</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif">所以最后一种可能就是利用PHP精度来绕过:?year=2016.99999999999</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif"></p>
<p>二、类型转换的缺陷</p>
<p>理论</p>
<p>PHP提供了is_numeric函数,用来变量判断是否为数字。PHP弱类型语言的一个特性,当一个整形和一个其他类型行比较的时候,会先把其他类型intval数字化再比。</p>
<p>实践</p>
<p>is_numeric()用于判断是否是数字,通常配合数值判断。</p>
<p>案例代码<?php </p>
<p>error_reporting(0);</p>
<p>$flag = 'flag{1S_numer1c_Not_S4fe}';</p>
<p>$id = $_GET['id'];</p>
<p>is_numeric($id)?die("Sorry...."):NULL;</p>
<p>if($id>665){ echo $flag;</p>
<p>}</p>
<p>?></p>
<p>考察点PHP类型转换缺陷</p>
<p>write-up</p>
<p>分析下代码:首先对GET方式提交的参数id的值进行检验。id通过is_numeric函数来判断是否为数字,如果为数字的话,GG。如果不是数字的话,和665进行比较,id的值大于665的时候输出flag。乍看上去又好像不可能这里,但是如果知道PHP弱类型语言的一个特性,当一个整形和一个其他类型行比较的时候,会先把其他类型intval数字化再比。这个特性的话就可以很好的绕过。http://localhost/?id=666gg</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif"></p>
<p>三、松散比较符的缺陷</p>
<p>理论</p>
<p>php比较相等性的运算符有两种,一种是严格比较,另一种是松散比较。如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif">严格比较符严格比较符,会先判断两种字符串的类型是否相等,再比较。=== //全等!== //不全等</p>
<p align="center"><img alt="6d27afabe8be213ce623efb1c485f47a.gif" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-01cbed93a2c87e042bdd3559b0fdd002.gif"></p>
<p>松散 |
|