PHP-tips

PHP-tips

变量覆盖

extract()

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。条件:若有EXTR_SKIP则不行。

<?php
$a = "Original";
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>
# 结果:$a = Cat; $b = Dog; $c = Horse
复制代码

这里原来是$a是original,后面通过extract把$a覆盖变成了Cat了,所以这里把原来的变量给覆盖了。

#?shiyan=&flag=1
<?php
$flag='xxx';
extract($_GET);
 if(isset($shiyan))
 {
    $content=trim(file_get_contents($flag)); # content is 0 , flag can be anything,cause file_get_contents cannot open file, return 0
    if($shiyan==$content)
    {
        echo'ctf{xxx}';
    }
   else
   {
    echo'Oh.no';
   }
   }
复制代码

parse_str()

解析字符串并注册成变量

import_request_variables()

?变量覆盖

全局变量覆盖漏洞

原理: register_globals 是php中的一个控制选项,可以设置成off或者on, 默认为off, 决定是否将 EGPCS(Environment,GET,POST,Cookie,Server)变量注册为全局变量。 如果register_globals打开的话, 客户端提交的数据中含有GLOBALS变量名, 就会覆盖服务器上的$GLOBALS变量.

$_REQUEST 这个超全局变量的值受 php.inirequest_order的影响,在php5.3.x系列中,request_order默认值为GP,也就是说默认配置下$_REQUEST只包含$_GET$_POST而不包括$_COOKIE。通过COOKIE就可以提交GLOBALS变量。

经过测试,开了register_globals会卡死

绕过过滤的空白字符

原理:baike.baidu.com/item/控制字符

而trim过滤的空白字符有

其中缺少了\f

2 函数对空白字符的特性

is_numeric函数在开始判断前,会先跳过所有空白字符。这是一个特性。

也就是说,is_numeirc(" \r\n \t 1.2")是会返回true的。同理,intval(" \r\n \t 12"),也会正常返回12。

案例

