首页 > 编程技术 > php

php中禁止危险php函数的例子

发布时间:2016-11-25 15:21

在php中我们如果想让系统函数不被执行可以在php.ini中加上Disable_functions后面跟函数名就可以了。

禁用方法如下:
 
打开/etc/php.ini文件,
 
搜索定位到这行 

1.disable_functions = 

添加需禁用的函数名,比如: 

 代码如下 复制代码

phpinfo,eval,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen

相反的如果要运行php运行某个函数删除相应的函数即可。但文章有个“eval”函数,这个不是系统函数所以无法禁止不信大家可试下。


以上只是列了部分不叫常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,
就能够抵制大部分的phpshell了。

但是我后来看一文章告诉我们这样做不是万能的在linux中可以直接突破Disable_functions执行Linux命令

 代码如下 复制代码

<?php
//PHP4调用方法
dl('../../../../../home/apache/htdocs/php4.so');
biguanspider('uname -a');//调用函数
?> www.111cn.net

<?php
//PHP5调用方法
dl('../../../../../home/apache/htdocs/php5.so');
spiderbiguan('uname -a');//调用函数
?>

很多管理员在封杀PHP危险函数的时候一般都是这样的:disable_functions = proc_open,exec,passthru,shell_exec,system,popen
但是如果编译PHP时带–enable-pcntl参数就危险了,可以用pcntl_exec函数执行指定程序,也可以反弹一个SHELL,在PHPINFO里查看编译参数。
描述:pcntl_exec — 在当前进程空间执行指定程序,具体的做法我就不写了,所以linux安全还是得从本身设置不要想到php这样配置就KO了。

在一些开发中,我们使用curl等进行通信,如果你的一些隐私数据不进行加密,就可能造成信息泄露,带来不必要的麻烦。我们提供一个带密钥的加密解密函数,只要你的密钥不泄露,就可能很好的保护你的传输。

代码

 代码如下 复制代码

function encrypt($data, $key)
{
    $key    =   md5($key);
    $x      =   0;
    $len    =   strlen($data);
    $l      =   strlen($key);
    for ($i = 0; $i < $len; $i++)
    {
        if ($x == $l) 
        {
            $x = 0;
        }
        $char .= $key{$x};
        $x++;
    }
    for ($i = 0; $i < $len; $i++)
    {
        $str .= chr(ord($data{$i}) + (ord($char{$i})) % 256);
    }
    return base64_encode($str);
}

function decrypt($data, $key)
{
    $key = md5($key);
    $x = 0;
    $data = base64_decode($data);
    $len = strlen($data);
    $l = strlen($key);
    for ($i = 0; $i < $len; $i++)
    {
        if ($x == $l) 
        {
            $x = 0;
        }
        $char .= substr($key, $x, 1);
        $x++;
    }
    for ($i = 0; $i < $len; $i++)
    {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1)))
        {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }
        else
        {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return $str;
}

上面的两个函数,一个是加密函数,一个是解密函数。encrypt($data, $key) 为加密函数,其中$data是要加密的内容,$key是你的密钥。decrypt($data, $key) 是解密函数,其中$data是要解密的字符串,$key是密钥

.inc文件在很久以前都是配置文件了,这样如果apache没有配置好很容易配置文件给爆露出来,下面我就来介绍具体的设置办法。

发现现在的项目是把所有的包含文件放在主目录下面,如下图:

网站目录为public,除了入口文件,所有的源码及配置文件,都在网站目录外。
刚开始没有意识到为什么这么做,后来想了想,真的很有必要,否则很容易就吧源代码和一些重要信息暴露在外了:
(1)比如说.inc扩展名的配置文件,和其它文本类型的文件,直接就可以在浏览器上访问了,很多能这里面就有数据库的账号啊
(2)如果你的apache还没有对PHP支持的时候,php文件也会默认作为文本类型在浏览器上访问【升级apache,或修改配置的时候可能出现】
如果将你的程序包含在网站目录之外,就避免了保留私密信息的危险。当然,你可以在apache上配置如禁止在浏览器上访问.inc文件:

 代码如下 复制代码

