09: 老生常谈的注入攻击

安全439 字

■ SQL注入

场景:SQL注入发生在任何有用户可控输入并且会和数据库进行交互操作的功能处,比如:用户登录验证、查询、搜索、更新信息等。

说明:通过预编译实现参数化查询,将用户的输入数据和后台的SQL代码分离,正确的使用预编译来实现参数化查询,可以有效地防止SQL注入。

PHP 示例:使用PDO处理用户输入

<?php
    $host='localhost';
    $dbName='xxxxx';
    $user='xxxxxxx';
    $pass='xxxxxxx';
    $dsn="mysql:host=$host; dbname=$dbName";
    
    try {
        $pdo = new PDO($dsn, $user, $pass);
        if (version_compare(PHP_VERSION, '5.3.6', '<') && !defined('PDO::MYSQL_ATTR_INIT_COMMAND')) {
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        }
    } catch (PDOException $e) {
        echo $e->getMessage();
        exit();
    }

    $pdo->exec("SET NAMES 'utf8'");
    $smt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    $smt->execute(array(':name' => $_GET['name']));
    // $smt->bindParam(':name', $_GET['name']); 
    foreach ($smt->fetchAll() as $row) {
        // do something with $row
    }
?>      

PHP 示例:使用Mysqli处理用户输入

<?php
    $host='localhost';
    $dbName='xxxxx';
    $user='xxxxxxx';
    $pass='xxxxxxx';
    
    try {
        $con = mysqli_connect($host, $user, $pass, $dbName)
        if (!&con) {
            echo mysqli_connect_error();
            exit();
        }
    } catch (PDOException $e) {
        echo $e->getMessage();
        exit();
    }
    $con->set_charset("utf8");
    $smt = $con->prepare("SELECT * FROM employees WHERE name = ?");
    $smt->bindParam("s", $_GET['name']);
    $smt->execute();
    $ret = $smt->get_result();
    while ($row = $ret->fetch_assoc()) {
        // do something with $row
    }
    mysqli_close($con);
?>  

■ XSS注入

场景:所有存在用户可控输入,而且会将用户输入输出到客户端的场景,比如:用户论坛发帖、用户评论、用户昵称、用户个人简介、用户提交反馈管理员后台查看、课程命名、课程信息介绍等等。

说明:对输入的数据进行过滤和转义,包含但不限于<>”’%()&+\’\”等危险特殊字符。

PHP示例:先对用户输入的内容输出进行html实体转码。

public function SafeFilter($arr){
    $ra=Array('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/','/script/','/javascript/','/vbscript/','/expression/','/applet/','/meta/','/xml/','/blink/','/link/','/style/','/embed/','/object/','/frame/','/layer/','/title/','/bgsound/','/base/','/onload/','/onunload/','/onchange/','/onsubmit/','/onreset/','/onselect/','/onblur/','/onfocus/','/onabort/','/onkeydown/','/onkeypress/','/onkeyup/','/onclick/','/ondblclick/','/onmousedown/','/onmousemove/','/onmouseout/','/onmouseover/','/onmouseup/','/onunload/');
    if (is_array($arr)){
        foreach ($arr as $key => $value){
            if (!is_array($value)){
                //不对magic_quotes_gpc转义过的字符使用addslashes(),避免双重转义。
                if (!get_magic_quotes_gpc()){
                    $value = addslashes($value);  //给单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)加上反斜线转义
                }
                $value = preg_replace($ra,'',$value); //删除非打印字符,粗暴式过滤xss可疑字符串

                $arr[$key] = htmlentities(strip_tags($value)); //去除 HTML 和 PHP 标记并转换为 HTML 实体
            }else{
                SafeFilter($arr[$key]);
            }
        }
    }
}       

■ XML注入

场景:XML被设计用来传输和存储数据,所以XML注入发生在使用XML传输或存储数据,而对用户输入没有严格验证处理的场景。

说明:在XML文档内部或外部引用数据时,过滤用户提交的参数,如<、>、’、“、&等特殊字符。禁止加载外部实体,禁止报错。

PHP示例:假设一个在线商城可以由用户指定商品数量,来完成支付,会生成如下的XML:

<?php
    if (isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || 
       !in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1',))) {
        header('HTTP/1.0 403 Forbidden');
        exit('You are not allowed to access this file.');
    }
?>          
maksim
Maksim(一笑,吡罗),PHPer,Goper
OωO
开启隐私评论,您的评论仅作者和评论双方可见