怎么运用SQLAlchemy库写出防SQL注入的Raw SQL

访客5年前黑客工具570

 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

参阅资料

SQLAlchemy Doc: Using Textual SQL ARCHITECTURAL DOCUMENTATION: SQLAlchemy at Architecture of Open Source Applications StackOverflow: How can I prevent SQL-injection in PHP?

相关文章

谷歌为G-Suite服务布置全新反钓鱼和歹意软件检测功用

Google 为 G Suite 服务推出了全新安全功用,包括企业云核算,生产力和协作东西。 现在企业用户能够运用 Gmail 来绑定企业自定义域名,并进行商务和企业内部的邮件联络。 而G Suite...

CTF标题实战:2019-Hgame-Web-Week4

前语 最近使用空余时刻做了一下Hgame,以下是部分web题题解。 happyPython 信息收集 发现是flask,顺手测验一下。 http://118.25.18.223:3001/{{1+1}...

梦里参加攻防演习活动的过程分享(上)-黑客接单平台

0×01 前语 跟着国家对网络安全的进一步注重,攻防演练活动变得越来越重要,规划也更大。高强度的演习让无论是蓝方仍是红方都变得筋疲力尽,借用朋友圈里一位大佬的一句话:活动完毕的这一天,安全圈的气氛像春...

向Web服务器投递恶意挖矿软件的蠕虫-黑客接单平台

实践中,面向公共互联网供给服务的体系或服务器,都是处于边际方位的。所以无论是物联网设备仍是企业级服务器,只要能被外界访问到,那就会无时无刻被进犯。 最近,咱们发现了一种进犯方法,多个公司Apache...

运用HTML注入进行信息走漏

本篇文章叙述了我怎么发现一个缝隙运用点,而且能够bypass现有安全机制,使我取得5位数赏金。 一个古怪的HTML注入事例 AndréBaptista和Cache-Money正在研讨一个十分风趣的缝隙...

鱼叉式网络钓鱼攻击——一份关于攻击动机、技术和预防方法的完整指南-黑客接单平台

每天都有不计其数的鱼叉式垂钓邮件发送给全世界的受害者。 进犯有许多不同的途径,不管怎样进犯,都会对您的网络形成损伤。 所以,精确的、有针对性的进行剖析和履行是至关重要的。 在本指南中,咱们将介绍鱼叉式...