PHP是WEB爷入门的东西,所以我打算好好学学习它,并把相关内容记下来,慢慢来...

危险函数
命令执行
system()
, passthru()
, exec()
, shell_exec(
, `
, popen()
, proc_open()
, pcntl_exec(
代码执行
eval\s*\(
, asert\s*\(
,preg_replace\s*\(
, call_user_func\s*\(
, include
, require
,call_user_func_array(
, create_function(
, array_map(
, ob_start(
, mail(
, usort
, uasort
还有个
preg_replace_callback
可以用来执行代码,写后门用吧
反序列化
反序列化可构造任意值,而一些魔法方法(__destruct
、__toString
、__sleep
、__wakeup
、__call
、__construct
)若存在问题可执行危险操作[2],若存在框架可看phpggc是否有已知Gadget,主要找unserialize
和phar
利用点。
这里重点看phar,它可类比为java中的jar文件,其具体存储可用zip/tar/phar格式,其中phar是专为该功能设计的格式,它们含如下内容:
1.stub
为一段bootstrap代码,当在执行上下文(如include文件时)会执行它,它里面至少要有<?php ... __HALT_COMPILER();
让引擎不再解析后面的内容,这在phar中位于文件首部,而在zip/tar中位于.phar/stub.php
文件里
2.manifest
含各种属性信息,里面最需要关注的是元数据metadata,它是序列化后的数据并且会被自动反序列化,元数据在zip中会被存放在单个文件或整体的注释(comment)里
3.contents
没啥说的就是数据内容,根据存储格式可被bzip2/gzip按单个文件或整体压缩
4.signatuer
是只存在于phar格式的签名信息(其实是摘要),包括签名值,签名算法和魔数GBMB
,这意味着phar文件首部任意但尾部得合法(该部分可配置为不校验)
phar通常通过phar://
流封装来触发,其利用条件如下:
1.能控制本地文件的全部或部分内容,例如通过文件上传方式或往session写内容等将恶意构造的phar文件写入,文件扩展名随意,文件可以被压缩去绕过某些检测
2.有使用文件流的地方且路径前半部可控,这样可通过phar://
去操作恶意文件,这里若它对phar有检测,可尝试用php://filter/resource=phar://
/compress.[bzip2|zlib]://phar://
等方式来绕过,至于文件流相关函数见下文(也可参考[1])
3.存在反序列化利用链,注意由于这里的元数据不会在其他地方使用因此只有__wakeup
和__destruct
能作为链的入口[0]
参考
[0] File Operation Induced Unserialization via the “phar://” Stream Wrapper (PPT)
[1] Phar与Stream Wrapper造成PHP RCE的深入挖掘
变量覆盖
当使用$$
, extract
没接收结果, parse_str
没提供第二个参数, import_request_variables
, register_globals=ON(配置文件)
时可能存在变量覆盖漏洞,向$GLOBAL
中任意写也会存在变量覆盖。PHP会解析GET/POST方式传入的字典,因此利用该漏洞可以覆盖很多危险点,如用?_SERVER[REMOTE_ADDR]=$(id)
来控制原本不可控的点从而实现地址伪造或进行注入
文件操作
主要关心文件读写操作:file_get_contents
, file_put_contents
,move_uploaded_file
, rename
,unlink
, rmdir
,fopen, fread
, fwrite
, fputs
, fgets
, fgetc
, readfile
, highlight_file
, show_source
, parse_ini_file
注:几乎所有能输入文件名的函数都可解析伪协议,利用此可绕过一些限制(如路径后缀)或实现其他攻击(如反序列化)...
解码操作
base64_decode
, urldecode
, decode
,aes
, des
, sm4
, (a)rc4
, blowfish
, crypt
, decrypt
,md5
, auth
, rand
, srand
, seed
注:在使用rand时,若存在足够的样本可用php_mt_rand反推出种子
服务端请求伪造
关注:file_get_contents
,curl
,fsockopen
,readfile
,fopen
等
其他
安全相关函数
1.addslashes
: 为'
/"
/\
/NUL
添加\
转义,由于它只懂PHP语意并不适用于其他组件(如不适合MySql过滤,可能存在无'
时绕过或宽子节注入)
2.htmlspecialchars
/htmlentities
: HTML实体编码,可以防XSS
3.strip_tags
: 删除字符串中的HTML/PHP/JS等标记,仅此而已
4.escapeshellcmd
: 作用于整条命令,防止多条命令被执行(他不会对参数转义,因此可以任意加参数),具体的,它在这些符号&#;`|*?~<>^()[]{}$\, \x0A 和 \xFF
前加\
转义,以及对不匹配的'"
转义
5.escapeshellarg
: 用于对单个参数进行转义
超全局变量
有9个超全局变量,如$GLOBAL
是全局变量的引用,不过这里主要关注$_SERVER
,它里面有很多字段:
1.SERVER_NAME
/SERVER_PORT
: 如果webserver没设置,则使用HOST头里的值
2.PHP_SELF
是当前URI(包括PATH_INFO但不包括QUERY_STRING),PATH_INFO
是URI中.php
之后的内容,SCRIPT_NAME
是PHP_SELF去掉PHP_INFO的内容
3.SCRIPT_FILENAME
是当前脚本的绝对地址(符号连接未解析),PATH_TRANSLATED
是解析符号连接后的绝对地址
特殊配置
配置 | 说明 |
---|---|
register_globals | 早期支持,会把请求注册到全局 |
magic_quotes_gpc | 设置后GPC的'"\0x00会被转意 |
disable_functions | 限制了能使用的函数,通过其他其他组件绕 |
open_basedir | 限定了能打开的目录,可通过DirectoryIterator+Glob绕 |
版本特性
这里记录每个版本间与安全相关的变化...
5.X
版本 | 新增或修改 | 删除 |
---|---|---|
4.0->5.0 | include_once /require_once 在windows下不区分路径大小写 |
- |
5.1->5.2 | 添加了data: 流; libxml_disable_entity_loader 可设置不加载外部实体,libxml 2.9.0 开始默认不处理实体了; 新增了filter 模块用于对变量进行过滤; 新增allow_url_include 选项来禁止远程文件包含,且默认禁止 |
- |
5.2->5.3 | 新增glob:// 和phar:// 流封装; 新增dechunk 流过滤器,bz2.decompress 支持串联了; 新增了内置Phar |
- |
5.3->5.4 | <?= 形式的短标签始终可用 |
不再支持register_globals 选项; 不再支持安全模式safe mode ; 不再支持magic_quotes_[gpc|runtime|sybase] 选项 |
5.5->5.6 | php://input 现在可多次打开来重用; 添加hash_equals 函数进行安全的字符串比较 |
- |
7.X
版本 | 新增或修改 | 删除 |
---|---|---|
5.6->7.0 | string处理时,16进制字符串不再被认为是数字,因此在一些比较时将会失败; int转换时8进制时若存在无效数字现在将直接出错而不是截断; 整数溢出会产生E_WARNING错误并返回null而不是截断; unserialize 支持设置允许反序列化的类(默认允许所有); assert 现在是一个语言结构而非函数了 |
不再支持preg_replace() 的/e 选项; 不再支持<%%> /<%= %> /` |