PHP代码审计之超全局变量 代码审计基础之超全局变量 $GET $POST $COOKIE $FILES $SESSION $SERVER $HTTP_RAW_POST_DATA $GLOBALS
$GET
直接从URL获取参数,参数构成一个数组,传入的参数既可以是字符串形式,也可以是数组形式(这是以前常用的绕过技巧)。
<?php var_dump($_GET); ?> //输入 ?var[1]=1&var[][]=test //输出 array(size=2) 'var' => array(size=1) 1 =>string '1' (length=1) 'var' => array (size=1) 0=> array(size=1) 0 => string 'test' (length=4)
有一些函数在处理参数时候,遇到意料之外的参数类型,比如本来是int,结果传入了array, 那么就会产生意料之外的结果,根据进一步的运行有可能可以绕过。
那如果传入多个相同的变量呢?
<?php var_dump($_GET); ?> //输入 ?var=1&var=2 //输出 array (size=1) 'var' => string '2' (length=1)
当然这只是在php是这样,其他语言可不是,比如asp会将相同变量进行拼接。(注意,如果传 入的是相同的数组,比如传入两个var[],是不会覆盖的,下标会自动递增)
$POST
和GET处理相同,只是传入位置发生变化。建议大家安装hackbar,不用每次POST都打开burp(一款火狐的插件)。 注意,传入的content-type必须是application/x-www-form- urlencoded或者multipart/form-data,否则没有办法生成$_POST数组。因此,PHP处理类似 xml文件(content-type:text/xml)时,采取的是别的方法。
$COOKIE
与GET,POST不同处在于分隔符为分号(;),其他一样。、
上面讲述的三个超全局变量,往往是过滤的最严格的。一般来讲,这三个变量都会做全局防护,比如遍历调用addslashes等。 REQUEST则是包含了GET,POST和COOKIE,将其三个合并到同一数组中。
$FILES
传入时对应的key为 <input type="file" name="xx"> 的name值。注意,FILES的type值是客户端传入的MIMETYPE,因此是不可信的。所以比较常用的方法是正则检测后缀名然后白名单筛选,同时对幻数以及相关信息做检测。
<?php var_dump($_FILES); ?> array (size=1) 'test' => array (size=5) 'name' => string '1.txt' (length=5) 'type' => string 'text/plain' (length=10) 'tmp_name' => string '/Applications/MAMP/tmp/php/phpsfA3vQ' (length=36) 'error' => int 0 'size' => int 16
//myfile就是上面那个唯一的name值
$_FILES['myFile']['name'] 客户端文件的原名称。 $_FILES['myFile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。 $_FILES['myFile']['size'] 已上传文件的大小,单位为字节。 $_FILES['myFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,但 用 putenv() 函数设置是不起作用的。 $_FILES['myFile']['error'] 和该文件上传相关的错误代码。['error'] 是在 PHP 4.2.0 版本中增加的。下面是它的说明:(它们在PHP3.0以后成了常量) UPLOAD_ERR_OK 值:0; 没有错误发生,文件上传成功。 UPLOAD_ERR_INI_SIZE 值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。 UPLOAD_ERR_FORM_SIZE 值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。 UPLOAD_ERR_PARTIAL 值:3; 文件只有部分被上传。 UPLOAD_ERR_NO_FILE 值:4; 没有文件被上传。 值:5; 上传文件大小为0.
文件被上传结束后,默认地被存储在了临时目录中,这时必须将它从临时目录中删除或移动到其它地方,如果没有,则会被删除。
$SESSION
可以将其理解成一个针对每个用户的单独的存储空间,存储用户的一些信息。一般使用cookie 作为对应的key值。存储方式也是为数组。
<?php session_start();//加载session变量 $_SESSION[$_COOKIE['PHPSESSID']] = 1; var_dump($_SESSION); session_destroy();//销毁session变量 ?> array (size=1) '0eded10f2372c5b05fcb053c5fa48bfa' => int 1
如果不销毁,则会存储在临时目录当中。查看临时存储目录可通过pathinfo查看。
$SERVER
服务器和请求头的信息。注意,这里即使是非法的头信息,也是可以传入的。
<?php var_dump($SERVER); ?>
在发送的过程中,我在请求头中添加了 fuck: you 。随后在页面当中我们看到了。
'HTTP_FUCK' => string 'you' (length=3)
当然,这个其实并不常用,因为服务器一般不会调用这个变量。除非涉及到一些遍历输出SERVER信息或存储SERVER信息时,可能会用到。 但是其他请求头,如UA等,调用较多, 而很多时候对这种信息,开发者往往疏与防范,因此有可能成为突破口。
- $_SERVER['HTTP_HOST'] 请求头信息中的Host内容,获取当前域名。
- $_SERVER["SERVER_NAME"] 输出配置文件httpd.conf中的ServerName,一般情况下与HTTP_HOST值相同,但如果服务器端口不是默认的80端口,或者协议规范不是HTTP/1.1时,HTTP_HOST会包含这些信息,而SERVER_NAME不一定包含。(主要看配置文件的设置)。
- $_SERVER["HTTP_USER_AGENT"] 获取用户相关信息,包括用户浏览器、操作系统等信息。
- $_SERVER['HTTP_ACCEPT'] 当前请求的ACCEPT头部信息。
- $_SERVER["HTTP_ACCEPT_LANGUAGE"] 这个值是由浏览器发送,表明用户默认的语言设置,后面的q值表示用户对该语言的喜好程度。
- $_SERVER["HTTP_ACCEPT_ENCODING"] 大部分的现代浏览器都支持gzip压缩,并会把这一信息报告给服务器。这时服务器就会压缩过的HTML发送给浏览器。这可以减少近80%的文件大小,以节省下载时间和带宽。
- $_SERVER["HTTP_COOKIE"] 浏览器的cookie信息。
- $_SERVER["HTTP_CONNECTION"] 当前请求的连接情况。
- $_SERVER["HTTP_UPGRADE_INSECURE_REQUESTS"] 表示浏览器可读懂服务器发过来的请求,
- $_SERVER["HTTP_CACHE_CONTROL"] 表示浏览器是否会缓存这个页面信息。
- $_SERVER["PATH"] 当前脚本所在文件系统。
- $_SERVER["SystemRoot"] 当前服务器的操作系统。
- $_SERVER["COMSPEC"] 指向cmd.exe的路径。
- $_SERVER["PATHEXT"] 环境变量设置。
- $_SERVER["WINDIR"] 脚本指向的系统目录。
- $_SERVER["SERVER_SIGNATURE"] 包含服务器版本和虚拟主机名的字符串。
- $_SERVER["SERVER_SOFTWARE"] 服务器软件配置信息。
- $_SERVER["SERVER_ADDR"] 当前运行脚本的服务器的ip地址。
- $_SERVER["SERVER_PORT"] 服务器端口。
- $_SERVER["REMOTE_ADDR"] 浏览网页的用户ip。
- $_SERVER["DOCUMENT_ROOT"] 当前运行脚本所在的根目录。
- $_SERVER["REQUEST_SCHEME"] 服务器通信协议,是http或https。
- $_SERVER["CONTEXT_PREFIX"] 前缀。
- $_SERVER["CONTEXT_DOCUMENT_ROOT"] 当前脚本所在的文档根目录。
- $_SERVER["SERVER_ADMIN"] 服务器管理员信息。
- $_SERVER["SCRIPT_FILENAME"] 当前执行脚本的绝对路径。
- $_SERVER ["REMOTE_PORT"] 用户连接到服务器时所使用的端口。
- $_SERVER["GATEWAY_INTERFACE"] 服务器使用的CGI规范的版本。
- $_SERVER["SERVER_PROTOCOL"] 请求页面时通信协议的名称和版本。
- $_SERVER["REQUEST_METHOD"] 请求提交数据的方式。
- $_SERVER["QUERY_STRING"] 服务器请求时?后面的参数。
- $_SERVER["REQUEST_URI"] 当前脚本路径,根目录之后的目录。
- $_SERVER["SCRIPT_NAME"] 当前脚本的路径。这在页面需要指向自己时非常有用。
- $_SERVER["PHP_SELF"] 当前正在执行脚本的文件名。
- $_SERVER["REQUEST_TIME"] 得到请求开始时的时间戳。
$HTTP_RAW_POST_DATA
前面提到,有些时候,因为MIMETYPE的问题,没法使用POST。那么这个时候就可能会去考 虑获取HTTP_RAW_POST_DATA。此时得到的就是一个字符串。因此,POST和HTTP_RAW_POST_DATA是完全两个不同的概念,对POST进行了过滤,不代表对HTTP_RAW_POST_DATA进行了过滤。(当然,现在普遍是使用php://input,原因可参考php 手册)
$GLOBALS
大杂烩,以数组形式包含了其他变量数组。
Refer:
https://github.com/ChrisLinn/greyhame-2017/blob/master/shared-files/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%9F%BA%E7%A1%80%E4%B9%8B%E8%B6%85%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F.pdf