PHP弱类型的安全问题详细总结


Posted in PHP onSeptember 25, 2016

前言

相信大家都知道PHP是世界上最好的语言,PHP本身的问题也可以算作是web安全的一个方面。在PHP中的特性就是弱类型,以及内置函数对于传入参数的松散处理。

这篇文章主要就是记录我在做攻防平台上面遇到的PHP的函数中存在的问题,以及PHP的弱类型所带来的问题。对大家在学习或者使用php的时候具有一定的参考借鉴价值,下面来一起看看。

PHP弱类型简介

小编之所以认为php很强大是因为php提供了很多独有的特性工开发者使用,其中一个就是php弱类型机制。

在PHP中,可以进行一下的操作。

$param = 1;
$param = array();
$param = "stringg";

弱类型的语言对变量的数据类型没有限制,你可以在任何地时候将变量赋值给任意的其他类型的变量,同时变量也可以转换成任意地其他类型的数据。

类型转换问题

类型转换是无法避免的问题。例如需要将GET或者是POST的参数转换为int类型,或者是两个变量不匹配的时候,PHP会自动地进行变量转换。但是PHP是一个弱类型的语言,导致在进行类型转换的时候会存在很多意想不到的问题。

比较操作符

类型转换

$a==$b的比较中

$a=null;$b=flase ; //true
$a='';$b=null; //true

这样的例子还有很多,这种比较都是相等。

使用比较操作符的时候也存在类型转换的问题,如下:

0=='0' //true
0 == 'abcdefg' //true
0 === 'abcdefg' //false
1 == '1abcdef' //true

当不同类型的变量进行比较的时候就会存在变量转换的问题,在转换之后就有可能会存在问题。

Hash比较

除了以上的这种方式之外在进行hash比较的时候也会存在问题。如下:

"0e132456789"=="0e7124511451155" //true
"0e123456abc"=="0e1dddada" //false
"0e1abc"=="0"  //true

在进行比较运算时,如果遇到了0e\d+这种字符串,就会将这种字符串解析为科学计数法。所以上面例子中2个数的值都是0因而就相等了。如果不满足0e\d+这种模式就不会相等。这个题目在攻防平台中的md5 collision就有考到。

十六进制转换

还存在一种十六进制余字符串进行比较运算时的问题。

例子如下:

"0x1e240"=="123456" //true
"0x1e240"==123456 //true
"0x1e240"=="1e240" //false

当其中的一个字符串是0x开头的时候,PHP会将此字符串解析成为十进制然后再进行比较,0x1240解析成为十进制就是123456,所以与int类型和string类型的123456比较都是相等。攻防平台中的起名字真难就是考察的这个特性。

类型转换

常见的转换主要就是int转换为string,string转换为int。

int转string:

$var = 5;
方式1:$item = (string)$var;
方式2:$item = strval($var);

string转intintval()函数。

对于这个函数,可以先看2个例子。

var_dump(intval('2')) //2
var_dump(intval('3abcd')) //3
var_dump(intval('abcd')) //0

说明intval()转换的时候,会将从字符串的开始进行转换知道遇到一个非数字的字符。即使出现无法转换的字符串,intval()不会报错而是返回0。

intval()的这种特性在攻防平台中的MYSQL这道题目中就有考到。

同时,程序员在编程的时候也不应该使用如下的这段代码:

if(intval($a)>1000) {
 mysql_query("select * from news where id=".$a)
}

这个时候$a的值有可能是1002 union…..

内置函数的参数的松散性

内置函数的松散性说的是,调用函数时给函数传递函数无法接受的参数类型。解释起来有点拗口,还是直接通过实际的例子来说明问题,下面会重点介绍几个这种函数。

md5()

$array1[] = array(
 "foo" => "bar",
 "bar" => "foo",
);
$array2 = array("foo", "bar", "hello", "world");
var_dump(md5($array1)==var_dump($array2)); //true

PHP手册中的md5()函数的描述是string md5 ( string $str [, bool $raw_output = false ] ) md5()中的需要是一个string类型的参数。但是当你传递一个array时,md5()不会报错,知识会无法正确地求出array的md5值,这样就会导致任意2个array的md5值都会相等。这个md5()的特性在攻防平台中的bypass again同样有考到。

strcmp()

strcmp()函数在PHP官方手册中的描述是int strcmp ( string $str1 , string $str2 ) ,需要给strcmp()传递2个string类型的参数。如果str1小于str2,返回-1,相等返回0,否则返回1。strcmp函数比较字符串的本质是将两个变量转换为ascii,然后进行减法运算,然后根据运算结果来决定返回值。

如果传入给出strcmp()的参数是数字呢?

