ホームページ >バックエンド開発 >Python チュートリアル >Pythonを使用してSQLインジェクションを防ぐ方法

Pythonを使用してSQLインジェクションを防ぐ方法

高洛峰
高洛峰オリジナル
2017-03-16 16:14:261774ブラウズ

はじめに

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


もちろん、他の言語が SQL インジェクションを回避する方法については議論したくありません。PHP でのインジェクションを防ぐ方法は、実際にはインターネット上にあります。ここでは例を示します。

原因

この脆弱性の最も一般的な理由は文字列スプライシングです。もちろん、SQLインジェクションは単なるスプライシングのケースではなく、ワイドバイトインジェクション、特殊文字エスケープなど、他にも多くの種類があります。 , ここでは、最も一般的な文字列の連結について説明します。これは、ジュニア プログラマーにとって最もよくある間違いでもあります。


まず、mysql

class Database:
    hostname = '127.0.0.1'
    user = 'root'
    password = 'root'
    db = 'pythontab'
    charset = 'utf8'
    def init(self):
        self.connection = MySQLdb.connect(self.hostname, 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()

の操作を処理するクラスを定義しますこのクラスに問題はありますか?

答えは「はい」です。


このクラスには欠陥があり、SQL インジェクションが簡単に発生する可能性があります。なぜ SQL インジェクションが発生するのかについて説明します。


問題の真偽を検証するために、上記のクラス内のメソッドを呼び出して、エラーが発生した場合に直接例外をスローする方法を示します

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

このメソッドは非常に単純です。最も一般的な select

query ステートメントの 1 つは、最も単純な文字列連結を使用して SQL ステートメントを形成します。注入テストを実行する場合は、渡されるパラメーター testUrl が制御可能であることは明らかです。 SQL インジェクション テストを実行するには、testUrl の値の後に一重引用符を追加するだけです。言うまでもなく、スクリプトを実行して結果を確認してください


(1064, " SQL 構文にエラーがあります。MariaDB サーバーのバージョンに対応するマニュアルを確認してください

、行 1 の ''t.tips''' 付近で使用する

正しい構文を確認してください。 エラー メッセージが表示されます。はよくあるエラーです。ここで渡します。入力されたテストパラメータはt.tips'

上記のメソッドを少し変更した後の別の状況です

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

このメソッドは直接使用しません。文字列のスプライシングですが、渡されるパラメータの代わりに %s を使用しますが、プリコンパイルされた SQL と非常によく似ていますか?この書き方でSQLインジェクションを防ぐことはできるのでしょうか?テストしてみるとわかります。応答は次のとおりです

(1064, "SQL 構文にエラーがあります。"t.tips 付近で使用する正しい構文については、MariaDB サーバーのバージョンに対応するマニュアルを確認してください。 ''' 行 1")

テスト結果は上記と同じであるため、この方法は実行可能ではありません。また、この方法はプリコンパイルされた SQL ステートメントではありません。では、SQL インジェクションを防ぐにはどうすればよいでしょうか?

解決策

2つの解決策

1>受信パラメータのエンコードとエスケープ


2>最初の解決策は、実際には多くのPHPにありますアンチ-注入メソッドでは、特殊文字はエスケープまたはフィルターされます。


2 番目のオプションは、PHP の

PDO
に似た内部メソッドを使用することです。ここでは、上記のデータベース クラスを単純に変更できます。


変更されたコード

class Database:
    hostname = '127.0.0.1'
    user = 'root'
    password = 'root'
    db = 'pythontab'
    charset = 'utf8'
    def init(self):
        self.connection = MySQLdb.connect(self.hostname, 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()

executeが実行されると、2つのパラメータが渡されます。1つ目はパラメータ化されたSQL文で、2つ目は対応する実際のパラメータ値です。関数は、受信したパラメータ値を内部的に処理します。 SQL インジェクションを防ぐために、実際に使用されるメソッドは次のとおりです


preUp

date

Sql = "UPDATE `article` SET title=%s,date=%s,mainbody= % s WHERE id=%s"

mysql.insert(preUpdateSql, [title, date, content, aid])

これにより、SQL インジェクションを防ぐことができます。リストを渡した後、MySQLdb モジュールはリストをタプルにシリアル化します。そして脱出操作を実行します。

以上がPythonを使用してSQLインジェクションを防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。