Python阵营有许多操作数据库的开源库(装置pip后,能够凭借”pip search mysql”检查可用的库列表),其中被运用最多的无疑是MySQLdb,这个库简略易上手。其偏底层的特性为开发者供给灵活性的一起,也对不少新手写出的DB操作代码提出了检测,由于它只支撑raw sql,简略导致sql注入进犯。
鉴于此,许多库供给了ORM接口才能,凭借OO思维,数据库中的表被映射为Python的类,类的目标代表数据表中的一行记载,一切的DB操作都经过目标办法调用来完成,这些调用在底层被主动转化成SQL句子,在转化过程中, 通常会选用parameter bind的办法确保生成的parameterized SQL不存在被注入的危险 。
SQLAlchemy 便是这样一个具有ORM才能的DB操作Python库,此外,该库还支撑开发者履行raw sql,并经过其供给的text目标完成 params binding ,然后防护SQL注入危险。
补白1:PHP中的DB操作库(如PDO或MySQLi)支撑的prepare/bind_param接口也是业界引荐的防备sql injection的办法,而escape_string只能对单/双引号等特别字符做简略的替换,它并不能确保防护一切的危险字符。
补白2:SQLAlchemy的官方文档比较多,其架构细节能够参阅 SQLAlchemy at Architecture of Open Source Applications 这篇文章,信任对初学者有不小的协助。
下面的代码示例用来阐明怎么凭借SQLAlchemy的parameters bind才能来写出能避免sql注入的raw sql。
条件假定
假定咱们完成了一个简略的sqlalchemy封装类(dbutil.py),代码如下:
#!/bin/env python #-*- encoding: utf-8 -*- from sqlalchemy import create_engine class DbWrapper(object): _db_inst = None _db_driver_cfg = { 'dbtype' : 'mysql', } @clas *** ethod def get_db_inst(cls, dbtype = 'mysql', user = '', password = '', host = '127.0.0.1', port = 3306, dbname = '', encoding = 'utf-8'): if cls._db_inst is None: stmt = '%s://%s:%s@%s:%s/%s' % (cls._db_driver_cfg['dbtype'], user, password, host, port, dbname) cls._db_inst = create_engine(stmt, encoding = encoding) return cls._db_inst
上面的代码十分简略,在需求操作db时,经过调用dbutil.get_db_inst()并传入db装备就能获取到能够操作db的类的实例。
补白:db实例更好创立一次后保存起来,进程发动后在做必要的初始化作业时就能够先把db实例创立出来且整个进程都可用这个实例拜访数据库。这是由于sqlalchemy库是支撑 connection pool 且默许启用的,在大多数情况下,一个db实例足以应对整个进程对db的并发拜访需求。
insert示例
下面以insert sql为例阐明怎么凭借sqlalchemy.text写出无sql注入危险的raw sql(假定现已创立出_db_inst实例)。
#!/bin/env python #-*- encoding: utf-8 -*- import time from sqlalchemy import text def insert_into_xxx_tbl(user_id, user_name, nickname): insert_params_dict = { 'user_id': user_id, 'user_name': user_name, 'nickname': nickname, 'db_insert_time': int(time.time()), 'db_update_time': int(time.time()), } ## use sqlalchemy bindparams to prevent sql injection pre_sql = 'insert into xxx_tbl (user_id, user_name, nickname, db_insert_time, db_update_time) values(:user_id, :user_name, :nickname, :db_insert_time, :db_update_time)' bind_sql = text(pre_sql) resproxy = _db_inst.connect().execute(bind_sql, insert_params_dict) ## return lastid as event_id event_id = resproxy.lastrowid return event_id
select示例
select的用法与insert相似:凭借Python dict结构select sql where条件的kv pairs,使用text()对sql进行参数绑定,调用execute()时传入绑定的sql及真实的参数即可。
#!/bin/env python #-*- encoding: utf-8 -*- import time from sqlalchemy import text def select_from_xxx_tbl(event_id): select_params_dict = { 'event_id': event_id, } ## use sqlalchemy bindparams to prevent sql injection pre_sql = 'select user_id, user_name, nickname from xxx_tbl where event_id = :event_id' bind_sql = text(pre_sql) resproxy = _db_inst.connect().execute(bind_sql, select_params_dict) rows = resproxy.fetchall() ret = rows[0] ## return (user_id, user_name, nickname) return ret
前语 本文合适Web安全爱好者,其中会说到8种思路,7个东西和还有1个小程序,看本文前需求了解相关的Web基础知识、子域名相关概念和Python 程序的基础知识。 感谢我的老友龙哥的技巧大放送以及Or...
许多Web运用会有避免跨站恳求假造的战略,比方经过request恳求传一个当时页面有用或许当时会话有用的参数(假如他们没有,那就很值得研讨)。这些参数用来证明这个恳求是从预订用户宣布的,而不是进犯者那...
要挟行为者在损害体系时,一般需求考虑怎么进入方针网络才干防止被检测到,而传递歹意附件的网络垂钓邮件往往就充当了初始感染前言的人物。 此外,攻击者还需求一种办法,在安全监控产品的眼皮底下履行代码。最常见...
各位在企业中做Web缝隙扫描或许浸透测验的朋友,或许会常常遇到需求对图形验证码进行程序辨认的需求。许多时分验证码分明很简略(关于非互联网企业,或许企业界网中的运用来说特别如此),但由于没有趁手的辨认...
在工业操控体系(ICS)的安全办理中,安全办理一般被分为3大块:物理设备的安全、IT安全和运营安全(工厂安全和体系完整性)。 现在在工业操控体系(ICS)的安全办理中,信息技能(IT)安全测验变得越来...
今日给咱们介绍的是Github上一个名叫PyMLProjects的项目,这个项意图意图是为了练习AI来学习人类结构暗码的形式,然后咱们就可以用AI来生成许多同一形式或品种的暗码了。这种办法或许可以用...