$array=[1,2,3];
var_dump(strcmp($array,'123')); //null,在某种意义上null也就是相当于false。

strcmp这种特性在攻防平台中的pass check有考到。

switch()

如果switch是数字类型的case的判断时,switch会将其中的参数转换为int类型。如下:

$i ="2abc";
switch ($i) {
case 0:
case 1:
case 2:
 echo "i is less than 3 but not negative";
 break;
case 3:
 echo "i is 3";
}

这个时候程序输出的是i is less than 3 but not negative,是由于switch()函数将$i进行了类型转换,转换结果为2。

in_array()

在PHP手册中,in_array()函数的解释是bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) ,如果strict参数没有提供,那么in_array就会使用松散比较来判断$needle是否在$haystack中。当strince的值为true时,in_array()会比较needls的类型和haystack中的类型是否相同。

$array=[0,1,2,'3'];
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true

可以看到上面的情况返回的都是true,因为'abc'会转换为0,'1bc'转换为1。

array_search()in_array()也是一样的问题。

总结

以上就是为大家总结的一些关于PHP弱类型的安全问题,希望这篇文章对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

PHP 相关文章推荐
PHP实现指定字段的多维数组排序函数分享
Mar 09 PHP
PHP生成静态HTML页面最简单方法示例
Apr 09 PHP
PHP的Socket通信之UDP通信实例
Jul 02 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
Mar 23 PHP
PHP操作mysql数据库分表的方法
Jun 09 PHP
php 使用html5实现多文件上传实例
Oct 24 PHP
PHP实现蛇形矩阵,回环矩阵及数字螺旋矩阵的方法分析
May 29 PHP
PHP微信企业号开发之回调模式开启与用法示例
Nov 25 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
Jun 13 PHP
php实现小程序支付完整版
Oct 09 PHP
laravel框架添加数据,显示数据,返回成功值的方法
Oct 11 PHP
tp5递归 无限级分类详解
Oct 18 PHP
php中mkdir()函数的权限问题分析
Sep 24 #PHP
php 生成Tab键或逗号分隔的CSV
Sep 24 #PHP
php 使用fopen函数创建、打开文件详解及实例代码
Sep 24 #PHP
php fread读取文件注意事项
Sep 24 #PHP
一个简单安全的PHP验证码类、PHP验证码
Sep 24 #PHP
jquery不支持toggle()高(新)版本的问题解决
Sep 24 #PHP
php getcwd与dirname(__FILE__)区别详解
Sep 24 #PHP
You might like
提升PHP执行速度全攻略(上)
2006/10/09 PHP
PHP开发的一些注意点总结
2010/10/12 PHP
《PHP编程最快明白》第七讲:php图片验证码与缩略图
2010/11/01 PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
2013/08/08 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
Firebug 字幕文件JSON地址获取代码
2009/10/28 Javascript
jquery简单的拖动效果实现原理及示例
2013/07/26 Javascript
Json序列化和反序列化方法解析
2013/12/19 Javascript
jquery操作checkbox实现全选和取消全选
2014/05/02 Javascript
Jquery中find与each方法用法实例
2015/02/04 Javascript
JavaScript实现自动对页面上敏感词进行屏蔽的方法
2015/07/27 Javascript
JavaScript设置表单上传时文件个数的方法
2015/08/11 Javascript
jQuery simplePage+AJAX plus分页插件用法实例
2016/02/17 Javascript
JQuery实现简单的服务器轮询效果实例
2016/03/31 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
2016/07/04 Javascript
AngularJS实现按钮提示与点击变色效果
2016/09/07 Javascript
jquery插件锦集【推荐】
2016/12/16 Javascript
简单实现bootstrap导航效果
2017/02/07 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
2017/09/07 Javascript
vue使用axios跨域请求数据问题详解
2017/10/18 Javascript
vue父组件向子组件传递多个数据的实例
2018/03/01 Javascript
原生javascript AJAX 三级联动的实现代码
2018/05/04 Javascript
JavaScript命令模式原理与用法实例详解
2020/03/10 Javascript
[04:44]DOTA2英雄梦之声_第12期_矮人直升机
2014/06/21 DOTA
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
python中nan与inf转为特定数字方法示例
2017/05/11 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
HTML5样式控制示例代码
2013/11/27 HTML / CSS
金融专业毕业生推荐信
2013/11/26 职场文书
消防演习通知
2015/04/25 职场文书
篮球赛新闻稿
2015/07/17 职场文书
2019个人年度目标制定攻略!
2019/07/12 职场文书
详解如何用Python实现感知器算法
2021/06/18 Python
Spark SQL 2.4.8 操作 Dataframe的两种方式
2021/10/16 SQL Server