mysql 多字节编码漏洞_[三个白帽子]is_numeric的理解和PHP 脚本多字节字符解析模式带来的安全隐患writeup...

0x01 is_numeric理解

简单翻看is_numeric实现代码,is_numeric对输入的参数,先做了样式判断如果是整型、浮点型就直接返回true,如果是字符串则进入is_numeric_string函数进行判断

switch (Z_TYPE_P(arg)) {

case IS_LONG:

case IS_DOUBLE:

RETURN_TRUE;

break;

case IS_STRING:

if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) {

RETURN_TRUE;

} else {

RETURN_FALSE;

}

break;

default:

RETURN_FALSE;

break;

经过查找,找到真正的处理函数_is_numeric_string_ex,省略一些代码,我们只用知道哪些字符能够出现在is_numeric的参数中,很明显可以看出,

空格、\t、\n、\r、\v、\f、+、-能够出现在参数开头,“点”能够在参数任何位置,E、e只能出现在参数中间。

ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(......) /* {{{ */

{

......

/* Skip any whitespace

* This is much faster than the isspace() function */

while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {

str++;

length--;

}

ptr = str;

if (*ptr == '-') {

neg = 1;

ptr++;

} else if (*ptr == '+') {

ptr++;

}

if (ZEND_IS_DIGIT(*ptr)) {

/* Skip any leading 0s */

while (*ptr == '0') {

ptr++;

}

....

for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {

check_digits:

if (ZEND_IS_DIGIT(*ptr)) {

tmp_lval = tmp_lval * 10 + (*ptr) - '0';

continue;

} else if (*ptr == '.' && dp_or_e < 1) {

goto process_double;

} else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {

const char *e = ptr + 1;

if (*e == '-' || *e == '+') {

ptr = e++;

}

if (ZEND_IS_DIGIT(*e)) {

goto process_double;

}

}

break;

}

......

}

}

再看下我们的题目中第一个需要bypass的地方:

if(is_numeric($num)&&!in_array($num[0],$filter)&&strtolower(urlencode($num[0]))!='%0b'&&!preg_match('/[\s]{1,}/',$num[0]) && !intval($num))

1.is_numeric($num)检测

2.!in_array($num[0],$filter)过滤array('0',' ','\n','\t','\r','\v','\f','+','-');

3.strtolower(urlencode($num[0]))!='%0b'过滤%0b

4.!preg_match('/[\s]{1,}/',$num[0]) 过滤\t\n\r\f\v

5.!intval($num) 必须intval检测返回false

综合看下来”.0“似乎是唯一选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值