2011-06-28 36 views
32

SQLAlchemyを使用しているときにSQLインジェクション攻撃を緩和するためのベストプラクティスは何ですか?あなたがあなたのデータに(例えばセミコロンや アポストロフィなど)任意の「特別な」の文字がある場合はSQLAlchemy + SQLインジェクション

+24

SQLAlchemy *の使用はベストプラクティスです。 :-) –

答えて

31

は、彼らが 自動的 SQLEngineオブジェクトによって、あなたのために引用されますので、あなたを約 心配する必要はありません引用しています。これはまた意図的にバイパスしない限り を意味します。 SQLAlchemyの引用メカニズム SQLインジェクション攻撃は基本的には不可能 です。 [http://www.rmunn.com/sqlalchemy-tutorial/tutorial.htmlあたり]

+16

答えは、引用符は "the"ドキュメントから来ていると言います。そうでないときは:[チュートリアル](http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html)から来ているようです。 )はSQLAlchemyに関連付けられていません。次に、エスケープ処理を行う例を使用して、エスケープ処理を正しく処理するSQLAlchemy APIの一部を引用しています。しかし、 'execute()'やSQLAlchemyでエスケープされない他のリテラルデータを使用することはできます。はい、ほとんどの場合、SQLAlchemyは自動的にエスケープしますが、リテラルまたは未加工SQLを使用している場合でも、自分自身で足を撃つことができます。 –

51

tldr:できるだけ多くの生のSQLを避けてください。

受け入れられる回答は、怠惰で間違っています。フィルタメソッドは生のSQLを受け取り、そのように使用されると、SQLインジェクション攻撃を受けやすくなります。あなたはURLから値を受け入れ、フィルタに生SQLとそれを組み合わせるした場合たとえば、あなたは攻撃に開かれている:

session.query(MyClass).filter("foo={}".format(getArgs['val']))

上記のコードと、以下のURLを使用して、あなたは次のようになりますフィルタ文にSQLを挿入します。上記のコードはデータベースのすべての行を返します。

http://domain.com/?val=2%20or%201%20=%201

+4

"SQLAlchemyの引用メカニズムを意図的にバイパスしない限り..."はい、raw SQLを入力すると意図的にその引用機構をバイパスしていますので、上記の答えは間違っていません。 – Johnston

+12

私は、フィルタメソッドに生のSQLを渡すことができますsqlalchemyの一部ではなく、 – Mike

+2

フィルタのユーザー入力を受けなければならない場合、ユーザーが未処理SQLを入力してテーブルを削除したり、その他の予期しない動作が発生していないことを確認する正しい方法は何ですか? –

3

@Tendrid answerに追加します。私は静かで素朴な方法で少し調べました。 filterメソッドの引数が*criterionの場合、他のいくつかのORM Queryメソッドにも同様の引数があります。

filterの場合、*criterionの引数が_literal_as_textに渡されます。これは文字列の場合は安全なsqlとしてマークします(私が間違っている場合は修正してください)。したがって、安全ではありません。ここで

*criterion引数でORM Query class方法の調査の結果である:可能な方法のmissusesの

filter - uses _literal_as_text (NOT SAFE) 
having - uses _literal_as_text (NOT SAFE) 

distinct - uses _literal_as_label_reference (NOT SAFE) 
group_by - uses _literal_as_label_reference (NOT SAFE) 
order_by - uses _literal_as_label_reference (NOT SAFE) 

join  - uses model attributes to resolve relation (SAFE) 

例(それをシンプルに保つために、文字列フォーマットはスキップさ):

db.session.query(User.login).group_by('login').having('count(id) > 4; select name from roles').all() 
db.session.query(User.login).distinct('name) name from roles /*').order_by('*/').all() 
db.session.query(User.login).order_by('users_login; select name from roles').all() 
db.session.query(User.login).group_by('login union select name from roles').all() 

注:文字列リテラルが渡された場合、これらのメソッドは安全ではありません。

関連する問題