zoukankan      html  css  js  c++  java
  • SQL注入以及防范

    SQL注入原理

    SQL注入漏洞存在的原因,就是拼接SQL参数,所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

    我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。

    例:参数为id

    $sql = 'select * from test where id='.$_GET['id'];

    正常输入2

    则sql为:select * from test where id=2;

    只会查出id为2的记录

    黑客输入2 or 1=1

    则sql为select * from test where id=2 or 1=1;

    这样就会输出test中所有的数据,就完成了一次sql注入

    例:登录输入用户名username和密码password

    $username = $_POST['username'];

    $password = md5($_POST['password']);

    //拼接sql

    $sql="select * from test where username='".$username."' and password='".$password."'";

    正常输入用户名ceshi和密码123456

    则sql为select * from test where username='ceshi' and password='e10adc3949ba59abbe56e057f20f883e';

    只会查出用户名为ceshi和password为123456的记录

    黑客输入用户名ceshi' or 1=1 --和密码123456

    则sql为select * from test where username='ceshi' or 1=1 -- ' and password='e10adc3949ba59abbe56e057f20f883e'

    这样查询的时候就相当于执行的sql为select * from test where username='ceshi' or 1=1,因为'--'注释了后面的sql

    这样又完成sql注入

    sql注入的防范

    1,预编译和参数化(重点)

    使用PDO

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

    $stmt->execute(array(':name' => $name));

    foreach ($stmt as $row) {

        // do something with $row

    }

    使用mysqli

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');

    $stmt->bind_param('s', $name);

    $stmt->execute();

    $result = $stmt->get_result();

    while ($row = $result->fetch_assoc()) {

        // do something with $row

    }

    原理:采用上述方法,会将sql语句:'select * from employees where name = ?'预先编译好,也就是

    sql引擎会预先进行语法分析,产生语法树,生成执行计划也就是说,后面输入的参数,无论输入什么,

    都不会影响该sql语句的语法结构了,即后面的输入的参数即使包含sql关键字(update select and or...)

    也不可能当作sql命令来执行,只会被当作字符转字面值参数,所以sql语句预编译可以防御sql注入

    2,字符串过滤

    在php.ini中开启magic_quotes_gpc on,对输入进行转义

    使用函数对输入进行sql关键字过滤

    sql注入之mysql的联合查询爆破

    mysql的联合查询原理就是对mysql自带的系统表进行查询,因为系统表包含了所有数据库的属性。没有access表猜不出表名列名暴力破解的尴尬。

    上图是我针对mysql的联合查询,画的系统表(系统数据库)的结构

    以查询test数据库为例:

    1.判断列数

    union select 1,2,3,..........  直到页面返回正常为止

    2.判断当前数据库

    union select  database(),2,3,4,5   1的位置将会返回数据库的名字

    数据库名 database()

    数据库版本 version()

    数据库用户 user()

    操作系统 @@version_compile_os

    3.查询表名

    union select  group_concat(table_name),2,3,4,5,6 from information_schema.tables where table_schema='test'

    //group_concat()使多行数据在一列显示

    4.查询列名

    union select group_concat(column_name),2,3,4,5,6 from information_schema.columns where table_name='admin'

    5.查数据 (0x20是空格的意思)

    方法一:

    union select  group_concat(username,0x20,password),2,3,4,5 from test.admin  //将所有数据在一行显示

    方法二

    union select  concat(username,0x20,password),2,3,4,5,6 from one.admin    //因为网页限制只能显示一行数据,所以显示第一行数据 

    union select  concat(username,0x20,password),2,3,4,5,6 from one.admin where username not in ('root')  //把第一行的用户排除掉,第二行自动上来

    union select  concat(username,0x20,password),2,3,4,5,6 from one.admin where username not in ('admin','root') //看第三行数据

    1.以下实例中,输入的用户名必须为字母、数字及下划线的组合,且用户名长度为 8 到 20 个字符之间:

    if (preg_match("/^w{8,20}/",$_GET['username'], $matches)) {

        result=mysql_query("SELECT ∗ FROM users WHERE username = $matches[0]");

    } else { echo "username 输入异常"; }   

    让我们看下在没有过滤特殊字符时,出现的SQL情况:

    // 设定username中插入了我们不需要的SQL语句username中插入了我们不需要的SQL语句username = "Qadir'; DELETE FROM users;"; mysql_query("SELECT * FROM users WHERE username='{username}'");

      以上的注入语句中,我们没有对username}'");  以上的注入语句中,我们没有对username 的变量进行过滤,$name 中插入了我们不需要的SQL语句,将删除 users 表中的所有数据。

      2.在PHP中的 mysql_query() 是不允许执行多个SQL语句的,但是在 SQLite 和 PostgreSQL 是可以同时执行多条SQL语句的,所以我们对这些用户的数据需要进行严格的验证。

      防止SQL注入,我们需要注意以下几个要点:

    1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。

    2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。

    3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

    4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。

    5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装

    6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。

      3.防止SQL注入

      在脚本语言,如Perl和PHP你可以对用户输入的数据进行转义从而来防止SQL注入。

      PHP的MySQL扩展提供了mysql_real_escape_string()函数来转义特殊的输入字符。

    if (get_magic_quotes_gpc()) { name=stripslashes(name=stripslashes(name); } name=mysqlrealescapestring(name=mysqlrealescapestring(name); mysql_query("SELECT * FROM users WHERE name='{$name}'");   4.Like语句中的注入

      like查询时,如果用户输入的值有""和"%",则会出现这种情况:用户本来只是想查询"abcd",查询结果中却有"abcd_"、"abcde"、"abcdf"等等;用户要查询"30%"(注:百分之三十)时也会出现问题。

      在PHP脚本中我们可以使用addcslashes()函数来处理以上情况,如下实例:

    sub=addcslashes(mysqlrealescapestring("//sub=addcslashes(mysqlrealescapestring("//sub == %something_ mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");   addcslashes()函数在指定的字符前添加反斜杠。

      语法格式:

      addcslashes(string,characters)

      参数 描述

      string 必需。规定要检查的字符串。

      characters 可选。规定受 addcslashes() 影响的字符或字符范围。

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/hua-nuo/p/12857672.html
Copyright © 2011-2022 走看看