zoukankan      html  css  js  c++  java
  • php 防注入

    php网站如何防止sql注入?

    网站的运行安全肯定是每个站长必须考虑的问题,大家知道,大多数黑客攻击网站都是采用sql注入,这就是我们常说的为什么最原始的静态的网站反而是最安全的。 今天我们讲讲PHP注入的安全规范,防止自己的网站被sql注入。

    如今主流的网站开发语言还是php,那我们就从php网站如何防止sql注入开始说起:

    Php注入的安全防范通过上面的过程,我们可以了解到php注入的原理和手法,当然我们也同样可以制定出相应该的防范方法:
    首先是对服务器的安全设置,这里主要是php+mysql的安全设置和linux主机的安全设置。对php+mysql注射的防范,首先将magic_quotes_gpc设置为On,display_errors设置为Off,如果id型,我们利用intval()将其转换成整数类型,如代码:
    $id=intval($id);
    mysql_query=”select *from example where articieid=’$id’”;或者这样写:mysql_query(”SELECT * FROM article WHERE articleid=”.intval($id).”")

    如果是字符型就用addslashes()过滤一下,然后再过滤”%”和”_”如:
    $search=addslashes($search);
    $search=str_replace(“_”,”\_”,$search);
    $search=str_replace(“%”,”\%”,$search);
    当然也可以加php通用防注入代码:
    /*************************
    PHP通用防注入安全代码
    说明:
    判断传递的变量中是否含有非法字符
    如$_POST、$_GET
    功能:
    防注入
    **************************/
    //要过滤的非法字符
    $ArrFiltrate=array(”‘”,”;”,”union”);
    //出错后要跳转的url,不填则默认前一页
    $StrGoUrl=”";
    //是否存在数组中的值
    function FunStringExist($StrFiltrate,$ArrFiltrate){
    foreach ($ArrFiltrate as $key=>$value){
    if (eregi($value,$StrFiltrate)){
    return true;
    }
    }
    return false;
    }
    //合并$_POST 和 $_GET
    if(function_exists(array_merge)){
    $ArrPostAndGet=array_merge($HTTP_POST_VARS,$HTTP_GET_VARS);
    }else{
    foreach($HTTP_POST_VARS as $key=>$value){
    $ArrPostAndGet[]=$value;
    }
    foreach($HTTP_GET_VARS as $key=>$value){
    $ArrPostAndGet[]=$value;
    }
    }
    //验证开始
    foreach($ArrPostAndGet as $key=>$value){
    if (FunStringExist($value,$ArrFiltrate)){
    echo “alert(/”Neeao提示,非法字符/”);”;
    if (empty($StrGoUrl)){
    echo “history.go(-1);”;
    }else{
    echo “window.location=/”".$StrGoUrl.”/”;”;
    }
    exit;
    }
    }
    ?>
    /*************************
    保存为checkpostandget.php
    然后在每个php文件前加include(“checkpostandget.php“);即可
    **************************/

    另外将管理员用户名和密码都采取md5加密,这样就能有效地防止了php的注入。
    还有服务器和mysql也要加强一些安全防范。
    对于linux服务器的安全设置:
    加密口令,使用“/usr/sbin/authconfig”工具打开密码的shadow功能,对password进行加密。
    禁止访问重要文件,进入linux命令界面,在提示符下输入:
    #chmod 600 /etc/inetd.conf //改变文件属性为600
    #chattr +I   /etc/inetd.conf     //保证文件属主为root
    #chattr –I   /etc/inetd.conf     // 对该文件的改变做限制
    禁止任何用户通过su命令改变为root用户
    在su配置文件即/etc/pam.d/目录下的开头添加下面两行:
    Auth   sufficient   /lib/security/pam_rootok.so debug
    Auth   required   /lib/security/pam_whell.so group=wheel
    删除所有的特殊帐户
    #userdel   lp等等 删除用户
    #groupdel lp等等 删除组
    禁止不使用的suid/sgid程序
    #find / -type f \(-perm -04000   - o –perm -02000 \) \-execls –lg {} \;

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    一直搞.net ,最近研究PHP,也涉及到防注入的安全措施,和.net的大同小异,从网上摘回一篇,作为备注,以供自己需要时查阅。

    介绍两种方法吧,首先请把以下代码保存为safe.php放在网站根目录下,然后在每个php文件前加include(“/safe.php“);即可 :

    php防注入代码方法一:

    <?php
    //要过滤的非法字符
    $ArrFiltrate=array(”‘”,”;”,”union”);
    //出错后要跳转的url,不填则默认前一页
    $StrGoUrl=””;
    //是否存在数组中的值
    function FunStringExist($StrFiltrate,$ArrFiltrate){
    foreach ($ArrFiltrate as $key=>$value){
    if (eregi($value,$StrFiltrate)){
    return true;
    }
    }
    return false;
    }
    //合并$_POST 和 $_GET
    if(function_exists(array_merge)){
    $ArrPostAndGet=array_merge($HTTP_POST_VARS,$HTTP_GET_VARS);
    }else{
    foreach($HTTP_POST_VARS as $key=>$value){
    $ArrPostAndGet[]=$value;
    }
    foreach($HTTP_GET_VARS as $key=>$value){
    $ArrPostAndGet[]=$value;
    }
    }
    //验证开始
    foreach($ArrPostAndGet as $key=>$value){
    if (FunStringExist($value,$ArrFiltrate)){
    echo “<script language=\”javascript\”>alert(\”非法字符\”);</script>”;
    if (emptyempty($StrGoUrl)){
    echo “<script language=\”javascript\”>history.go(-1);</script>”;
    }else{
    echo “<script language=\”javascript\”>window.location=\””.$StrGoUrl.”\”;</script>”;
    }
    exit;
    }
    }
    ?>

    php防注入代码方法二:

    /* 过滤所有GET过来变量 */
    foreach ($_GET as $get_key=>$get_var)
    {
    if (is_numeric($get_var)) {
    $get[strtolower($get_key)] = get_int($get_var);
    } else {
    $get[strtolower($get_key)] = get_str($get_var);
    }
    }
    /* 过滤所有POST过来的变量 */
    foreach ($_POST as $post_key=>$post_var)
    {
    if (is_numeric($post_var)) {
    $post[strtolower($post_key)] = get_int($post_var);
    } else {
    $post[strtolower($post_key)] = get_str($post_var);
    }
    }
    /* 过滤函数 */
    //整型过滤函数
    function get_int($number)
    {
    return intval($number);
    }
    //字符串型过滤函数
    function get_str($string)
    {
    if (!get_magic_quotes_gpc()) {
    return addslashes($string);
    }
    return $string;
    }

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    在现在各种黑客横行的时候,如何实现自己php代码安全,保证程序和服务器的安全是一个很重要的问题,我随便看了下关于php安全的资料,并不是很多,至少比asp少多了,呵呵,于是就想写点东西,来防止这些可能出现的情况。这里没有太深的技术含量,我只是比较简单的谈了谈。(以下操作如无具体说明,都是基于PHP+MySQL+Apache的情况)

        先来说说安全问题,我们首先看一下两篇文章:
    http://www.xfocus.net/articles/200107/227.html    
    http://www.xfocus.net/articles/200107/228.html

        上面文章是安全焦点上的关于PHP安全的文章,基本上比较全面的介绍了关于PHP的一些安全问题。

        在PHP编码的时候,如果考虑到一些比较基本的安全问题,首先一点:
    1. 初始化你的变量

        为什么这么说呢?我们看下面的代码
    if ($admin)
    {
        echo '登陆成功!';
        include('admin.php');
    }
    else
    {
        echo '你不是管理员,无法进行管理!';
    }

        好,我们看上面的代码好像是能正常运行,没有问题,那么加入我提交一个非法的参数过去呢,那么效果会如何呢?比如我们的这个页是 http://www.traget.com/login.php,那么我们提交:http://www.target.com/login.php?admin=1,呵呵,你想一些,我们是不是直接就是管理员了,直接进行管理。
        当然,可能我们不会犯这么简单错的错误,那么一些很隐秘的错误也可能导致这个问题,比如最近暴出来的phpwind 1.3.6论坛有个漏洞,导致能够直接拿到管理员权限,就是因为有个$skin变量没有初始化,导致了后面一系列问题。

        那么我们如何避免上面的问题呢?首先,从php.ini入手,把php.ini里面的register_global = off,就是不是所有的注册变量为全局,那么就能避免了。但是,我们不是服务器管理员,只能从代码上改进了,那么我们如何改进上面的代码呢?我们改写如下:
    $admin = 0;      // 初始化变量
    if ($_POST['admin_user'] && $_POST['admin_pass'])
    {
        // 判断提交的管理员用户名和密码是不是对的相应的处理代码
        // ...
        $admin = 1;
    }
    else
    {
        $admin = 0;
    }

    if ($admin)
    {
        echo '登陆成功!';
        include('admin.php');
    }
    else
    {
        echo '你不是管理员,无法进行管理!';
    }

        那么这时候你再提交 http://www.target.com/login.php?admin=1 就不好使了,因为我们在一开始就把变量初始化为 $admin = 0 了,那么你就无法通过这个漏洞获取管理员权限。


    2. 防止SQL Injection (sql注射)

        SQL 注射应该是目前程序危害最大的了,包括最早从asp到php,基本上都是国内这两年流行的技术,基本原理就是通过对提交变量的不过滤形成注入点然后使恶意用户能够提交一些sql查询语句,导致重要数据被窃取、数据丢失或者损坏,或者被入侵到后台管理。
    基本原理我就不说了,我们看看下面两篇文章就很明白了:
    http://www.4ngel.net/article/36.htm
    http://www.4ngel.net/article/30.htm

        那么我们既然了解了基本的注射入侵的方式,那么我们如何去防范呢?这个就应该我们从代码去入手了。

        我们知道Web上提交数据有两种方式,一种是get、一种是post,那么很多常见的sql注射就是从get方式入手的,而且注射的语句里面一定是包含一些sql语句的,因为没有sql语句,那么如何进行,sql语句有四大句:
        select 、update、delete、insert,那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢?
        于是我们使用正则就构建如下函数:

    /*
    函数名称:inject_check()
    函数作用:检测提交的值是不是含有SQL注射的字符,防止注射,保护服务器安全
    参        数:$sql_str: 提交的变量
    返 回 值:返回检测结果,ture or false
    函数作者:heiyeluren
    */
    function inject_check($sql_str)
    {
         return eregi('select|insert|update|delete|'|/*|*|../|./|union|into|load_file|outfile', $sql_str);    // 进行过滤
     }

        我们函数里把 select,insert,update,delete, union, into, load_file, outfile /*, ./ , ../ , ' 等等危险的参数字符串全部过滤掉,那么就能够控制提交的参数了,程序可以这么构建:

    <?php
    if (inject_check($_GET['id']))
    {
         exit('你提交的数据非法,请检查后重新提交!');
    }
    else
    {
        $id = $_GET['id'];
        echo '提交的数据合法,请继续!';
    }
    ?>
        假设我们提交URL为:http://www.target.com/a.php?id=1,那么就会提示:
        "提交的数据合法,请继续!"
        如果我们提交 http://www.target.com/a.php?id=1%27 select * from tb_name
        就会出现提示:"你提交的数据非法,请检查后重新提交!"

        那么就达到了我们的要求。

        但是,问题还没有解决,假如我们提交的是 http://www.target.com/a.php?id=1asdfasdfasdf 呢,我们这个是符合上面的规则的,但是呢,它是不符合要求的,于是我们为了可能其他的情况,我们再构建一个函数来进行检查:

    /*
    函数名称:verify_id()
    函数作用:校验提交的ID类值是否合法
    参        数:$id: 提交的ID值
    返 回 值:返回处理后的ID
    函数作者:heiyeluren
    */
    function verify_id($id=null)
    {
       if (!$id) { exit('没有提交参数!'); }    // 是否为空判断
       elseif (inject_check($id)) { exit('提交的参数非法!'); }    // 注射判断
       elseif (!is_numeric($id)) { exit('提交的参数非法!'); }    // 数字判断
       $id = intval($id);    // 整型化
     
       return  $id;
    }

        呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成了下面的:

    <?php
    if (inject_check($_GET['id']))
    {
         exit('你提交的数据非法,请检查后重新提交!');
    }
    else
    {
        $id = verify_id($_GET['id']);    // 这里引用了我们的过滤函数,对$id进行过滤
        echo '提交的数据合法,请继续!';
    }
    ?>

        好,问题到这里似乎都解决了,但是我们有没有考虑过post提交的数据,大批量的数据呢?
        比如一些字符可能会对数据库造成危害,比如 ' _ ', ' % ',这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的magic_quotes_gpc = off 的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加' '的,那么我们要控制这些问题,于是构建如下函数:

    /*
    函数名称:str_check()
    函数作用:对提交的字符串进行过滤
    参    数:$var: 要处理的字符串
    返 回 值:返回过滤后的字符串
    函数作者:heiyeluren
    */
    function str_check( $str )
    {
       if (!get_magic_quotes_gpc())    // 判断magic_quotes_gpc是否打开
       {
          $str = addslashes($str);    // 进行过滤
     }
         $str = str_replace("_", "\_", $str);    // 把 '_'过滤掉
         $str = str_replace("%", "\%", $str);    // 把' % '过滤掉
      
       return $str;
    }

    OK,我们又一次的避免了服务器被沦陷的危险。

        最后,再考虑提交一些大批量数据的情况,比如发贴,或者写文章、新闻,我们需要一些函数来帮我们过滤和进行转换,再上面函数的基础上,我们构建如下函数:

    /*
    函数名称:post_check()
    函数作用:对提交的编辑内容进行处理
    参    数:$post: 要提交的内容
    返 回 值:$post: 返回过滤后的内容
    函数作者:heiyeluren
    */
    function post_check($post)
    {
       if (!get_magic_quotes_gpc())    // 判断magic_quotes_gpc是否为打开
       {
          $post = addslashes($post);    // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤
       }
       $post = str_replace("_", "\_", $post);    // 把 '_'过滤掉
       $post = str_replace("%", "\%", $post);    // 把' % '过滤掉
       $post = nl2br($post);    // 回车转换
       $post= htmlspecialchars($post);    // html标记转换
     
       return $post;
    }

        呵呵,基本到这里,我们把一些情况都说了一遍,其实我觉得自己讲的东西还很少,至少我才只讲了两方面,再整个安全中是很少的内容了,考虑下一次讲更多,包括php安全配置,apache安全等等,让我们的安全正的是一个整体,作到最安全。

        最后在告诉你上面表达的:1. 初始化你的变量  2. 一定记得要过滤你的变量

    +++++++++++++++++++++++++++++++++++++++++++++

    对POST或GET数据过滤

    $_POST = sql_injection($_POST);
    $_GET = sql_injection($_GET);

    function sql_injection($content)
    {
    if (!get_magic_quotes_gpc()) {
    if (is_array($content)) {
    foreach ($content as $key=>$value) {
    $content[$key= addslashes($value);
    }
    else {
    addslashes($content);
    }
    }
    return $content;
    }

    /* 
    函数名称:inject_check() 
    函数作用:检测提交的值是不是含有SQL注射的字符,防止注射,保护服务器安全 
    参  数:$sql_str: 提交的变量 
    返 回 值:返回检测结果,ture or false 
    */ 
    function inject_check($sql_str) { 
    return eregi('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile', $sql_str); // 进行过滤 


    /* 
    函数名称:verify_id() 
    函数作用:校验提交的ID类值是否合法 
    参  数:$id: 提交的ID值 
    返 回 值:返回处理后的ID 
    */ 
    function verify_id($id=null) { 
    if (!$id) { exit(
    '没有提交参数!'); } // 是否为空判断 
    elseif (inject_check($id)) { exit(
    '提交的参数非法!'); } // 注射判断 
    elseif (!is_numeric($id)) { exit(
    '提交的参数非法!'); } // 数字判断 
    $id = intval($id); // 整型化 

    return $id; 


    /* 
    函数名称:str_check() 
    函数作用:对提交的字符串进行过滤 
    参  数:$var: 要处理的字符串 
    返 回 值:返回过滤后的字符串 
    */ 
    function str_check( $str ) { 
    if (!get_magic_quotes_gpc()) { // 判断magic_quotes_gpc是否打开 
    $str = addslashes($str); // 进行过滤 

    $str = str_replace("_", "\_", $str); // 把 
    '_'过滤掉 
    $str = str_replace("%", "\%", $str); // 把 
    '%'过滤掉 

    return $str; 


    /* 
    函数名称:post_check() 
    函数作用:对提交的编辑内容进行处理 
    参  数:$post: 要提交的内容 
    返 回 值:$post: 返回过滤后的内容 
    */ 
    function post_check($post) { 
    if (!get_magic_quotes_gpc()) { // 判断magic_quotes_gpc是否为打开 
    $post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤 

    $post = str_replace("_", "\_", $post); // 把 
    '_'过滤掉 
    $post = str_replace("%", "\%", $post); // 把 
    '%'过滤掉 
    $post = nl2br($post); // 回车转换 
    $post = htmlspecialchars($post); // html标记转换 

    return $post; 
    }

  • 相关阅读:
    python_tkinter弹出对话框2
    python_tkinter弹出对话框1
    python生成图片二维码(利用pillow)
    nginx配置ssl证书流程及常见问题
    Django app安装,配置mysql,时区,模板,静态文件,媒体,admin
    使用Git Flow规范!
    python快速生成验证码
    json&pickle模块
    sys模块
    常用模块
  • 原文地址:https://www.cnblogs.com/buffer/p/1984355.html
Copyright © 2011-2022 走看看