Python で SQL インジェクションを防ぐ方法

高洛峰
リリース: 2017-02-28 09:21:34
オリジナル
1127 人が閲覧しました

はじめに

最も一般的な Web 脆弱性は SQL であることを誰もが知っているはずです。Web バックエンド開発にどの言語が使用されていても、リレーショナル データベースが使用されている限り、SQL インジェクション攻撃に遭遇する可能性があります。では、Python Web 開発中に SQL インジェクションはどのように発生し、この問題をどのように解決するのでしょうか?

もちろん、他の言語が SQL インジェクションを回避する方法についてここで議論するつもりはありません。PHP (ブロガー注: 世界で最も素晴らしい言語と言われています) ではインジェクションを防ぐさまざまな方法があります。インターネット。Python のメソッドも同様です。ここで例を示します。

原因

脆弱性の最も一般的な原因は文字列のスプライシングです。もちろん、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()
ログイン後にコピー

このコードは、これまでのスクリプトの多くで見られましたが、Python が 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
ログイン後にコピー

このメソッドは非常に簡単です。最も一般的な選択クエリ ステートメントの 1 つは、SQL ステートメントを形成するために、最も単純な文字列の結合を使用することもできます。 SQL インジェクション テストを実行するには、articleurl の値の後に一重引用符を追加する必要があります。言うまでもなく、スクリプトを実行して結果を確認してください。エラー メッセージはよく知られています。エラー、ここで渡したテスト パラメーターは

(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")
ログイン後にコピー
ログイン後にコピー


上記のメソッドを少し変更した後、次のような状況について話しましょう。このメソッドでは文字が直接使用されていません。文字列連結の代わりに、渡されるパラメータの代わりに %s が使用されます。プリコンパイルされた SQL に非常によく似ていると思いませんか?この書き方でSQLインジェクションを防ぐことはできるのでしょうか?テストすると、エコーは次のようになることがわかります

t.tips'
ログイン後にコピー


は上記のテスト結果と同じであるため、この方法は不可能であり、この方法は SQL ステートメントをプリコンパイルしません。 SQLインジェクションを防ぐには?

解決策


2つの解決策


1> PythonのMySQLdbモジュールに付属のメソッドを使用します

最初の解決策は、実際には多くのPHPアンチ注射メソッドには、特殊文字のエスケープまたはフィルタリングが含まれます。 2 番目のオプションは、PHP の PDO に似た内部メソッドを使用することです。ここでは、上記のデータベース クラスを単純に変更できます。 修正コード

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
ログイン後にコピー

executeが実行されると、2つのパラメータが渡されます。1つ目はパラメータ化されたSQL文で、2つ目は対応する実際のパラメータ値です。渡されたパラメータは、内部で渡されます。入力されたパラメータ値は、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")
ログイン後にコピー
ログイン後にコピー

このようにして、リストを渡した後、MySQLdb モジュールが SQL インジェクションを防ぐことができます。リストをタプルに変換してから、エスケープ操作を実行します。

Python で SQL インジェクションを防ぐ方法に関するその他の関連記事については、PHP 中国語 Web サイトに注目してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート