PHP zend_zend empty stringg_extend函数拒绝服务漏洞

PHP GD拒绝服务漏洞(CVE-)_Linux安全_Linux公社-Linux系统门户网站
你好,游客
PHP GD拒绝服务漏洞(CVE-)
来源:Linux社区&
作者:Linux
PHP GD拒绝服务漏洞(CVE-)
发布日期:更新日期:受影响系统:
PHP PHP & 5.6.12
CVE(CAN) ID: PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。 PHP & 5.6.12版本,GD存在栈耗尽漏洞。通过构造的imagefilltoborder调用,远程攻击者可造成拒绝服务。&*来源:PHP & *&建议:
厂商补丁:PHP---目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
本文永久更新链接地址:
相关资讯 & & &
& (03月29日)
& (01月17日)
& (05月16日)
& (03月29日)
& (01月13日)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款网络与信息安全
    网络与信息安全
您的位置&&&&网络与信息安全&&漏洞预警&&正文
关于PHP GD Graphics Library存在拒绝服务漏洞的安全公告
[上传者:Super | 日期: 00:00:00]
&安全公告编号:CNTA-
<span style="mso-spacerun:'yes';font-family:仿宋_GB2312;font-size:16.0000mso-font-kerning:1.年1月18日,国家信息安全漏洞共享平台(CNVD)收录了PHP GD Graphics Library存在拒绝服务漏洞(CNVD-,对应CVE-)。综合利用上述漏洞,攻击者可以构造恶意GIF文件,远程利用PHP函数形成无限循环的方式发起拒绝服务攻击。目前,漏洞利用代码已公开,且厂商已发布漏洞修复版本。
一、漏洞情况分析
PHP(超文本预处理器)是一种通用开源脚本语言。GD Graphics Library(又名libgd或libgd2)是一个开源的用于动态创建图像的库,它支持创建图表、图形和缩略图等,广泛应用于PHP语言的开发。
该漏洞触发的前提条件为受影响版本的PHP,并且使用了libgd库,漏洞文件存在于ext/gd/libgd/gd_gif_in.c。在&LWZReadByte_&函数存在一个循环(while-loop),该循环里&GetCode_&函数会调用GetDataBlock来读取GIF图片中的数据,但由于&GetCode_&函数未能正确处理int到unsigned char的类型转换,导致PHP在解析特定GIF文件调用PHP函数imagecreatefromgif或imagecreatefromstring时出现死循环,从而导致服务器计算资源大量消耗,直至崩溃宕机。该漏洞允许远程攻击者利用该漏洞导致拒绝服务攻击。
CNVD对上述漏洞的综合评级为&高危&。
二、漏洞影响范围
PHP 5 & 5.6.33版本
PHP 7.0 & 7.0.27版本
PHP 7.1 & 7.1.13版本
PHP 7.2 & 7.2.1版本
三、漏洞修复建议
目前,厂商已发布升级新版本以修复该漏洞,最新版本下载链接:
http://php.net/downloads.php
附:参考链接:
http://php.net/ChangeLog-7.php
https://bugs.php.net/bug.php?id=75571
http://www.cnvd.org.cn/flaw/show/CNVD-PHP ext/wddx/wddx.c拒绝服务漏洞(CVE-)_Linux安全_Linux公社-Linux系统门户网站
你好,游客
PHP ext/wddx/wddx.c拒绝服务漏洞(CVE-)
来源:Linux社区&
作者:Linux
PHP ext/wddx/wddx.c拒绝服务漏洞(CVE-)
发布日期:更新日期:受影响系统:
PHP PHP & 5.6.29PHP PHP 7.x & 7.0.14PHP PHP 7.x & 7.0.14
CVE(CAN) ID: PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。 PHP & 5.6.29、7.x & 7.0.14版本,ext/wddx/wddx.c内php_wddx_push_element函数中存在安全漏洞,远程攻击者通过wddxPacket XML文档内的空布尔元素,可造成拒绝服务。&*来源:vendor& *&建议:
厂商补丁:PHP---目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
本文永久更新链接地址:
相关资讯 & & &
& (03月29日)
& (01月17日)
& (05月16日)
& (03月29日)
& (01月13日)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款新手向-PHP5.2.17上Zend Optimizer安装失败 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
已注册用户请 &
新手向-PHP5.2.17上Zend Optimizer安装失败
14:08:24 +08:00 · 3146 次点击
PHP5.2.17ZendOptimizer-3.3.3安装ZendOptimizer-3.3.3中的Readme,将ZendOptimizer-3.3.3丢到了C:\Program Files目录下php.ini中添加如下配置[Zend]zend_extension_manager.optimizer_ts="C:\Program Files\ZendOptimizer-3.3.3"zend_extension_ts="C:\Program Files\ZendOptimizer-3.3.3\ZendExtensionManager.dll"但是在phpinfo()中看到的只有 This program makes use of the Zend Scripting Language Engine:Zend Engine v2.2.0, Copyright (c)
Zend Technologies
with Zend Extension Manager v1.2.0, Copyright (c) , by Zend Technologies没有with Zend Optimizer v3.3.3, Copyright (c) , by Zend Technologies这个提示
4 回复 &| &直到
08:00:00 +08:00
& & 14:12:17 +08:00
& & 14:54:33 +08:00
搞定了...路径问题
解压出的ZendOptimizer-3.3.3中Optimizer-3.3.3这层文件夹去掉就OK了
& & 04:55:22 +08:00
学习、开发,装这个版本无所谓。
但最好别在生产环境部署这个版本。有个严重的拒绝服务漏洞。
& & 09:43:09 +08:00
@ 多谢提醒
& · & 711 人在线 & 最高记录 3541 & · &
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.1 · 17ms · UTC 19:42 · PVG 03:42 · LAX 12:42 · JFK 15:42? Do have faith in what you're doing.【问底】王帅:深入PHP内核(三)——内核利器哈希表与哈希碰撞攻击
发表于 22:26|
摘要:PHP作为一门简单而强大的语言,能够提供很多Web适用的语言特性。从实践出发,继弱类型变量原理探究后,王帅将继续带大家弄清PHP内核中的一些常用部分,本期则是内核利器哈希表与哈希碰撞攻击。
【导读】王帅在海量分布式Web系统有超过8年沉淀,主导过多个大型系统的架构设计,目前在腾讯企业SaaS团队。PHP内核系列文章,是作者在PHP领域实践中,把相关原理性的知识,通过更便于理解的方式,系统整理出来分享给读者。希望通过PHP原理性的轻量解读,对这门Web领域最热门技术的优秀架构分析解构,让更多的人不断的深入了解语言的原理本身,更容易定位、理解一些问题背后原因,更游刃有余的做基础架构设计。同时希望影响更多的人才投入Web开源领域,不仅是应用和学习一门技术、组件,同样能够贡献更多高质量组件,像战国时期的百家争鸣一样,PHP开源界花开遍地。作者一直倡导技术的深入学习就像职业篮球训练,80%的时间都是基本功的训练,球场上实际战术的练习只是基本功的应用。同样的,学习PHP语言本身的特性,应当是每个PHP领域工程师所掌握、理解的,至于系统的架构设计也是基于对Linux、Mysql、Nginx等原理机制足够理解后,战术性的使用。深入PHP内核(三)——内核利器哈希表与哈希碰撞攻击在PHP的Zend&Engine(下面简称ZE)中,有一个非常重要的数据结构——哈希表(HashTable)。哈希表在ZE中有非常广泛的应用,PHP的复杂数据结构中数组和类的存储和访问就是用哈希表来组织,PHP语言结构中的常量、变量、函数等符号表也是用它来组织。
1.&哈希表的基本概念
什么是哈希表呢?哈希表在数据结构中也叫散列表。是根据键名经过hash函数计算后,映射到表中的一个位置,来直接访问记录,加快了访问速度。在理想情况下,哈希表的操作时间复杂度为O(1)。数据项可以在一个与哈希表长度无关的时间内,计算出一个值hash(key),在固定时间内定位到一个桶(bucket,表示哈希表的一个位置),主要时间消耗在于哈希函数计算和桶的定位。
在分析PHP中HashTable实现原理之前,先介绍一下相关的基本概念:
如下图例子,希望通过人名检索一个数据,键名通过哈希函数,得到指向bucket的指针,最后访问真实的bucket。
键名(Key):在哈希函数转换前,数据的标识。
桶(Bucket):在哈希表中,真正保存数据的容器。
哈希函数(Hash&Function):将Key通过哈希函数,得到一个指向bucket的指针。MD5,SHA-1是我们在业务中常用的哈希函数。
哈希冲突(Hash&Collision):两个不同的Key,经过哈希函数,得到同一个bucket的指针。
2.&PHP的哈希表实现原理
哈希表的结构:
Zend/zend_hash.h
typedef struct _hashtable {
uint nTableS
//哈希表的长度,不是元素个数
uint nTableM
//哈希表的掩码,设置为nTableSize-1
uint nNumOfE
//哈希表实际元素个数
ulong nNextFreeE
//指向下一个空元素位置
Bucket *pInternalP
//用于遍历哈希表的内部指针
Bucket *pListH
//哈希表队列的头部
Bucket *pListT
//哈希表队列的尾部
Bucket **arB
//哈希表存储的元素数组
dtor_func_t pD
//哈希表的元素析构函数指针
//是否是持久保存,用于pmalloc的参数,可以持久存储在内存中
unsigned char nApplyC
// zend_hash_apply的次数,用来限制嵌套遍历的层数,限制为3层
zend_bool bApplyP
//是否开启嵌套遍历保护
#if ZEND_DEBUG
} HashT1)& nTableSize&哈希表的大小。最小容量是2^3(8),最大容量是2^31()。当如果进行一次操作后发现元素个数大于nTableSize,会申请当前nTableSize&*&2的空间。假设当前nTableSize为8,当插入元素达到9个的时候,会申请nTableSize=16的空间。
2)& nTableMask&为nTableSize-1,用于调整最大索引值。当哈希后值大于索引值时候,把这个值映射到索引值范围内。
3)& nNumOfElements&HashTable中的个数。数组操作中,sizeof和count函数获取的是这个值。
4)& nNextFreeElement&下一个空元素的地址。
5)& pInternalPointer&存储了HashTable当前指向的元素的指针,当我们使用一些内部循环函数的时候会用到这个指针比如reset(),&current(),&prev(),&next(),&foreach(),&end()。相当于游标。
6)& pListHead和pListTail则具体指向了该哈希表的第一个和最后一个元素,对应就是数组的起始和结束元素。哈希表的pListHead、pListTail与Bucket的pListNext、pListLast维护了一个哈希表中Bucket的双向链表,按照插入的先后顺序,用于哈希表的遍历。
7)& arBuckets&实际存储Buckets的数组。
8)& pDestructor&是一个析构函数,当某个值被从哈希表删除的时候会触发此函数。他还有一个主要作用是用于变量的GC回收。在PHP里面GC是通过引用计数实现的,当一个变量的引用计数变为0,就会被PHP的GC回收。
9)& persistent&定义了hashtable是否能在多次request中获得持久存在。
10)& nApplyCount&和&bApplyProtection&是用来防止嵌套遍历的。
11)& inconsistent&是在调试模式下捕获对HT不正确的使用。
Bucket的结构:
typedef struct bucket {
//数组索引的哈希值
uint nKeyL
//索引数组为0,关联数组为key的长度
//元素内容的指针
void *pDataP
// 如果是指针大小的数据,用pDataPtr直接存储,pData指向pDataPtr
struct bucket *pListN
//哈希链表中下一个元素
struct bucket *pListL
//哈希链表中上一个元素
struct bucket *pN
//解决哈希冲突,变为双向链表,双向链表的下一个元素
struct bucket *pL
//解决哈希冲突,变为双向链表,双向链表的上一个元素
const char *arK
//最后一个元素key的名称
通过下图来表示HashTable的原理:
我们先来看一下,ZE是如何创建一个hash表的。创建并初始化一个Hash比较容易,调用_zend_hash_init函数。PHP的哈希表最小容量8(2^3),最大容量是0x^31,即)。nTableSize会按照2的整数次幂圆整来增加,直到超过预设值的nSize。
Zend/zend_hash.c
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
uint i = 3;
SET_INCONSISTENT(HT_OK);
if (nSize &= 0x) {
/* prevent overflow */
ht-&nTableSize = 0x;
while ((1U && i) & nSize) {
ht-&nTableSize = 1 &&
/* 省略哈希表初始化步骤 */
return SUCCESS;
1)& *ht&是哈希表的指针,这里既可以传入一个已存在的HashTable,&也可以通过内核宏ALLOC_HASHTABLE(ht)来自动申请一块HashTable内存。ALLOC_HASHTABLE(ht)相当于ht=emalloc(sizeof(HashTable))
2)& nSize&哈希表能拥有的最大数量。通过预先申请好内存的方式,减少哈希表rehash操作。
3)& pHashFunction&自定义哈希函数的钩子
4)& pDesctructor&哈希表析构的回调函数,当删除一个哈希表的时候,会调用。
5)& persistent&对应HashTable.persistent,当设置为true的时候,不会在RSHUTDOWN阶段自动销毁。
我们通过更新哈希表的操作方式,来分析哈希表的操作机制:
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht-&nTableM
p = ht-&arBuckets[nIndex];
while (p != NULL) {
if (p-&arKey == arKey ||
((p-&h == h) && (p-&nKeyLength == nKeyLength) && !memcmp(p-&arKey, arKey,
nKeyLength))) {
if (flag & HASH_ADD) {
return FAILURE;
/* 省略 */
UPDATE_DATA(ht, p, pData, nDataSize);
// 找到h 和 Key都相等的Buckets,说明需要更新
/* 省略 */
// 这里说明有哈希冲突,按照Buckets[nIndex]的链表找下去
/* 省略 */
p-&nKeyLength = nKeyL
INIT_DATA(ht, p, pData, nDataSize);
// 把Bucket.pData数据更新
CONNECT_TO_BUCKET_DLLIST(p, ht-&arBuckets[nIndex]);
if (pDest) {
*pDest = p-&pD
HANDLE_BLOCK_INTERRUPTIONS();
CONNECT_TO_GLOBAL_DLLIST(p, ht);
ht-&arBuckets[nIndex] =
HANDLE_UNBLOCK_INTERRUPTIONS();
ht-&nNumOfElements++;
ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* 如果哈希表满了,重新散列,这里有一定开销
通过哈希算法&&times33(Key)&&&(nTableSize-1)&,生成Key对应的哈希值A,获取arBuckets[A]的值
2) 判断arBuckets[A]是否存在,如果存在而且没有哈希冲突,进行数据update(UPDATE_DATA)。如果存在但是Key不相同说明有哈希冲突,在arBuckets[A]链表中寻找Key是否存在,如果存在,执行update操作(UPDATE_DATA)
3) 如果arBuckets[A]不存在,创建新的arBucket[A](INIT_DATA)。或哈希冲突情况下,在arBuckets[A]的链表中找不到Key。创建新的bucket(INIT_DATA),并把新的buckets放在arBucket[A]链表头
4) 维护哈希表的逻辑链表(CONNECT_TO_GLOBAL_DLLIST)。
5)&如果发现新插入元素已经超过HashTable的nTableSize,自动扩容至2倍nTableSize,重新哈希后维护新的HashTable。
3.&PHP使用的哈希函数
PHP的哈希表是用Times33哈希算法,又称为DJBX33A。这是一个使用比较广泛的对字符串的哈希算法,计算速度快,散列均匀,Perl和Apache都使用了这个算法。算法原理就是不断的乘以33,其算法原型如下:
hash(i) = hash(i-1) * 33 + str[i]为什么是33呢?对于33这个数,DJB注释中是说,1到256之间的所有奇数,都能达到一个可接受的哈希分布,平均分布大概是86%。而其中33,17,31,63,127,129这几个数在面对大量的哈希运算时有一个更大的优势,就是这些数字能将乘法用位运算配合加减法替换,这样运算速度会更高。gcc编译器开启优化后会自动将乘法转换为位运算。PHP实际算法如下:
static inline ulong zend_inline_hash_func(const char *arKey, uint nKeyLength)
register ulong hash = 5381;
/* variant with the hash unrolled eight times */
for (; nKeyLength &= 8; nKeyLength -= 8) {
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
hash = ((hash && 5) + hash) + *arKey++;
switch (nKeyLength) {
case 7: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 6: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 5: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 4: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 3: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 2: hash = ((hash && 5) + hash) + *arKey++; /* fallthrough... */
case 1: hash = ((hash && 5) + hash) + *arKey++;
EMPTY_SWITCH_DEFAULT_CASE()
PHP在哈希算法上有所优化,使用了(hash&&5)+hash,效率有所提高。至于hash的初始值为什么为一个大素数5381,要数学上来解释了,不是很理解。
4.&操作哈希表的内部函数
PHP的变量符号表是通过哈希表来维护,首先介绍一下再PHP扩展中如何创建一个新的变量。PHP变量介绍,请看我上一篇文章,。
ZEND_FUNCTION(variable_creation)
zval *new_var1, *new_var2, *new_var3; //创建两个新的变量容器
char *string_contents = "This is a new string variable";
MAKE_STD_ZVAL(new_var1);
//为new_var1申请空间并初始化
MAKE_STD_ZVAL(new_var2);
ZVAL_LONG(new_var1, 10);
//设置new_var1并赋值为long
ZVAL_LONG(new_var2, 5);
ZVAL_STRINGL(new_var3, string_contents, sizeof(string_contents), 0);
//设置new_var3为字符串
ZEND_SET_SYMBOL(EG(active_symbol_table), "local_variable", new_var1);
//设置long_variable为函数variable_creation的局部变量
ZEND_SET_SYMBOL(&EG(symbol_table), "global_variable", new_var2);
//设置global_variable为全局变量
zend_hash_update(
&EG(symbol_table),
"new_var3",
strlen("new_var3") + 1,
&new_var3,
sizeof(zval *),
RETURN_NULL();
}这里的zend_hash_update会更新变量符号表。PHP的数组也是用哈希表来维护,下面通过操作一个array来解释如何使用哈希表来才做数组。
增加一个关联数组:
zval *new_array, *new_
char *key = "element_key";
MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);
array_init(new_array);
ZVAL_LONG(new_element, 10);
if(zend_hash_update(new_array-&value.ht, key, strlen(key) + 1, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
// do error handling here
}增加一个索引数组:
zval *new_array, *new_
int key = 2;
MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);
array_init(new_array);
ZVAL_LONG(new_element, 10);
if(zend_hash_index_update(new_array-&value.ht, key, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
// do error handling here
哈希表的增删改查
int&zend_hash_add( HashTable *ht, char *arKey, uint nKeyLen,void *pData, uint nDataSize, void **pDest);
int zend_hash_update(
HashTable *ht, char *arKey, uint nKeyLen, void *pData, uint nDataSize, void **pDest);
int zend_hash_index_update(
HashTable *ht, ulong h,
void *pData, uint nDataSize, void **pDest);//与zend_hash_update类似,不过哈希值计算是用h&TableMask
int zend_hash_next_index_insert(HashTable *ht,&&&&&&&&&&&&&&&&&&&&&&&&&&& void *pData, uint nDataSize, void **pDest);
int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength,void **pData);
int zend_hash_index_find(HashTable *ht, ulong h, void **pData);&
ZEND_API&int&zend_hash_exists(const&HashTable&*ht,&const&char&*arKey,&uint&nKeyLength)
ZEND_API ulong zend_get_hash_value(const char *arKey, uint nKeyLength)
ZEND_API&void&zend_hash_merge_ex(HashTable&*target,&HashTable&*source,&copy_ctor_func_t&pCopyConstructor,&uint&size,&merge_checker_func_t&pMergeSource,&void&*pParam)
通过source的逻辑双向链表,遍历source插入target
ZEND_API&void&zend_hash_copy(HashTable&*target,&HashTable&*source,&copy_ctor_func_t&pCopyConstructor,&void&*tmp,&uint&size)
哈希表的遍历
ZEND_API&int&zend_hash_get_pointer(const&HashTable&*ht,&HashPointer&*ptr)
ZEND_API&int&zend_hash_set_pointer(HashTable&*ht,&const&HashPointer&*ptr)
ZEND_API&void&zend_hash_internal_pointer_reset_ex(HashTable&*ht,&HashPosition&*pos)
ZEND_API&void&zend_hash_internal_pointer_end_ex(HashTable&*ht,&HashPosition&*pos)
ZEND_API&int&zend_hash_move_forward_ex(HashTable&*ht,&HashPosition&*pos)
ZEND_API&int&zend_hash_move_backwards_ex(HashTable&*ht,&HashPosition&*pos)
数组操作函数reset(),&each(),&current(),&next()会用这些函数来实现。
比较,排序
ZEND_API int
zend_hash_sort ( HashTable
sort_func_t
sort_func ,
compare_func_t compar , int renumber TSRMLS_DC )
ZEND_API int
zend_hash_minmax (const HashTable
compare_func_t
compar , int
flag , void ** pData
TSRMLS_DC )
ZEND_API int
zend_hash_compare ( HashTable
compare_func_t compar ,
zend_bool ordered TSRMLS_DC )哈希表有一套排序算法。sort(),&asort(),&resort(),&arsort(),&ksort(),&krsort()
详细请见:
5.&哈希冲突(Hashtable&Collisions)
因为任何一个哈希表的长度都是有限制的,所以一定会发生键名不同,hash函数计算后得到相同的bucket位置。也就是key1&!=&key2,但是HASH(key1)&=&HASH(key2)。如下图2,在发生哈希冲突时(Hash&Collision),最坏情况下,所有的键名全部冲突,哈希表会退化成双向链表,操作时间复杂度为O(n)。
当发生了哈希冲突,会把当前bucket插入到哈希值所在链表的第一位,并插入HashTable的逻辑链表。
6.&哈希碰撞攻击及解决
在去年发现了PHP的哈希碰撞攻击漏洞,PHP5.3.9以下的版本都会受影响。我们在业务压力很重的情况下,还是最短时间内把运营服务器全部更新到5.3.13以上,防止通过PHP的哈希碰撞进行拒绝服务攻击。
如何哈希碰撞攻击呢?运用哈希冲突。在我们对PHP哈希算法足够了解以后,通过精心构造,可以让PHP的哈希表全部冲突,退化成链表,每插入元素时候,PHP都要遍历一遍链表,消耗大量的CPU,造成拒绝服务攻击。最简单的方法是利用掩码规律制造碰撞,我们知道HashTable的长度nTableSize会被圆整为2的整数次幂,假设我们构造一个长度为2^16的哈希表,nTableSize的二进制表示为:1&00&0000,而nTableMask&=&nTableSize&–&1为:0&11&1111。这样我们只要保证后16位均为0,则与掩码与运算后得到的哈希值全部碰撞在位置0。
& 0 11 1111 = 0&
& 0 11 1111 = 0
& 0 11 1111 = 0
以下这个例子就是这个原理的实现,插入65535个数据需要消耗30秒,而正常情况下仅需要0.01秒。
echo &#039;
$size = pow(2, 16); // 16 is just an example, could also be 15 or 17
$startTime = microtime(true);
$array = array();
for ($key = 0, $maxKey = ($size - 1) * $ $key &= $maxK $key += $size) {
$array[$key] = 0;
$endTime = microtime(true);
echo &#039;Inserting &#039;, $size, &#039; evil elements took &#039;, $endTime - $startTime, &#039; seconds&#039;, "\n";
$startTime = microtime(true);
$array = array();
for ($key = 0, $maxKey = $size - 1; $key &= $maxK ++$key) {
$array[$key] = 0;
$endTime = microtime(true);
echo &#039;Inserting &#039;, $size, &#039; good elements took &#039;, $endTime - $startTime, &#039; seconds&#039;, "\n";
Inserting 65536 evil elements took 32. seconds
Inserting 65536 good elements took 0.247 seconds
文章来源:http://nikic.github.io//Supercolliding-a-PHP-array.html
对于哈希碰撞攻击有2中常见形式:通过POST攻击或通过反序列化攻击。PHP会自动把HTTP包中POST的数据解析成数组$_POST,如果我们构造一个无限大的哈希冲突的值,可以造成拒绝服务攻击。
PHP5.3.9+是通过增加一个限制来尽量避免被此类攻击影响:
- max_input_vars - 指定 GET/POST/COOKIE 的最大输入变量数。默认是1000。
反序列化同样是利用数组的哈希冲突,如果POST的数据有字段为数组serialize后的值,或数组json_encode后的值,在unserialize或json_decode后,会有可能造成哈希碰撞攻击。解决方法,尽量避免在公网上以数组的序列化形式传递数据,如果不可避免,请使用私有协议(TLV)增加供给难度,或使用加密协议(HTTPS)防止中间人攻击。
PHP的哈希表采用times33的哈希算法,通过HashTable数据结构维护Buckets,当有哈希冲突的时候,会将元素插入到该Buckets前形成双向链表。同时为了方便遍历,HashTable也会维护逻辑双向链表(按照插入顺序),通过内部游标指针可以遍历Hashtable。PHP的变量符号表、常量符号表和函数都是用哈希表维护,PHP的数组类型变量也是通过哈希表维护。
哈希表容易遭到哈希碰撞攻击,请更新PHP版本到5.3.9以上,可以解决POST数据的攻击问题;反序列化(把序列化字符串还原为Array)的哈希碰撞攻击,到目前位置PHP官方还没有彻底解决这个问题,请尽量避免用户篡改数据和中间人攻击。
关于作者:王帅,腾讯企业QQ SaaS团队Leader。
更多《问底》内容
《问底》是CSDN云计算频道新建栏目,以实践为本,分享个人对于新时代软件架构与研发的深刻见解。在含有“【问底】”字样标题的文章中,你会看到某个国外IT巨头的架构分享,会看到国内资深工程师对某个技术的实践总结,更会看到一系列关于某个新技术的探索。《问底》邀请对技术具有独特/深刻见解的你一起打造一片只属于技术的天空,详情可邮件至。
免费订阅“CSDN云计算(左)和CSDN大数据(右)”微信公众号,实时掌握第一手云中消息,了解最新的大数据进展!
CSDN发布虚拟化、Docker、OpenStack、CloudStack、数据中心等相关云计算资讯, & & 分享Hadoop、Spark、NoSQL/NewSQL、HBase、Impala、内存计算、流计算、机器学习和智能算法等相关大数据观点,提供云计算和大数据技术、平台、实践和产业信息等服务。
推荐阅读相关主题:
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章

我要回帖

更多关于 stringextend 的文章

 

随机推荐