常用数据库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注入漏洞的发生!

原文地址:https://www.cnblogs.com/wyb666/p/9236686.html