<Files ~ ".inc$">
    Order allow,deny
    Deny from all
</Files>

类似的很多细节很容易被运维人员忘记

 

在生成表单的时候,为防止表单重复提交。在form表单中添加一个隐藏的input标签来存放令牌,等到提交的时候,和表单一起提交。提交以后和生成的session值作比较,通过这种方式来达到防止重复提交的目的。简要代码如下,

例子,session方法

 代码如下 复制代码

<?php
if($_POST){
    if($_SESSION["token"]!=$_POST["token"]){
        die("非法提交!");
    }else{
        echo "安全提交!";
    }
}
$_SESSION["token"]=md5(rand(1,999));//没生成一次表单,修改一次值,不要在post处理前修改它,不然无法比对 www.111cn.net
?>
<form action="1.php" method="post">
<input type="hidden" value="<?php echo $_SESSION["token"]?>" name="token">
<input type="submit" value="提交" />
</form>

例子,cookie+md5方法

 代码如下 复制代码

<?php

$value = $_COOKIE[“value”]; //读取上一次设置的Cookie值

if(count($_POST)) {

$long = “”;

while(list($key,$value)=each($_POST))$long.=$value;

$hash = md5($long);

setcookie(“value”,$hash,time()+60*60); //重新设置cookie

}

if($value!=$hash) {

// 如果两次的MD5值不一样就对数据进行进一步操作

} else {

//如果两次MD5的值相同,告知用户提交失败 ,为重复提交表单

}

?>

 

is_numberic函数在php用来判断数字,很多初学者喜欢利用is_numberic函数来判断外部提交的数据是否为安全的数字了,但须不知道is_numberic存在一个bug哦,下面我们一起来看看具体测试吧。

0×00 简介

国内一部分CMS程序里面有用到过is_numberic函数,我们先看看这个函数的结构

bool is_numeric ( mixed $var )


is_numeric会判断一个字符串是否是数字类型,这很重要. 比如-1, 1.5 这类的数字在is_numberic中是返回true, 因为是一个数字类型

0×01 函数是否安全

接下来我们来看个例子,说明这个函数是否安全。

 代码如下 复制代码

$s = is_numeric($_GET['s'])?$_GET['s']:0;
$sql="insert into test(type)values($s);";  //是 values($s) 不是values('$s')
mysql_query($sql);

上面这个片段程序是判断参数s是否为数字,是则返回数字,不是则返回0,然后带入数据库查询。(这样就构造不了sql语句)
我们把‘1 or 1’ 转换为16进制 0x31206f722031 为s参数的值

程序运行后,我们查询数据库看看,如下图:

如果再重新查询这个表的字段出来,不做过滤带入另一个SQL语句,将会造成2次注入.

0×02 总结

尽量不要使用这函数,如果要使用这个函数,建议使用规范的sql语句,条件加入单引号,这样16进制0x31206f722031就会在数据库里显示出来。而不会出现1 or 1。

如果我们要判断是否是数字我们可以通过 intval()函数来代替is_numeric函数这样上面的方法全部无效了,下面看个例子

 代码如下 复制代码

$id = intval($_GET['id']);

echo intval(42); // 42
echo intval(4.2); // 4
echo intval('42'); // 42
echo intval('+42'); // 42
echo intval('-42'); // -42
echo intval(042); // 34
echo intval('042'); // 42
echo intval(1e10); // 1410065408
echo intval('1e10'); // 1
echo intval(0x1A); // 26
echo intval(42000000); // 42000000
echo intval(420000000000000000000); // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8); // 42
echo intval('42', 8); // 34
?>

intval最常用的是正在程序中功滤入进数据库的变质,将其转换为整型,避免SQL注进攻打的发生

标签:[!--infotagslink--]

您可能感兴趣的文章: