PHP代码审计-变量覆盖
PHP变量覆盖
1 register_global
全局变量注册,本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。
当在php.ini开启register_globals= On时,代码中的参数会被用户提交的参数覆盖掉。
1 |
|
当访问http://127.0.0.1/1.php时输出没有覆盖
但是当请求http://127.0.0.1/1.php?auth=1时会覆盖掉$auth输出覆盖。
2 extract()
从数组中将变量导入到当前的符号表 直接看代码
1 |
|
同样请求http://127.0.0.1/1.php?auth=1时会覆盖掉$auth输出over。
3 $$
$$符号在php中叫做可变变量,可以使变量名动态设置。举个例子
1 |
|
这里$$b = $a,$$b就将 $a 中的值改掉了
1 | $auth=0; |
在第二行中遍历了全局变量$_GET,第三行将key当作变量名,把value赋值。 那么我们传入http://127.0.0.1/1.php?auth=1时会将$auth的值覆盖为1
4 import_request_variables
将 GET/POST/Cookie 变量导入到全局作用域中,如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。那么和register_globals存在相同的变量覆盖问题。
1 | $auth = '0'; |
同样传入http://127.0.0.1/1.php?auth=1时会将$auth的值覆盖为1,输出over!
5 parse_str()
将字符串解析成多个变量
1 | $a='aa'; |
可以看出来将$str解析为$a='test',与parse_str()类似的函数还有mb_parse_str(),不在赘述。
来看ctf中的一道题:
1 |
|
在第五行将请求的URI通过parse_url()解析后赋值给$parsed变量。
在第八行将我们提交的query参数使用parse_str解析,这时就产生了变量覆盖的问题,我们可以通过query提交参数去覆盖变量。
接着往下看$hashed_input!==$hashed_key成立输出flag,此时$hashed_input我们可控,那么我们可以覆盖掉$hashed_key来使条件成立
$hashed_input = hash('sha256', $key);是sha256加密,那么我们可以传入key=a,此时$hashed_input等于ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb。
然后覆盖$hashed_key,传入query=&hashed_key=ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb覆盖掉。
这时payload为
1 | http://39.100.83.188:8066/?query=&hashed_key=ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb&action=auth&key=a |
可能有人会疑惑参数hashed_key前为什么要加&
如果直接
?query=hashed_key=...,那么parse_str("hashed_key=...")只会设置$hashed_key但我们需要同时设置
$action和$key变量所以需要:
?query=&hashed_key=...&action=auth&key=a- 开头的
&确保hashed_key被正确解析为一个独立的参数 - 后面的
&action=auth&key=a设置其他必要变量
- 开头的