SQL注入

21 篇文章 1 订阅

一、sql注入原理

SQL注入就是把SQL命令插入到Web表单然后提交到所在页面请求(查询字符串),从而达到欺骗服务器执行恶意的SQL命令
它是利用现在已有的应用程序,将SQL语句插入到数据库中执行,执行一些并非按照设计者意图的SQL语句。
产生原因
    是程序没有细致过滤用户输入的数据,从而导致非法数据进入系统。
相关技术原理
    SQL注入可以分为 平台层注入代码注入。前者是由不安全的数据库配置或平台漏洞所致。后者是程序员对输入未进行细致过滤产生。
    这种攻击的要诀在于将SQL的查询/行为命令通过‘嵌入’的方式放入合法的HTTP提交请求中从而达到攻击者的某种意图。现在很多的动态网页都会从该网页使用者的请求中得到某些参数,然后动态的构成SQL请求发给数据库的。
    举个例子,当有某个用户需要通过网页上的用户登陆(用户身份验证)时,动态网页会将该用户提交上来的用户名与密码加进SQL询问请求发给数据库,用于确认该用户提交的身份验证信息是否有效。在SQL注入攻击的角度看来,这样可以使我们在发送SQL请求时通过修改用户名与/或密码值的‘领域’区来达到攻击的目的。
 
注入的手段无非是在拼接字符串的时候加入一些SQL关键字。要防止SQL注入,就要对传入的字符串进行检查,对包含SQL关键字的输入都视为非法

二、SQL注入点判断

传入SQL语句可控参数分为两类:
    1. 数字类型,参数不用被引号括起来,如 ?id=1
    2. 字符类型,参数要被引号扩起来,如 ?name="phone"
 
判断某个链接是否存在SQL注入,可以通过对其传入的可控参数进行简单的构造,通过服务端返回的内容来判断有无注入。
 
字符类型:
构造测试                      预期结果                                          变种
a'                            //触发错误,返回数据库错误                             
a ' or ' 1 '=' 1              //永真条件,返回所有记录                     a ') or (' 1'=1  
a ' or ' 1 '=' 2              //空条件,返回原来相同结果                  a ') or (' 1'=2
a ' and ' 1 '=' 2           //永假条件,不返回记录                        a ') and (' 1 '=' 2
  
数字类型:
构造测试                     预期结果                                           变种
'                              //触发错误,返回数据库错误                 
1 + 1                         //返回原来相同的结果                              3 - 1
1 + 0                         //返回原来相同的结果                    
1 or 1 = 1                 //永真条件,返回所有记录                       1 ) or ( 1 = 1
1 or 1 = 2                //空条件,返回原来相同的结果                1 ) or ( 1 = 2
1 and 1 = 2               //永假条件,不返回记录                          1 ) and ( 1 = 2

三、危害

SQL注入的 危害不仅体现在数据库层面上,还有可能危及承载数据库的操作系统 ;如果SQL注入被用来挂马,还可能用来传播恶意软件等,这些危害包括但不局限于:
1.数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。作为数据的存储中心,数据库里往往保存着各类的隐私信息,SQL注入攻击能导致这些隐私信息透明于攻击者。
2.网页篡改:通过操作数据库对特定网页进行篡改。
3.网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
4.数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
5.服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
6.破坏硬盘数据,瘫痪全系统。
一些类型的数据库系统能够让SQL指令操作文件系统,这使得SQL注入的危害被进一步放大。

四、解决方案

