2017-11-22 1 views
0

私はランダムなSQL文を受け取り、実行結果を返すシステムを持っています。私は、読み取り専用ステートメントを実行し、レコードを更新/挿入/削除するなどのステートメントを拒否するようにシステムを制限したいと考えています。文を実行する前に文を更新するかどうかをチェックする

ステートメントが実際に実行されていない読み取り専用ステートメントであるかどうかを確認する方法はありますか?

注:

  • システムはとにかくデータベースへのフルアクセス権を持っているいくつかの「信頼できる」ユーザーのみアクセス可能です - ので、私が欲しいのは「おっと」安全策である - 私はこれがあることを理解SQLインジェクション攻撃などを処理する方法ではありません。
  • 正規表現の検証はおそらくあまりにも複雑です。たとえば、コメントや列名に「禁止された単語」が含まれていればOKです。
    は、これは有効な入力する必要があります:

    SELECT 
        a AS update_value, 
        'INSERT FOR FUN' AS q 
    FROM t --comment: should we delete stuff? 
    /*why not as long as you don't drop database*/ 
    

    しかし、これは拒否されなければならない:

    UPDATE t SET a = 1 
    
  • が、私はむしろ、私がいることを信じている
+6

これを防ぐために、読み取り専用ユーザを作成するのは**唯一の**安全な方法です。代わりはありません。 –

+0

ユーザは任意のアドホッククエリを実行できますか?許可は 'SELECT'だけに制限してください。 –

+0

@a_horse_with_no_nameそれは私が得ることを望んでいた答えです - それを投稿しても構いません。 – assylias

答えて

2

別々の読み取り専用ユーザーを作成していないと思いますこれには2つの解決策があります:

  1. 入力を解析するのに、sqlparserまたはANTLR4などのパーサを使用できます。それであなたはどんなコマンドを持っているのかを決めるのは簡単です。 SQLParserには、SQLコマンドを分類する方法を示すサンプルの例があります。 ANTLR4よりもANTLR4を使用すると、成功した構文解析の後に構文解析ツリーが得られます(gramar)。 SELECT文がある場合は、構文解析ツリーにselect_statementの文法規則が必要です。

  2. SET SHOWPLAN_XML ONを使用して、XMLで見積もり計画を取得できます。 SQL Serverによって返されたXMLにはStatementTypeという属性があり、ケースにはSELECTの値が必要です。

1

非常にエレガントではない、と確かにない防弾 - しかし、我々は、一度実装不審なSQLステートメントの周りSELECTラッパーだったもの。

あなたのユーザータイプ

UPDATE t SET a = 1 

のであればその後、我々は、これをラップ:SELECTラッパー内の何かがupdatedeleteまたはinsert(ある場合には、一般的にエラーが発生します

SELECT TOP 1 * FROM 
(
UPDATE t SET a = 1 
) 

さらに重要なことに、DROP TABLE,TRUNCATEなど)。次に、テーブルを大幅に変更するSQL文を実際に実行しないようにします。しかし、SQLステートメントが純粋なSELECTステートメントであれば、エラーはなく、1行が戻されます。

ストアドプロシージャなどではあまり役に立ちませんが、多くの制限がありますが、私たちの文脈では完璧な解決策でした(もちろん、TOP 1を修正または削除することもできます)。 (私たちは、アプリケーションにSQLのフリーハンドを入力する機能をユーザに与えました)

+0

SELECTにCTEがある場合はどうなりますか? –

+0

@RadimBačaあまり確かではありません:)この特定のシナリオでCTEに遭遇したことはありませんでした。テストする価値があります。価値があるテスト:) – Grantly

関連する問題