2016-12-14 11 views
0

MySqlにストアドプロシージャがあり、ユーザからの入力があります。私はSQLインジェクションを避けたい。 MySqlにSQLインジェクションを防止する機能はありますか?私はグーグルではありますが、ほとんどのウェブサイトにMySqlのPHP mysql_real_escape_stringが表示されます。文字列変数をサニタイズするためのmysqlの組み込み関数

入力変数をストアドプロシージャレベルでサニタイズする必要があります。私は準備された文を使用しましたが、依然としてMySqlに任意の組み込み関数があり、指定された文字列をサニタイズします。

CREATE PROCEDURE `SP_Xyz` 
(IN _abc varchar(40), 
) 
BEGIN 
    SET @abc = _abc; 
    // This might cause sql injection 
    SELECT * FROM tbl WHERE col1 = @abc; 
    // We must use prepares statements 
    // But is there any mysql builtin function to sanitize input 
    # Say SELECT * FROM tbl WHERE col1 = PREVENT_SQL_INJECTION(@abc); 
    # In PHP we usually do 
    # $name = mysql_real_escape_string($name); 
    # mysql_query("SELECT * FROM users WHERE name='{$name}'"); 
END 

phpが関数を提供して以来、MySqlに似た関数があります。どんな助けでも大歓迎です。

+0

私はあなたのアプリケーション層でこれを処理する必要があると思います。データベースレベルでクエリをエスケープすることについて聞いたことはありませんでしたが(確かに済んでいますが) –

+0

@TimBiegeleisen、私は同意しますが、タスクやプロジェクトの要件は何ですか?私が見た多くの企業システムでは、DB管理者、プロダクトマネージャーなどが、1つまたは複数の環境でDB書き込みアクセスでデータベースコンテンツを汚しているApp Teamに疲れてしまったため、ストアドプロシージャの検証レイヤーがあります。これは、リレーショナル・インテグリティのデータベース・エンジン実施の背後にある理由でもあります。何をすべきか!=よく行われること。 –

答えて

-1

これは必要ありません。

ストアドプロシージャに渡される変数は、文字通り、クエリに貼り付けられません。そのような方法では、不適切に書かれたPHPアプリケーションのSQLインジェクションの脆弱性につながる可能性があります。

+0

ありがとうございます。したがって、クエリは貼り付けられません。次に、私たちは以下のように@spencerのようなストアドプロシージャのプリペアドステートメントでバインドプレースホルダを使用します。したがって、ストアドプロシージャでもプリペアドステートメントを使用する必要はありません。私に確認してください – user3205479

+0

プリペアドステートメントは、一般に、PHPのような他の言語のインターフェイスでのみ使用されています。ストアドプロシージャではほとんど役に立ちません。 – duskwuff

+1

アーキテクチャでは、複数レベルのセキュリティが必要です。どの層にもセキュリティホールが存在しないと仮定すると、財務、政府、インフラストラクチャー、軍事、または重要なビジネスシステムには賢明ではありません。 –

1

EDITビルKarwin(正しくは)MySQLのQUOTE()機能を指摘しています。この(私の)答えの最初の文はが間違っていたでした。私は、準備されたステートメントでプレースホルダを介して提供される値を "エスケープ"する必要はない、という一般的な考え方に立っています。

これを実行するSQL関数はありません。 1つの必要はありません。

準備済みの文でバインドプレースホルダを使用できます。たとえば、次のように、この特定のケースで

PREPARE stmt FROM 'SELECT * FROM tbl WHERE col1 = ?'; 
    EXECUTE stmt USING @abc; 
    DEALLOCATE PREPARE stmt; 

、プリペアドステートメントを使用する必要はありません。 MySQLの格納されたプログラムの中で、我々はSQLインジェクションの脆弱性を導入することなく、これを行うことができます:

SELECT * FROM tbl WHERE col1 = @abc ; 

が質問にストアドプロシージャを考えると、私たちが実際にユーザ定義の変数を使用する必要はありません、私たちは参照することができ引数の変数を中間のユーザ定義変数に代入しないでください。

DELIMITER $$ 

CREATE PROCEDURE `SP_Xyz`(IN _abc varchar(40)) 
BEGIN 
    -- no SQL Injection vulnerability 
    SELECT * FROM tbl WHERE col1 = _abc; 
END$$ 
2

私はあなたがこれらの義務づける方針に従う他の回答に同意:

  • ちょうど手順であなたの固定されたクエリを持つ変数を兼ね備えています。クエリが動的でない場合、変数はSQLインジェクションを引き起こすことができません。
  • PREPARE/EXECUTEを、クエリが動的である場合はクエリパラメータと共に使用します。とにかくこれは大抵の場合は不要ですが、たとえば、オプションの検索句またはオプションの列を選択リストに含めて問合せを作成する必要がある場合は、動的SQLを使用する必要があります。

