1. Project Background
本项目主要是通过SQL注入案例来让大家了解如何防范SQL攻击,希望对大家有所帮助
2. Implementation process
》》创建数据表
》》插入数据
》》SQL注入
》》分析原因
mysql> use gzh;
Database changed
mysql> 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)
注:数据库中总共有两条数据。
》》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)
#定义username
username="1 OR 1=1"
#定义password
password="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语句
3. Prevent SQL Injection
预编译机制
》》解释:预编译SQL语句就是数据库提前把SQL语句编译成二进制,这样反复执行同一条SQL语句的效率会提升
》》原理:SQL语句编译过程中,关键字已经被解析过了,所以向编译后的SQL语句传入参数,都会被当作字符串
处理,数据库不会解析其中注入的SQL语句
Execution process diagram
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)
#定义username
username="1 OR 1=1"
#定义password
password="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注入已经成功