解决SQL注入问题的关键是对所有可能来自用户输入的数据进行严格的检查、对数据库配置使用最小权限原则
经常使用的方案有:
1.所有的查询语句都使用数据库提供的 参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入攻击。
2. 对进入数据库的特殊字符('"\<>&*;等)进行转义处理,或编码转换
3.要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等
3.确认 每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型。
4.数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。
5.网站每个数据层的 编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。
6.严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
7. 避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断
8.在网站发布之前建议使用一些专业的 SQL注入检测工具进行检测,及时修补这些SQL注入漏洞。
9.限制 Web 应用程序所用的数据库访问帐号权限。一般来说,应用程序没有必要以 dbo 或者 sa 的身份访问数据库。需要严格遵循权限最小化原则,根据业务需要建立数据库登录用户,设置足够健壮的密码,只分配必要的权限及可访问数据库。

4.1、参数化防止SQL注入

sql注入中最常见的就是字符串拼接,研发人员对字符串拼接应该引起重视
错误用法1:
    sql = "select id, name from test where id=%d and name='%s'"  % (id, name)
    cursor.execute(sql)
错误用法2:
    sql = "select id, name from test where id="+ str(id) +" and name='"+ name +"'"
    cursor.execute(sql)
正确用法1:(Mysql数据库)
    sql = "select id, name from test where id=%s and name=%s"
    cursor.execute(sql, (id, name)   python会自动过滤args中的特殊字符,制止SQL注入的产生
     execute()函数本身有接受sql语句参数位的,可以通过python自身的函数处理sql注入问题。
    如果只有一个参数,则写成:cursor.execute(sql,(id,))
正确用法2:
    name = MySQLdb.escape_string(name)
    sql = "select id, name from test where id=%s and name=%s" %(id, name)
    cursor.execute(sql)
    python模块MySQLdb自带针对mysql的字符转义函数escape_string,可以对字符串转义。
防止like的SQL注入:
Mysql数据库:
    sql = " and indexNum like concat('%',?,'%') "
Oracle:
    sql = " like '%' || ? || '%' "
SQL Server:
    sql = " like '%' + ? + '%' "
    WHERE Name LIKE CONCAT('%',@name,'%')
sqlite3:
    rulename = rule_name + "%"
    sql = ''' UPDATE {} SET has_alert=1 WHERE device_id=? AND rule LIKE ?;'''
    cursor.execute(sql.format(table),(did, rulename))
模糊查询防sql注入 :
def sub_type_total(self, taskid, type, subtype, aggregate_name, keyword):
    if keyword:
        sql = 'SELECT count(1)  FROM tmp_tbl where type=? and subtype=? and aggregate_name=? and rawlog like ?;'
    else:
        sql = 'SELECT count(1)  FROM tmp_tbl where type=? and subtype=? and aggregate_name=?;'
    with sqlite3.connect(self.getDB(taskid)) as conn:
        cursor = conn.cursor()
        cursor.execute('PRAGMA case_sensitive_like = false;')  # 忽略内置LIKE 操作符字母的大小写
        if keyword:
            cursor.execute(sql, (type, subtype, aggregate_name, "%" + keyword + "%"))
        else:
            cursor.execute(sql, (type, subtype, aggregate_name))
        return cursor.fetchone()[0]

4.2、过滤特殊字符

过滤非法字符:在开发过程中,要对前端传过来的数据进行验证,防止sql注入攻击,其中的一个方案就是过滤用户传过来的非法的字符

Python sql注入 过滤字符串的非法字符 - 淋哥 - 博客园 (cnblogs.com)

def sql_filter(sql, max_length=20):
    dirty_stuff = ["\"", "\\", "/", "*", "'", "=", "-", "#", ";", "<", ">", "+", "%", "$", "(", ")", "%", "@","!", "|",]
    for stuff in dirty_stuff:
        sql = sql.replace(stuff, "")
    return sql[:max_length]

username = "1234567890!@#!@#!@#$%======$%"
username = sql_filter(username)  # SQL注入
print(username)
# 输出结果是:1234567890

五、参考

(python)PyMySQL模块的使用与SQL注入_miaoqinian的博客-CSDN博客

06 SQL 注入:小心数据库被拖走(上)_哔哩哔哩_bilibili

07 SQL 注入:小心数据库被拖走(下)_哔哩哔哩_bilibili

08 SQL 注入:漏洞的检测与防御_哔哩哔哩_bilibili

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值