しかし、直接あなたの質問に答える:はい、彼らは安全に、動的SQLに補間することができるように、パラメータを使用せずにを照会文字列をサニタイズMySQLでの組み込み関数があります。

QUOTE(str)は、引用符で囲まれた文字列を返します。特殊文字はエスケープされます。

mysql> SELECT QUOTE('Don''t!') as _quoted; 
+-----------+ 
| _quoted | 
+-----------+ 
| 'Don\'t!' | 
+-----------+ 

これは、PHPのPDO::quote()

MySQLを使用しての16年間で、私はこの機能を使用するために必要なことはありません、と述べたものと同様です。ほとんどの場合、prepare-and-executeをクエリパラメータとともに使用する方が良いでしょう。

+1

+10。ビルは正確に(いつものように) 'QUOTE'関数を指摘しています。私の答えはこの点で間違っていた。 QUOTE関数を使用する必要はありませんでした。準備されたステートメント*の*バインドプレースホルダ*を介して提供される値を "エスケープ"する必要はありません。 – spencer7593

2

あなたは良い質問をしています。サイトのセキュリティに関しては、ドキュメントやよく開発された製品を常に信頼するとは限りません。おそらく、ハッカーがPHP、MySQL、その他のシステムコンポーネントの既知または新たに発見されたセキュリティホールを悪用しないようにしたいと考えています。そのようなものは発見され、悪用され、バグリストに追加され、修正され、定期的に新しいリリースに配備されます。

正規表現マッチがスピードの問題であるハイスループットアプリケーションの場合、入力文字列がシングルクォートの前に挿入され、utf-8や不正なシーケンスを正しく処理するかどうかを判断する正しい方法は、文字列はMySQLに入ります。この調査技術はあなたのために働くかもしれません。 (私はそれがストアドプロシージャのI/Oをどのように記録するのか覚えていません)。

  1. 次のSQLを実行します。global_log = 'ON';
  2. 一重引用符を含む文字列、 'Abraham Lincoln'のような識別可能な文字列、およびさまざまなutf-8と違法文字を送信してください。
  3. 次のSQLを実行します。show variables like general_log%;
  4. 「Abraham Lincoln」を見つけてMYSQLがSELECTのために受け取ったものを正確に見るには、良いプログラマツール(Cygwin、LINUX、UNIX、MacなどのRepやvimなど)を使用してください。
  5. ヘビーロギングをオフにするには、次のようにします。set global general_log = 'OFF';

SELECTを使用してデータベースの格納内容を調べるだけで済むため、INSERTとUPDATEを使用する方が簡単です。

他の人が何を言っていても、何が書かれているのか、またあなたの結果が上記のログから得られたものであっても、大量ではない場合、安全であり、正規表現を使用して、 HTTPリクエストから取得します。これはセキュリティアーキテクトのトップルールの1つです。

ユーザーの文字列を検証する方法は数多くありますが、安全であるためには、シミュレートされたブラウズ中に変更できるコードで行う必要があります。クライアント側の検証は、ユーザーの便宜のためのもので、他のスキームに比べてネットワーク帯域幅を縮小しますが、セキュリティを提供することはできません。

ストアドプロシージャを使用しているため、正規表現を使用してそのストアドプロシージャを検証すると便利です。 http://dev.mysql.com/doc/refman/5.7/en/regexp.htmlを参照してください。私は、MySQLがパターンをコンパイルするので速いと信じています。 JavaScriptループから百万回HTTP(s)トランザクションを実行することで、スピードテストを実行したい場合があります。

上記のMySQLリンクに示されている形式でSELECT文の1つを「// SQLインジェクションを引き起こす可能性があります」の代わりに置き、結果をテストします。ゼロが返された場合、文字列が意味を持たないことを意味するインテリジェントな処理を行うようにしてください。

^と$の開始と終了のアンカーでそれぞれ正規表現の両側にアンカリングすることが重要です。この例の正規表現は、電話番号にとっては良い例です: '^ [0-9a-zA-Z()。 - ] + $ '

上記の例のような国際電話番号の場合は、有効範囲を広げておきたい場合があります。

+1

私はいつもPrepを取った。ステートメントは100%安全でした。ちょうど新しいことを学びました! – arnaldop

+0

はい、より安全ですが、セキュリティホールが見つかっており、カーネル、データベース、その他の低レベルライブラリで修正されています。銀行、インフラストラクチャー、政府、軍事および重要なビジネスのセキュリティチームは、多くの場合、複数のレベルの防御(データ検証およびその他の技術)を必要とします。 Bruce SchneierのApplied Cryptographyがその確率を説明します。実践的なシナリオでは、NTTでは毎日攻撃に対抗し、Architectural TeamからすべてのRestFUL呼び出しで多層防御を要求しました。 ITTやDirecTVでも同じです。ハードウェアの暗号化が必要になることがあります。 –

関連する問題