『Oracleプログラミングアート』を読んで感銘を受けたSQL注入とバインド変数について


Oracle Database 9 i/10 g/11 gプログラミングアートデータベースアーキテクチャ第2版に記載されています.
SQL注入はセキュリティ・ホールであり、開発者がエンド・ユーザーからの入力を受け入れ、この入力をクエリーにつなぎ、このクエリーをコンパイルして実行すると、このセキュリティ・ホールが存在します.実際には、開発者はエンドユーザーからのSQLコードセグメントを受け入れ、これらのコードセグメントをコンパイルして実行することができます.この方法では,エンドユーザがSQL文を修正し,アプリケーション開発者が意図しなかったことをする可能性がある.これは、端末を開いてSQLPlusセッションにログインし、SYSDBAとして接続するようなものです.誰かがコマンドを入力してコンパイルして実行することを望んでいます.結果は災難的になるだろう.
SQLインジェクションとは、SQLコマンドをWebフォームに挿入してドメイン名やページリクエストのクエリー文字列を渡したり入力したりすることで、最終的にサーバをだまして悪意のあるSQLコマンドを実行することです.『Oracleプログラミングアート』の上の引用によると、簡単に言えば、SQL注入は特定のパラメータを入力することによって、それからこのパラメータをSQLセグメントの形式でつなぎ合わせた後にコンパイルして実行して、重点はSQLの“つなぎ合わせ”です!
SQL注入攻撃の危険性を説明するために、『Oracle Databaseプログラミングアート』では、SQL注入の危険性をより簡単な例で感じてみましょう.
 
SELECT STUNO, STNAME FROM STUDENT T
WHERE T.CREATE_DATE = 

もし私たちのプログラムが学生情報表から学生の学号と名前情報を読むと、入力した入学日(作成日)パラメータを通じて指定した学生の情報を返します.
プログラムが接合のモードを使用している場合、例えば:
DBMS_OUTPUT.PUT_LINE('
     SELECT STUNO, STNAME FROM STUDENT T
     WHERE T.CREATE_DATE =' || P_CREATE_DATE );

入力パラメータをSQL文に直接接続し、コンパイルして実行します.
CREATE_DATEはVARCHARタイプで、例えば「YYYY-MM-DD」という文字列フォーマットが格納されており、SQL注入を知った子供靴たちは一目でこの文の灰がSQL注入攻撃を受けやすいことがわかります.
ここで、問題を説明するために、もう一つのテーブルT_を導入するPASWORDは、機密のユーザーパスワード情報などが格納されています.もちろん、この表のデータをすべての人に見せたくありません.さらに、不要な人にこのような表があることを知られたくありません.しかし、ハッカー(または悪意のある開発者)は、上記のSQLセグメントでSQL注入を利用してこのテーブルデータを読み取ることができます.
    
まず、悪意のある開発者やユーザーはこのテーブルがあることを知らないが、彼らは入力したパラメータP_を通じてCREATE_DATEイコール
'' UNION ALL SELECT '', T.OWNER||'.'||T.TABLE_NAME FROM ALL_TABLES T

これにより、悪党たちはフロントの開発者が提供したパラメータポートを通じて、ライブラリのライブラリテーブル情報を表示することができます.T_PASWORD表の存在はもちろん露呈しますよね~
   
彼らは私たちのTを知らないと言うかもしれませんPASWORDにはどんなフィールドがありますか.はい、彼らはまだ知りませんが、次のステップで知っています.彼らはT_を知ったPASWORDテーブルの後、このテーブルのフィールドを理解するには、パラメータP_を入力することもできます.CREATE_DATEイコール
'' UNION ALL SELECT '' , T.COLUMN_NAME ||'.'||T.DATA_TYPE FROM ALL_TAB_COLS T
                    WHERE T.OWNER = ... AND T.TABLE_NAME = ...

   
ここに着いたら、彼らがTを見ることができることも知っています.PASWORD表データでしょう.
 
CREATE_DATEはVARCHARタイプのフィールドで、ここでは仮説にすぎず、制限ではありません!VARCHARタイプのフィールドではなく、入力されたパラメータは合法ではないかと聞かれるかもしれません.これでSQL注入攻撃を回避できるのではないでしょうか.実は、そうではありません.CREATEを手に入れることができますDATEはDATEタイプについて引き続き説明しますが、DATEのような7バイトのバイナリフォーマットでもSQL文がSQL注入される攻撃を受けることは避けられません.
Oracle Database 9 i/10 g/11 gプログラミングアートデータベースアーキテクチャ第2版に記載されています.
現在、私の知っている多くの開発者はコードを見て、このコードはSQL注入攻撃を受けないと言います.また、このルーチンの入力はORACLE DATE変数でなければならないため、DATEは世紀、年、月、日、時、分、秒を表す7バイトのバイナリフォーマットであると説明します.DATE変数はSQL文の意味を変えることができないと考えています.しかし、実際には、彼らは間違っています!このコードは確かに「注入される」ことができ、方法のある人(明らかに、どうすればいいか知っている人が多い)が軽く再実行できるときに修正することができます.
たとえば、悪意のある開発者やユーザーは、次のコードを実行するだけでいいです.
ALTER SESSION SET
    NLS_DATE_FORMAT = ' '' ' ' UNION SELECT TNAME,0,NULL FROM TAB-- '' ';

 
Oracle Database 9 i/10 g/11 gプログラミングアートデータベースアーキテクチャ第2版に記載されています.
このNLS_DATE_FORMATはとても面白くて、多くの人はNLSを使うことができることさえ知らない.DATE_FORMATには文字列の字面量が含まれています.(また、NLS_DATE_FORMATという「テクニック」を使わなくても、このように日付フォーマットを変えることができることを知らない人も多いです.)
NLS_を通じてDATE_FORMATの設定は、上記のようにSQL注入も可能です!
 
(注:上記の日付フォーマットの変更は、本人はまだ理解していません.後で研究する時間があります)
 
 
 
 
では、私たちはどのように自分を守るのでしょうか.最も直接的な方法は、バインド変数を使用することです.
OPEN C_CURSOR FOR 
' SELECT STUNO, STNAME FROM STUDENT T
  WHERE T.CREATE_DATE = :P_CREATE_DATE '  USING P_DATE

 
バインド変数を使用すると、SQL注入攻撃に遭遇しません.実は、バインド変数はプログラムの実行速度を向上させることができますが、本文はSQL注入攻撃の思想に言及し、このハッカーがよく使う手段と防犯方法を理解することを目的としています.その他は本稿で議論する範囲内ではありませんので、ここではあまり説明しません.