常用数据库2 sqlite及SQL注入
知识内容:
1.sqlite数据库介绍
2.sqlite数据库操作
3.SQL注入
一、sqlite数据库介绍
1.sqlite数据库
sqlite数据库:轻量级的数据库,一般开发中使用sqlite数据库,上线后将sqlite数据库换成其他数据库(比如MySQL、MongoDB)来进行快速开发
sqlite的数据库操作相对来说比较简单,sqlite是python3中自带的数据库,不用安装,python3中的sqlite3是操作sqlite数据库的模块,可以装一个叫sqlitebrowser的软件浏览sqlite数据库中的数据
2.现在的数据库分类
- 数据库现在主要分 关系型数据库(传统比如MySQL oracle等)
- NoSQL(新式比如 mongodb)
- 其他数据库(比如 fb 的图数据库)
二、sqlite数据库操作
1.数据库结构
传统数据库以表的形式存储数据 一张表可以有很多个字段 以用户表为例, 存储 4 个数据的表结构如下 用户 id 用户名 密码 邮箱 范例数据如下 1 wyb 666 wyb@qq.com 2 xxx 333 xxx@qq.com
2.关于SQL语言
sql语句详细:http://www.cnblogs.com/wyb666/p/9017402.html
1 数据库通过 SQL 来操作数据 2 SQL (结构化查询语言)-> 操作数据库的接口 也就是操作数据库的方法 3 增加数据 删除数据 修改数据 查询数据 4 CRUD 5 create retrieve update delete
3.sqlite操作数据库
几种关系型数据库的用法和 sql 语法都极度相似,开发中一般会用 sqlite 数据库,部署到服务器上的时候才会使用 mysql 等数据库
直接看下面代码:
1 # __author__ = "wyb" 2 # date: 2018/6/27 3 import sqlite3 4 5 # SQL 语句示例: 6 # INSERT INTO 7 # `users`(`id`,`username`,`password`,`email`) 8 # VALUES \ 9 # (2,'','',NULL); 10 # 11 # UPDATE `users` SET `username`=? WHERE `_rowid_`='2'; 12 # UPDATE `users` SET `password`=? WHERE `_rowid_`='2'; 13 # UPDATE `users` SET `email`=? WHERE `_rowid_`='2'; 14 15 16 """ 17 下面是 python 操作 sqlite 数据库的范例代码 18 """ 19 20 21 # 创建数据库中的表 22 def create(conn): 23 # 注意 CREATE TABLE 这种语句不分大小写 24 sql_create = ''' 25 CREATE TABLE `users` ( 26 `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 27 `username` TEXT NOT NULL UNIQUE, 28 `password` TEXT NOT NULL, 29 `email` TEXT 30 ) 31 ''' 32 # 用 execute 执行一条 sql 语句 33 conn.execute(sql_create) 34 print('创建成功') 35 36 37 # 向数据库中插入数据 38 def insert(conn, username, password, email): 39 sql_insert = ''' 40 INSERT INTO 41 users(username,password,email) 42 VALUES 43 (?, ?, ?); 44 ''' 45 # 下面的写法用 string.format 拼 sql, 是一个严重的安全漏洞 -> SQL注入 46 # 会被 SQL 注入 47 # sql = ''' 48 # INSERT INTO 49 # users(username,password,email) 50 # VALUES 51 # ("{}", "{}", "{}") 52 # '''.format('123', '345', 'a.com') 53 # conn.execute(sql) 54 # 参数拼接要用 ?,execute 中的参数传递必须是一个 tuple 类型 55 conn.execute(sql_insert, (username, password, email)) 56 print('插入数据成功') 57 58 59 # 查询数据 60 def select(conn): 61 sql = ''' 62 SELECT 63 * 64 FROM 65 users 66 ''' 67 # 这是读取数据的套路 68 cursor = conn.execute(sql) 69 print('所有数据', list(cursor)) 70 # for row in cursor: 71 # print(row) 72 73 74 # 删除数据 75 def delete(conn, user_id): 76 sql_delete = ''' 77 DELETE FROM 78 users 79 WHERE 80 id=? 81 ''' 82 # 注意, execute 的第二个参数是一个 tuple 83 # tuple 只有一个元素的时候必须是这样的写法 84 conn.execute(sql_delete, (user_id,)) 85 86 87 # 更新数据 88 def update(conn, user_id, email): 89 """ 90 UPDATE 91 `users` 92 SET 93 `email`='gua', `username`='瓜' 94 WHERE 95 `id`=6 96 """ 97 sql_update = ''' 98 UPDATE 99 `users` 100 SET 101 `email`=? 102 WHERE 103 `id`=? 104 ''' 105 conn.execute(sql_update, (email, user_id)) 106 107 108 # 主程序 109 def main(): 110 # 指定数据库名字并打开 -> 没有会自动创建 111 db_path = 'web8.sqlite' 112 conn = sqlite3.connect(db_path) 113 print("打开数据库") 114 115 # create 116 # 打开数据库后 就可以用 create 函数创建表 -> 注意创建表只能创建一次 创建已创建的表会报错 117 # create(conn) 118 119 # insert 120 # 然后可以用 insert 函数插入数据 -> 注意插入一次后下面的数据就不能再插入 因为用户名有限制(unique) 121 # insert(conn, 'test', '123456', 'a@b.c') 122 123 # delete 124 # 可以用 delete 函数删除数据 125 # delete(conn, 1) 126 127 # update 128 # 可以用 update 函数更新数据 129 # update(conn, 1, 'woz_wyb@qq.com') 130 # select 函数查询数据 131 select(conn) 132 133 # 最后提交: 134 # 必须用 commit 函数提交你的修改 135 # 否则你的修改不会被写入数据库 136 conn.commit() 137 # 用完数据库要关闭 138 conn.close() 139 140 141 if __name__ == '__main__': 142 main()
三、SQL注入问题
1.什么是SQL注入
SQL注入:所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将恶意的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入恶意SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句
比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击
注意在拼SQL语句时一定要使用?让数据库自己去拼接字符串,而不是使用某种编程语言自带的语法去拼接字符串,比如在下面使用python中的format拼接字符串就会导致SQL注入的漏洞!
2.SQL注入实例
表结构:
创建数据库及表及插入数据见上面的sqlite操作数据库,SQL注入的实例:
1 # __author__ = "wyb" 2 # date: 2018/6/28 3 import sqlite3 4 5 6 # 查询数据 存在SQL注入隐患 7 def select(conn): 8 # 以下是一个隐患! 完全可以构造一个字符串来注入SQL 看下面的sql_inject函数 9 # 这样的漏洞就是等着被人搞 尤其是PHP 这样的漏洞非常多 字符串拼接在这里是又麻烦又不安全 不要在SQL语句上使用语言自带的字符串拼接 10 user = "123" 11 pwd = "345" 12 sql = ''' 13 SELECT 14 id, username, email 15 FROM 16 users 17 WHERE 18 username="{}" and password="{}" 19 '''.format(user, pwd) 20 # 这是读取数据的套路 21 cursor = conn.execute(sql) 22 print('所有数据', list(cursor)) 23 # for row in cursor: 24 # print(row) 25 26 27 # SQL注入演示 28 def sql_inject(conn): 29 user = '123" or "1"="1' # 一个注入的用户名 30 pwd = "xxadfaksbglwsyfansdvliaysf" # 随便乱打的密码 31 sql = ''' 32 SELECT 33 id, username, email 34 FROM 35 users 36 WHERE 37 username="{}" and password="{}" 38 '''.format(user, pwd) 39 # user = '123" or "1"="1' -> 拼接的结果是: username="123" or "1"="1" and password="随便乱打一个密码" -> 恒成立 40 41 # 读取数据 42 cursor = conn.execute(sql) 43 print('所有数据', list(cursor)) 44 45 46 # SQL拼接正确做法 -> 使用?让数据库自己处理拼接 47 def sql_select(conn): 48 user = '123" or "1"="1' # 一个注入的用户名 49 pwd = "xxadfaksbglwsyfansdvliaysf" # 随便乱打的密码 50 sql = ''' 51 SELECT 52 id, username, email 53 FROM 54 users 55 WHERE 56 username=? and password=? 57 ''' 58 59 # 读取数据 60 cursor = conn.execute(sql, (user, pwd)) 61 print('所有数据', list(cursor)) 62 63 64 # 主程序 65 def main(): 66 # 指定数据库名字并打开 -> 没有会自动创建 67 db_path = 'web8.sqlite' 68 conn = sqlite3.connect(db_path) 69 print("打开数据库") 70 71 # select 查询 72 # select(conn) 73 # SQL注入 74 sql_inject(conn) 75 # 正确的SQL拼接写法 76 sql_select(conn) 77 78 # 最后提交: 79 # 必须用 commit 函数提交你的修改 80 # 否则你的修改不会被写入数据库 81 conn.commit() 82 # 用完数据库要关闭 83 conn.close() 84 85 86 if __name__ == '__main__': 87 main()
最后总结:在拼接SQL语句时一定使用?,千万不要使用编程语言自带的拼接语法(比如python中的format),避免SQL注入漏洞的发生!
3.如何防止SQL注入
在拼接SQL语句时一定使用?,千万不要使用编程语言自带的拼接语法(比如python中的format),避免SQL注入漏洞的发生!