☰
python sql注入 Python防SQL注入秘籍大公开,你竟还不知道?
2026/10/12 13:34:24 网站建设 项目流程

中防止sql注入的方法详解

更新时间为, 二零一七年二月二十五日, 十五时四十四分十秒, 作者是一只猿。

SQL注入属于较为常见的网络攻击方式当中的一种, 它并非借助操作系统的漏洞来达成攻击行径, 而是瞄准程序员在编程那会儿所出现的疏忽之处, 借助SQL语句, 达成无需账号便可登录, 甚至还能对数据库予以篡改, 下面的这一篇文章着重给大伙介绍了有关针对SQL注入的防范举措, 有所需求的朋友能够去参考一番。

前言

众多人理应都清楚当下web漏洞里排在首位的便是sql了, 不论运用哪一种语言来开展web后端开发, 只要用到了关系型数据库, 或许都会碰到sql注入攻击方面的问题。那么在web开发的整个进程当中sql注入到底是怎样出现的, 并且又是怎样去把这个问题给解决掉的?

当然, 我这儿可不打算去探讨别的语言究竟是怎样去避免sql注入这种情况发生的, 在网络上, 关于PHP(博主注: 据说这是世界上最厉害的语言)防止注入的各种各样的方法到处都有, 这些方法实际上是相似的, 在这儿我就通过举例来讲一下。

起因

造成漏洞的缘由, 最为常见的便是字符串拼接了, 当然, sql注入并非仅仅是拼接这一种情形, 还有诸如宽字节注入, 特殊字符转义等等诸多形式, 在此就讲讲最为常见的字符串拼接, 这也是初级程序员极易犯下的错误。

首先咱们定义一个类来处理mysql的操作

class Database: aurl = '127.0.0.1' user = 'root' password = 'root' db = 'testdb' charset = 'utf8' def __init__(self): self.connection = MySQLdb.connect(self.aurl, self.user, self.password, self.db, charset=self.charset) self.cursor = self.connection.cursor() def insert(self, query): try: self.cursor.execute(query) self.connection.commit() except Exception, e: print e self.connection.rollback() def query(self, query): cursor = self.connection.cursor(MySQLdb.cursors.DictCursor) cursor.execute(query) return cursor.fetchall() def __del__(self): self.connection.close()

这段代码, 在我先前好多好多脚本当中, 都是可以见到的, 那些涉及对mysql数据库进行操作的脚本, 我都会把它写进这个类里面, 那么, 这个类存在问题吗?

答案是:有!

这样的一个类, 存在着缺陷, 极易致使sql注入情况出现。关于为何会引发sql注入, 下面就要阐述一番。

在此, 为对问题真实性予以验证, 写下一种举措, 以此去调用上面那个类之中的方法, 一旦出现差错, 便会直接将异常抛出。

def test_query(articleurl): mysql = Database() try: querySql = "SELECT * FROM `article` WHERE url='" + articleurl + "'" chanels = mysql.query(querySql) return chanels except Exception, e: print e

该方法极其简易,是一种极为常见的查询语句, 竟也运用了最为简单的字符串拼接来构成sql语句, 显而易见传入的参数能够操控, 若要开展注入测试, 只需在其值的后面添加上单引号便可进行sql注入测试, 对此不多作阐述, 肯定是存在注入漏洞的, 运行一遍脚本, 瞧瞧是啥结果。

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")

回显报错,很眼熟的错误,这里我传入的测试参数是

t.tips'

下面再说一种导致注入的情况,对上面的方法进行稍微修改后

def test_query(articleurl): mysql = Database() try: querySql = ("SELECT * FROM `article` WHERE url='%s'" % articleurl) chanels = mysql.query(querySql) return chanels except Exception, e: print e

这个方法当中并非直接运用字符串拼接, 却是运用了 %s 用以替代即将传入的参数这般的方式, 看上去是不是极为类似那种做了预编译处理的 sql ? 那么这样的写法可不可以防止 sql 注入这一情况的发生? 去做一下测试就可以知晓, 回显如下。

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")

参照上面的测试得出的结果, 是相一致的, 因而这种方式同样是不可行的, 并且这种方式并非是针对预编译sql语句而言的, 既然如此那么要以怎样的做法才能够避免sql注入情况的发生之举呢?

解决

两种方案

1> 对传入的参数进行编码转义

2> 使用的模块自带的方法

第一种方案, 实际上在诸多PHP的防注入方法当中都存在, 针对特殊字符开展转义或者过滤的操作。

存在着第二种方案, 此方案是运用内部方法, 该部方法与PHP里面的PDO相类似, 仅依据这种情况, 对于处在上面位置处的数据库类来说, 进行一番简单的修改便是可行的了。

修改后的代码

class Database: aurl = '127.0.0.1' user = 'root' password = 'root' db = 'testdb' charset = 'utf8' def __init__(self): self.connection = MySQLdb.connect(self.aurl, self.user, self.password, self.db, charset=self.charset) self.cursor = self.connection.cursor() def insert(self, query, params): try: self.cursor.execute(query, params) self.connection.commit() except Exception, e: print e self.connection.rollback() def query(self, query, params): cursor = self.connection.cursor(MySQLdb.cursors.DictCursor) cursor.execute(query, params) return cursor.fetchall() def __del__(self): self.connection.close()

这里在执行之际, 会传入两个参数, 其中第一个是经过参数化的sql语句, 第二个是与之对应的实际的参数值。函数内部会针对传入的参数值开展相应的处理, 以此避免sql被注入。实际运用的方法像下面这样。

preUpdateSql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s" mysql.insert(preUpdateSql, [title, date, content, aid])

以防 sql 注入, 如此行事便可, 于传入一列表后, 于模块内部, 会把该列表序列化为一个元组, 随后开展操作。

总结

我在之前部分脚本里运用了存在 sql 注入破绽的代码, 会逐步改好, 行了, 上面这些便是这篇文章的所有内容, 期望本文内容能给大家的学习或者工作带去一定的助力, 要是有疑问大家能够留言沟通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询