SQL注入解决方案

文章目录

      • 1. SQL注入原理
      • 2. SQL注入的危害
      • 3. Python防注入方法

1. SQL注入原理

  • sql作为一种解释型语言,在运行时是由一个运行时组件解释语言代码并执行其中包含的指令的语言。基于这种执行方式,产生了一系列叫做代码注入(code injection)的漏洞 。它的数据其实是由程序员编写的代码和用户提交的数据共同组成的。

SQL作为字符串通过API传入给数据库,数据库将查询的结果返回,数据库自身是无法分辨传入的SQL是合法的还是不合法的,它完全信任传入的数据,如果传入的SQL语句被恶意用户控制或者篡改,将导致数据库以当前调用者的身份执行预期之外的命令并且返回结果,导致安全问题。

根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:

  • 不当的类型处理;
  • 不安全的数据库配置;
  • 不合理的查询集处理;
  • 不当的错误处理;
  • 转义字符处理不合适;
  • 多个提交处理不当。

2. SQL注入的危害

  • 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。
  • 网页篡改:通过操作数据库对特定网页进行篡改。
  • 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
  • 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
  • 服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
  • 破坏硬盘数据,瘫痪全系统。
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='table', charset='utf-8')
cursor = conn.cursor()

def query_key(key):
    sql = "SELECT * FROM user where username='{}' and password={}".format(username,password)
    cursor.execute(sql)
    fet = cursor.fetchone()

    if not fet:
        result ="用户账号密码验证错误!"
    else:
        result = "登录成功!"

    print(result)

上面的程序会在用户输入key的时候,将key拼接到SQL语句进行查询。

  1. 测试正常用户行为
username = admin
password = 123456
query_key(key)
# SELECT * FROM user where username='admin' and password='123456'

#结果:登录成功!
  1. 测试注入攻击者行为
username = "' or '1'='1"
password = "' or '1'='1"       
query_key(key)
# sql = SELECT name FROM user where username='' or '1'='1' and password='' or '1'='1'
#结果:登录成功!

如果是某个需要登录账号密码验证的网站,使用sql语句拼接的方法来操作数据库,那么即可用sql注入使之无需账号密码就能登陆成功,那么这样网站的风险性则极大。所有我们需要解决这个问题。

3. Python防注入方法

  1. 使用参数化查询执行原生语句;
cursor.execute('insert into user (name,password) value (?,?)',(name,password))

或者

cursor.execute('insert into user (name,password) value (%s,%s)',(name,password))
  • %s与?都可以作为sql语句的占位符,它们作为占位符的功能是没有区别的,mysql.connector用 %s 作为占位符;pymysql用 ? 作为占位符。这样name,password都是作为参数传入到sql语句中,即可避免sql注入问题。
  1. 使用带有ORM的web框架等或使用ORM组件sqlalchemy,peewee;
  • ,数据库中的表被映射为Python的类,类的对象代表数据表中的一行记录,所有的DB操作都通过对象方法调用来实现,这些调用在底层被自动转换成SQL语句,在转换过程中,通常会采用parameter bind的方式保证生成的parameterized SQL不存在被注入的风险。
  1. 使用正则和字符串方法检测注入风险,比如单引号和注释符号等(不推荐)。
  • 例如用replace()方法,过滤掉“or”、“and”、“/”、“*”、“#”、“s”等字符,则使之sql语句不能注入。

你可能感兴趣的:(学习笔记)