mysql sql注入方案_pymysql的sql注入解决方案

本文介绍了SQL注入的概念,通过实例展示了如何使用pymysql进行SQL注入攻击,并提供了两种解决方案:转义特殊字符和使用`escape_string`函数。通过这些方法,可以有效防止SQL注入,确保数据库操作的安全。
摘要由CSDN通过智能技术生成

1.什么是sql注入

释义:

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息

参考文章

2.基于pymysql:sql注入问题举例

例子:

我现在tb1数据库,下面有个user表,结构如下:

mysql> desc user;

+-------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-------+-------------+------+-----+---------+----------------+

| id | int(11) | NO | PRI | NULL | auto_increment |

| name | varchar(10) | NO | | NULL | |

| pwd | varchar(12) | NO | | NULL | |

+-------+-------------+------+-----+---------+----------------+

3 rows in set (0.00 sec)

查看一下user表当前的数据:

mysql> select id, name, pwd from user;

+----+------+---------+

| id | name | pwd |

+----+------+---------+

| 1 | jack | jack123 |

| 2 | rose | rose123 |

+----+------+---------+

2 rows in set (0.00 sec)

现在用pymysql来连接数据库,然后进行sql语句查询,一般的查询都是用户名=xxx and 密码=xxx,下面先来写一个函数,来连接数据库:

import pymysql

def query(sql):

conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', password='', db='tb1')

cursor = conn.cursor()

cursor.execute(sql)

print('打印结果:', cursor.fetchall())

cursor.close()

conn.close()

if __name__ == "__main__":

sql = "select * from user where name= %s and pwd=%s" % ("'' or 1=1 #", 'sdf')

print(sql)

query(sql)

输出

select id, name, pwd from user where name= '' or 1=1 # and pwd=sdf

打印结果: ((1, 'jack', 'jack123'), (2, 'rose', 'rose123'))

sql将里面的' '进行转义后再去查询,转义后sql语句查询会语法错误,完美解决sql注入问题。

case2:将sql语句先escape_string,然后执行

if __name__ == "__main__":

# sql = "select id, name, pwd from user where name= %s and pwd=%s" % ("'' or 1=1 #", 'sdf')

# print(sql)

sql = "select * from user where name= %s and pwd=%s" % ("'' or 1=1 #", 'sdf')

escape_string_sql = pymysql.escape_string(sql)

print(escape_string_sql)

query(escape_string_sql)

输出结果

escape_string_sql: select * from user where name= \'\' or 1=1 # and pwd=sdf

# 报错如下:

pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\\'\\' or 1=1 # and pwd=sdf' at line 1")

sql将里面的' '进行转义后再去查询,转义后sql语句查询会语法错误,完美解决sql注入问题。

3.pymysql.escape_string源码简析

下面摘取片段escape_string的源码:

_escape_table = [unichr(x) for x in range(128)] # 对128个unicode字符生成列表

_escape_table[0] = u'\\0'

_escape_table[ord('\\')] = u'\\\\'

_escape_table[ord('\n')] = u'\\n'

_escape_table[ord('\r')] = u'\\r'

_escape_table[ord('\032')] = u'\\Z'

_escape_table[ord('"')] = u'\\"'

_escape_table[ord("'")] = u"\\'"

# 将Unicode某些字符进行替换

def _escape_unicode(value, mapping=None):

"""escapes *value* without adding quote.

Value should be unicode

"""

return value.translate(_escape_table) # 根据映射进行替换

if PY2:# 在python2中

def escape_string(value, mapping=None):

"""escape_string escapes *value* but not surround it with quotes.

Value should be bytes or unicode.

"""

if isinstance(value, unicode):

return _escape_unicode(value)

assert isinstance(value, (bytes, bytearray)) # 如果是字节的话

value = value.replace('\\', '\\\\')

value = value.replace('\0', '\\0')

value = value.replace('\n', '\\n')

value = value.replace('\r', '\\r')

value = value.replace('\032', '\\Z')

value = value.replace("'", "\\'")

value = value.replace('"', '\\"')

return value # 将字节里面进行转义

def escape_bytes_prefixed(value, mapping=None):

assert isinstance(value, (bytes, bytearray))

return b"_binary'%s'" % escape_string(value)

def escape_bytes(value, mapping=None):

assert isinstance(value, (bytes, bytearray))

return b"'%s'" % escape_string(value)

else:

escape_string = _escape_unicode # 在python3中unicode_string = escape_string

分析:

1.对128个ASCII码,在PY2中用unichr()函数转换为对应字符,并按顺序生成列表。

在PY3中用chr(),unichr已经不适用PY3了;

2.将128个转换后的特殊字符用ord()找到特殊字符顺序,然后进行重新赋值(转义),生成最终的ASCII字符对照表(已转义)。

3.定义了_escape_unicode函数,函数传入一个参数为value,可以理解为我们传入的sql语句,返回的是将值的每个ASCII字符对应位置进行转化。

4.判断当前python环境

如果是python2,escape_string判断value值是不是unicode类型,如果是,直接调用_escape_unicode方法

如果是bytes类型,那么就针对bytes类型的特殊字符进行转义操作即可,然后返回转义后的value

为什么PY2中要进行类型判断?:

这需要从PY2和PY3的编码变化来说

- PY3:所有str类型都是Unicode对象

- PY2:默认编码是ascii,但是有2中数据模型来支持字符串这种数据类型,分别为str(bytes类型)和unicode,所以要进行判断str到底是bytes,然后进行操作。

5.然后如果是PY3,PY3所有str都是unicode类型了,所以_escape_string=_escape_unicode方法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值