1. Project Background

本项目主要是通过SQL注入案例来让大家了解如何防范SQL攻击,希望对大家有所帮助

picture


2. Implementation process

》》创建数据表》》插入数据》》SQL注入》》分析原因
mysql> use gzh;Database changedmysql> create table t_user(    -> username varchar(120),    -> password varchar(200))    -> engine=innodb default charset=utf8;Query OK, 0 rows affected, 1 warning (0.13 sec)

mysql> insert into t_user(username,password) values('Tom','1234acd'),('Alice','opqw362');Query OK, 2 rows affected (0.04 sec)Records: 2 Duplicates: 0 Warnings: 0

mysql> select * from t_user;+----------+----------+| username | password |+----------+----------+| Tom | 1234acd || Alice | opqw362 |+----------+----------+2 rows in set (0.00 sec)
注:数据库中总共有两条数据。

picture

》》SQL注入
import mysql.connector#配置数据库参数config={ "host":"localhost", "port":3306, "user":"root", "password":"253611", "database":"gzh", "auth_plugin":"mysql_native_password"}#初始化connect对象con=mysql.connector.connect(**config)#定义usernameusername="1 OR 1=1"#定义passwordpassword="1 OR 1=1"#书写sql语句,AES_DECRYPT为解密函数sql="SELECT COUNT(*) FROM t_user WHERE username=%s " \ "AND AES_DECRYPT(UNHEX(password),'HelloWorld')=%s";#初始化游标cursor=con.cursor()#执行SQL语句,字符串拼接生成cursor.execute(sql%(username,password))#输出数据print("全部数据条数为:",cursor.fetchone()[0])#关闭链接con.close()
总结:》》cursor.execute(sql%(username,password))通过字符串拼接生成SQL语句》》由下图可知,我们SQL注入已经成功,设想如果是delete语句会带来巨大风险》》原因:SQL语句是解释性语言,在拼接SQL语句时,容易被注入恶意的SQL语句

picture

3. Prevent SQL Injection

预编译机制》》解释:预编译SQL语句就是数据库提前把SQL语句编译成二进制,这样反复执行同一条SQL语句的效率会提升》》原理:SQL语句编译过程中,关键字已经被解析过了,所以向编译后的SQL语句传入参数,都会被当作字符串处理,数据库不会解析其中注入的SQL语句

Execution process diagram

picture

import mysql.connector

config={ "host":"localhost", "port":3306, "user":"root", "password":"253611", "database":"gzh", "auth_plugin":"mysql_native_password"}#初始化connect对象con=mysql.connector.connect(**config)#定义usernameusername="1 OR 1=1"#定义passwordpassword="1 OR 1=1"#书写sql语句sql="SELECT COUNT(*) FROM t_user WHERE username=%s " \ "AND AES_DECRYPT(UNHEX(password),'HelloWorld')=%s";#初始化游标cursor=con.cursor()#执行SQL语句,这里sql为预编译后的语句cursor.execute(sql,(username,password))#输出数据print("全部数据条数为:",cursor.fetchone()[0])#关闭链接con.close()
总结:》》cursor.execute(sql,(username,password))通过预编译后二进制执行》》由下图可知,我们防范SQL注入已经成功

picture