[github.com/bowu678/php…](https://github.com/bowu678/php_bugs/blob/master/02 绕过过滤的空白字符.php)

intval整数溢出

php整数上限溢出绕过intval

intval 函数最大的值取决于操作系统。 32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。举例,在这样的系统上, intval('1000000000000') 会返回 2147483647。 64 位系统上,最大带符号的 integer 值是 9223372036854775807。

intval 四舍五入

浮点数精度忽略

在小数小于某个值(10^-16)以后,再比较的时候就分不清大小了。 输入number = 1.00000000000000010, 右边变成1.0, 而左与右比较会相等。

多重加密

题目中有:

本地则写:

截断

iconv 异常字符截断

eregi、ereg可用%00截断

功能:正则匹配过滤 条件:要求php<5.3.4

move_uploaded_file 用\0截断

5.4.x<= 5.4.39, 5.5.x<= 5.5.23, 5.6.x <= 5.6.7

在高版本(受影响版本中),PHP把长度比较的安全检查逻辑给去掉了,导致了漏洞的发生

cve:web.nvd.nist.gov/view/vuln/d…

move_uploaded_file($_FILES['x']['tmp_name'],"/tmp/test.php\x00.jpg") 上传抓包修改name为a.php\0jpg(\0是nul字符),可以看到$_FILES['xx']['name']存储的字符串是a.php,不会包含\0截断之后的字符,因此并不影响代码的验证逻辑。 但是如果通过$_REQUEST方式获取的,则可能出现扩展名期望值不一致的情况,造成“任意文件上传”。

inclue用?截断

当输入的文件名包含URL时,问号截断则会发生,并且这个利用方式不受PHP版本限制,原因是Web服务其会将问号看成一个请求参数。

测试POC:http://127.0.0.1/test/t1.php?name=http://127.0.0.1/test/secret.txt? 则会打开secret.txt中的文件内容。本测试用例在PHP5.5.38版本上测试通过。

系统长度截断

这种方式在PHP5.3以后的版本中都已经得到了修复。 win260个字符,linux下4*1024=4096字节

mysql长度截断

mysql内的默认字符长度为255,超过的就没了。 由于mysql的sql_mode设置为default的时候,即没有开启STRICT_ALL_TABLES选项时,MySQL对于插入超长的值只会提示warning

mysql中utf-8截断

写入为admin

弱类型比较

原理

比较表:php.net/manual/zh/t…

以下等式会成立

==、>、<的弱类型比较

这里用到了PHP弱类型的一个特性,当一个整形和一个其他类型行比较的时候,会先把其他类型转换成整型再比。

switch 弱类型

md5比较(0e相等、数组为Null)

技巧:找出在某一位置开始是0e的,并包含“XXX”的字符串

json传数据{"key":0}

PHP将POST的数据全部保存为字符串形式,也就没有办法注入数字类型的数据了而JSON则不一样,JSON本身是一个完整的字符串,经过解析之后可能有字符串,数字,布尔等多种类型。

第一个application/x-www-form-urlencoded,是一般表单形式提交的content-type第二个,是包含文件的表单。第三,四个,分别是json和xml,一般是js当中上传的.

{"key":"0"}

这是一个字符串0,我们需要让他为数字类型,用burp拦截,把两个双引号去掉,变成这样:

{"key":0}

strcmp漏洞1:返回0

适用与5.3之前版本的php

int strcmp ( string $str1 , string $str2 ) // 参数 str1第一个字符串。str2第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。 当这个函数接受到了不符合的类型,这个函数将发生错误,但是在5.3之前的php中,显示了报错的警告信息后,将return 0,所以可以故意让其报错,则返回0,则相等了。

strcmp漏洞2:返回Null

修复了上面1的返回0的漏洞,即大于5.3版本后,变成返回NULL。 array和string进行strcmp比较的时候会返回一个null,因为strcmp只会处理字符串参数,如果给个数组的话呢,就会返回NULL。

strcmp漏洞3: 判断使用的是 ==

而判断使用的是==,当NULL==0是 bool(true)

in_array,array_search 弱类型比较

松散比较下,任何string都等于true:

sha1() md5() 报错相等绕过(False === False)

sha1()函数默认的传入参数类型是字符串型,给它传入数组会出现错误,使sha1()函数返回错误,也就是返回false

md5()函数如果成功则返回已计算的 MD5 散列,如果失败则返回 FALSE。可通过传入数组,返回错误。

strpos数组NULL(Null !== False)

strpos()输入数组出错返回null

十六进制与十进制比较

== 两边的十六进制与十进制比较,是可以相等的。

md5注入带入’or’

原理:

当md5函数的第二个参数为True时,编码将以16进制返回,再转换为字符串。而字符串’ffifdyop’的md5加密结果为'or'<trash> 其中 trash为垃圾值,or一个非0值为真,也就绕过了检测。

switch没有break

反序列化

文件包含

原理:

include()/include_once(),require()/require_once(),中的变量可控

利用方法:

  1. 上传图片(含有php代码的图片)

  2. 读文件,读php文件

  3. 包含日志文件getshell

  4. 包含/proc/self/envion文件getshell

  5. 如果有phpinfo可以包含临时文件

  6. 包含data://或php://input等伪协议(需要allow_url_include=On)

封装协议:

提交参数无过滤

原理:过滤了GPC,但没有过滤其它部分。

案例:

通过表单来传值。

这里的gid为查询参数

伪造IP

原理:以 HTTP_ 开头的 header, 均属于客户端发送的内容。那么,如果客户端伪造user-agent/referer/client-ip/x-forward-for,就可以达到伪造IP的目的,php5之后不受GPC影响。

绕过正则匹配

缺少^和$限定

数组绕过正则

str_replace路径穿越

原理:str_replace的过滤方式为其search参数数组从左到右一个一个过滤。

short_open_tag=on 短标签

原理:当 php.ini 的short_open_tag=on时,PHP支持短标签,默认情况下为off。格式为:<?xxxx;?> --> <?xxx;

file_put_contents第二个参数传入数组

原理:

单引号和双引号

原理:单引号或双引号都可以用来定义字符串。但只有双引号会调用解析器。

查询语句缺少单引号

宽字符注入

原理:

常见转码函数: iconv() mb_convert_encoding() addslashes

防御:

用mysql_real_escape_string

跳转无退出

原理:没有使用return()或die()或exit()退出流程的话,下面的代码还是会继续执行。可以使用burp测试,不会跳转过去。

二次编码注入

由于浏览器的一次urldecode,再由服务器端函数的一次decode,造成二次编码,而绕过过滤。如%2527,两次urldecode会最后变成'

前端可控变量填充导致XSS

当html里的链接是变量时,易出现XSS。

命令执行函数

防范方法:

  1. 使用自定义函数或函数库来替代外部命令的功能

  2. 使用escapeshellarg 函数来处理命令参数

  3. 使用safe_mode_exec_dir 指定可执行文件的路径

create_function

create_function构造了一个return后面的语句为一个函数。

mb_ereg_replace()的/e模式

原理

preg_replace /e模式执行命令

动态函数执行

代码执行

eval()和assert()代码执行

当assert()的参数为字符串时 可执行PHP代码。 区别:assert可以不加;,eval不可以不加。

优先级绕过

原理:如果运算符优先级相同,那运算符的结合方向决定了该如何运算 php.net/manual/zh/l…

优先级:&&/|| 大于 = 大于 AND/OR

getimagesize图片判断绕过

原理:

当用getimagesize判断文件是否为图片,可以判断的文件为gif/png/jpg,如果指定的文件如果不是有效的图像,会返回 false。 只要我们在文件头部加入GIF89a后可以上传任意后缀文件。

生成小马图的方法:

<变*,windows findfirstfile利用

原理:Windows下,在搜索文件的时候使用了FindFirstFile这一个winapi函数,该函数到一个文件夹(包含子文件夹)去搜索指定文件。 执行过程中,字符">"被替换成"?",字符"<"被替换成"*",而符号"(双引号)被替换成一个"."字符。所以:

  1. ">"">>"可代替一个字符,"<"可以代替后缀名多个字符(即.后的字符),"<<"可以代替包括文件名和后缀名多个字符。所以一般使用<<

  2. " 可以代替.

  3. 文件名第一个字符是"."的话,读取时可以忽略之

NO
Status
Function
Type of operation

1.

OK

include()

Includefile

2.

OK

include_once()

Includefile

3.

OK

require()

Includefile

4.

OK

require_once()

Include file

5.

OK

fopen()

Openfile

6.

OK

ZipArchive::open()

Archive file

7.

OK

copy()

Copyfile

8.

OK

file_get_contents()

Readfile

9.

OK

parse_ini_file()

Readfile

10.

OK

readfile()

Readfile

11.

OK

file_put_contents()

Write file

12.

OK

mkdir()

New directory creation

13.

OK

tempnam()

New file creation

14.

OK

touch()

New file creation

15.

OK

move_uploaded_file()

Move operation

16.

OK

opendiit)

