zoukankan      html  css  js  c++  java
  • php中的一些需要注意点

    PHP中的全局变量global和GLOBALS的区别

    1、global

    global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。但是在函数体内定义的global变量,函数体内可以使用,在函数体外定义的global变量不能再函数体内使用。

    2、$GLOBALS

    $GLOBALS数组中,每一个变量为一个元素,键名对应变量名,值对应变量的内容。$GLOBALS是一个超全局变量。注意$GLOBALS的写法,比如变量$a1,写法为$GLOBALS['a1'].

     

    变量覆盖问题

    register_globals

     register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过来的参数。
     register_globals为on的时候,传递过来的值会被直接注册为全局变量直接引用,而off的时候,我们需要到特定的数组里去得到它。
     例如:
     register_globals=off的时候,下一个程序接收的时候应该用$GET['user_name']和$_GET['user_pass']来接收传递过来的值。
     register_globals=On的时候,下一个程序可以直接使用$user_name和$user_pass来接收值。

    经常导致变量覆盖漏洞的场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。

    $$导致的变量覆盖问题

    $$这种写法称为可变变量,一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。

     <?php
     $a = "hello";
     echo "$a";              //输出hello
     $a="world";
     echo "$a";              //输出hello
     echo "$$a";            //输出word
     echo "$a ${$a}";    //输出hello world
     echo "$a $hello";  //输出hello world
     ?>
    漏洞产生

    使用foreach来遍历数组中的值,然后在将获取到的数组键名作为变量,数组中的键值作为变量的值,因此产生了变量覆盖漏洞。

     <?php
     foreach ($_GET as $key => $value) {
     ${$key} = $value;
     }
     echo $a;
     ?>

    get得到的数据value,关键第3行,用传进来的key做为新的变量,将get传进来的赋值给它。第行回解析为a=1。就造成了变量覆盖。

    extract()函数使用不当
    1、extract()函数介绍

    extract()函数从数组中将变量导入到当前的符号表。

    该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

    该函数返回成功设置的变量数目。

    2、语法

    extract(array,extract_rules,prefix)

    参数 描述

    array必需。规定要使用的数组

    extract_rules可选。extract()函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据参数决定。

    可能的值: EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。 EXTR_SKIP - 如果有冲突,不覆盖已有的变量。 EXTR_PREFIX_SAME - 如果有冲突,在变量名前加上前缀 prefix。 EXTR_PREFIX_ALL - 给所有变量名加上前缀 prefix。 EXTR_PREFIX_INVALID -仅在不合法或数字变量名前加上前缀 prefix。 EXTR_IF_EXISTS - 仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。 EXTR_PREFIX_IF_EXISTS - 仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。 EXTR_REFS - 将变量作为引用提取。导入的变量仍然引用了数组参数的值。

    prefix可选。 如果 extract_rules 参数的值是 EXTR_PREFIX_SAME、EXTR_PREFIX_ALL、 EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS,则 prefix 是必需的。 该参数规定了前缀。前缀和数组键名之间会自动加上一个下划线。

    从以上说明我们可以看到第一个参数是必须的,会不会导致变量覆盖漏洞由第二个参数决定,该函数有三种情况会覆盖已有变量。

     <?php
     $a = 1;    //原变量值为1
     $b = array('a' => '3');
     extract($b);    //经过extract()函数对$b处理后
     echo $a;    //输出结果为3
     ?>
    3、漏洞重现
     "extract($_GET);
     if(isset($bdctf))
     {
     $content=trim(file_get_contents($flag));//file_get_contents—将整个文件读入一个字符串
     if($bdctf==$content)                             //trim—去除字符串首尾处的空白字符(或者其他字符)
     { echo'bdctf{**********}'; }
     else
     { echo'这不是蓝盾的密码啊'; }
     }"

    题目分析 题目使用了extract($_GET)接收了GET请求中的数据,并将键名和键值转换为变量名和变量的值,然后再进行两个if 的条件判断,所以可以使用GET提交参数和值,利用extract()对变量进行覆盖,从而满足各个条件。

    解题思路 if($bdctf==​$content) 输出flag 利用extract($_GET)漏洞,使$bdctf与​$content都为空或者不存在就满足 ​$bdctf==$content get ?flag=&bdctf= 得到flag

     

    parse_str()函数使用不当

    1、parse_str函数介绍

    parse_str()函数把查询字符串解析到变量中。

    注释:如果未设置array参数,由该函数设置的变量将覆盖已存在的同名变量。

    注释:php.ini文件中的magic_quotes_gpc设置影响该函数的输出。如果已启用,那么在parse_str()解析之前,变量会被addslashes()转换。

    parse_str函数的作用就是解析字符串并注册成变量,在注册变量之前不会验证当前变量是否存在,所以直接覆盖掉已有变量

    2、语法

    parse_str(string,array)**

    参数描述

    string必需。规定要解析的字符串。

    array可选。规定存储变量的数组名称。该参数指示变量存储到数组中。

    import_request_variables()使用不当

    1、import_request_variables()函数介绍

    import_request_variables 将GET/POST/Cookie变量导入到全局作用域中

    import_request_varibales()函数就是把GET、POST、COOKIE的参数注册成变量,用在register_globals被禁止的时候

    2、语法

    bool import_request_variables(string$type,[string$prefix])

    $type代表要注册的变量,G表示GET,P表示POST,C代表COOKIE,第二个参数为前缀

    PHP中0、空、null和false之间的区别

    原因是PHP中变量是以C语言的结构体来存储的,空字符串和NULL,false都是以值为0存储的,其中这个结构体有个zen_uchartype;这样的成员变量,他是用来保存变量的类型的,而空字符串的类型是string,NULL的类型是NULL, false是boolean

    所以空字符串'',false,NULL和0是值相同而类型不一样

    注意:NULL是一种特殊的类型,两种情况下为NULL。

    1、$var = NULL;

    2、$var;

    3、""、0、"0"、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的,如果var为空,则返回TRUE(这地方我是不太理解的)

     $a =  0;
     $b="0";
     $c= '';
     $d= null;
     $e = false;
     
     echo "5个变量-原始测试类型";
         var_dump($a);//int 0
         var_dump($b);//string '0'
         var_dump($c);//string ''
         var_dump($d);//null
         var_dump($e);//boolean false
     
     echo "<h4>empty测试</h4>";
         var_dump(empty($a));//true
         var_dump(empty($b));//true
         var_dump(empty($c));//true
         var_dump(empty($d));//true
         var_dump(empty($e));//true
     
     echo "<hr>";
         var_dump(isset($a));//true
         var_dump(isset($b));//true
         var_dump(isset($c));//true
         var_dump(isset($d));//【false】 见结论一
         var_dump(isset($e));//true
     
     echo "<h4>(==)双等式测试</h4>";
         var_dump($a == $b);//true
         var_dump($a == $c);//true
         var_dump($a == $d);//true
         var_dump($a == $e);//true !!
     
         var_dump($b == $c);//【false】见结论二
         var_dump($b == $d);//【false】见结论二
         var_dump($b == $e);//true
     
         var_dump($c == $d);//true
         var_dump($c == $e);//true
     
     echo "<h4>(===)三等式测试</h4>";
         var_dump($a === $b);//false
         var_dump($a === $c);//false
         var_dump($a === $d);//false
         var_dump($a === $e);//false
     
         var_dump($b === $c);//false
         var_dump($b === $d);//false
         var_dump($b === $e);//false
     
         var_dump($c === $d);//false
         var_dump($c === $e);//false

    总结

    对于【0;'0';'';null;false】五种类型

    empty操作以上五个变量,都返回false

    结论一:

    关于变量类型的理解

    1.null为不存在之意:php底层的zval空间里(结构见下方)没有存其value值,只存储了一个type标志其 IS_NULL(所以解释了 empty(null)=true,isset(null)=false ,isset('')=true)

    2.【0 ; '0' ; '' ; false 】:这四个为存在,php底层是开辟zval空间存储,有value,有type.

    结论二:

    1、string '0'与 string '' 不相等,(想一下就明白,同类型比较【1个长度】的字符串怎么可能 等于 【0个长度】 的字符串)

    2、int 0 却和 string '' 空相等,(非同类形比较,php会做类型转换)

    3、string '0'null 不相等,int 0null 相等

    ereg()

    ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true否则返回false。搜索字母的字符是大小写敏感的。

    ereg函数存在NULL截断漏洞,导致正则过滤被绕过,所以可以使用%00截断正则匹配。

    ereg()只能处理字符串,遇到数组做参数返回NULL,判断用的是===,要求类型也相同,而NULL跟FALSE类型是不同的,strpos()参数同样不能为数组,否则返回NULL。

    preg_replace()函数

     preg_replace($pattern, $replacement, $subject)
     函数作用:搜索subject中匹配pattern的部分,以replacement进行替换。
     $pattern:要搜索的模式,可以是字符串或一个字符串数组
     $replacement:用于替换的字符串或字符串数组。
     $subject:要搜索替换的目标字符串或字符串数组

    preg_replace函数的参数pattern输入/e模式的时候,参数replacement的代码当做PHP代码执行。

     

    intval()函数绕过

    intval函数参数填入科学计数法的字符串,会以e前面的数字作为返回值,而对于科学计数法+数字则会返回字符串类型。

     <?php
     $num='2e4';
     echo(intval($num));    //输出2
     echo('<br>');
     echo(intval($num+1));  //输出20001
     ?>

     

     

     

     

     

     

  • 相关阅读:
    第一次离职
    代码人生
    Array.Sort()实现细节和效率
    步入正轨
    2013,冲刺、加油!!!
    Struts2 OGNL 字符串自定义转化对象细节
    Struts2 输入格式自动校验的一些注意事项
    MySQL 5.7.17 Windows安装和启动
    关于Hibernate 5 和 Hibernate 4 在创建SessionFactory的不同点分析(解决 org.hibernate.MappingException: Unknown entity: xx类报错问题)
    Struts2 OGNL 自动转换Date类型的一些注意事项
  • 原文地址:https://www.cnblogs.com/shijiahao/p/13416732.html
Copyright © 2011-2022 走看看