Directory operation

17.

OK

readdir()

Directory operation

18.

OK

rewinddir()

Directory operation

19.

OK

closedir()

Directory operation

20.

FAIL

rename()

Move operation

21.

FAIL

unlink()

Delete file

22.

FAIL

rmdir())

Directory operation

Linux 通配符利用

原理:linux下,*代表任意字符(0到多个),?代表一个字符,所以如果是有执行linux系统命令,那就可以用这些通配符来绕过过滤,并执行我们想要的命令

处理value没有处理key

foreach时,addslashes对获得的value值进行处理,但没有处理key。

用来目录遍历的特别函数

wooyun.webbaozi.com/bug_detail.…

lstat 函数

wooyun.webbaozi.com/bug_detail.… stream_resolve_include_path函数

wooyun.webbaozi.com/bug_detail.…

wooyun.webbaozi.com/bug_detail.…

wooyun.webbaozi.com/bug_detail.…

绕过GD库图片渲染

jpg_payload.zip

jpg_name.jpg是待GD处理的图片

生成好的图片,在经过如下代码处理后,依然能保留其中的shell:

会话固定

通过get方法来设置session。所以可以通过CSRF:

http://xxxx/index.php?r=admin/index/index&phpsessid=f4cking123

管理员点了我们就能使用此session进后台了。

黑名单绕过

原理:通过黑名单将敏感字符替换为空,然而只按顺序执行一次。可通过故意过滤构造payload.

XXE注入

原理:simplexml_load_file函数的参数过滤不严,导致引入外部实体。产生任意文件读取。

文件上传条件竞争

原理:

后台逻辑:将上传的文件上传到Web目录,然后检查文件的安全性,如果发现文件不安全就马上通过unlink()将其删除。 利用方法:在上传完成和安全检查完成并删除它的间隙,攻击者通过不断地发起访问请求的方法访问了该文件,该文件就会被执行,并且在服务器上生成一个恶意shell。这时候shell已经生成,文件被删除就无所谓了。

资料

github.com/bowu678/php…

github.com/jiangsir404…

read.douban.com/reader/eboo…

github.com/SecWiki/CMS…

github.com/CHYbeta/Cod…

作者:木禾ali0th 链接:https://juejin.cn/post/6844903829725511693 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后更新于

这有帮助吗?