SQLステートメントで日付形式を指定する必要がありますか?


8

暗黙的な日付変換を使用している開発者のコ​​ードを見ています。彼らがなぜこれをしてはいけないのかについての明確な回答をお願いします。

SELECT * from dba_objects WHERE Created >= '06-MAR-2012';

1
例はありますか?
FrustratedWithFormsDesigner 2012年

1
@Frustrated例を追加しました。
Leigh Riffel

to_date()呼び出しでNLS_DATE_LANGUAGEパラメータも使用されていない限り、省略された月の名前も使用しないようにするまで、私はこれまで行きました
a_horse_with_no_name

回答:


15

そのため'2012/12/1'、米国で11ヶ月、ヨーロッパで同じ文字列の日付の後です。

暗黙の変換を許可することは、位置設定に翻弄されることを意味します。

11か月が許容誤差範囲であるビジネスに名前を付けることができれば、感心します。


6
確かに、'01 / 01/11 'は10年オフになる可能性があります。+1
Leigh Riffel

@LeighRiffel:あるいは110年オフ...
ypercubeᵀᴹ

+1、暗黙のDATE変換(または暗黙のデータ型キャスト)に依存することはできません
a_horse_with_no_name

2
「11か月が許容誤差範囲であるビジネスに名前を付ける」-家系図エンジンは、レジスターを検索するときに、入力年のどちら側でも2年を許容する傾向があります。
2012年

1
@onedaywhen良い答え-述べたように、私は感銘を受けました!
JNK 2012年

14

異なる日付形式のセッションでコードを実行すると、問題が発生します。

ステートメントの失敗

DROP TABLE t1;
CREATE TABLE t1 AS (SELECT sysdate mydate FROM dual WHERE 1=2);
ALTER SESSION SET NLS_DATE_FORMAT = 'MON-DD-RR';
INSERT INTO t1 VALUES ('01-02-12');
                       *
ERROR at line 1:
ORA-01843: not a valid month

悪いデータ

  DROP TABLE t1;
  CREATE TABLE t1 AS (SELECT sysdate mydate FROM dual WHERE 1=2);

  --User 1
  ALTER SESSION SET NLS_DATE_FORMAT = 'MM-DD-RR';
  INSERT INTO t1 VALUES ('01-02-11');

  --User 2
  ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-RR';
  INSERT INTO t1 VALUES ('01-02-11');

  --User 3
  ALTER SESSION SET NLS_DATE_FORMAT = 'RR-MM-DD';
  INSERT INTO t1 VALUES ('01-02-11');

  SELECT to_char(mydate,'MM/DD/YYYY') FROM t1;

この状況では、alter / insertステートメントはそれぞれ異なるユーザーが実行できるためです。それらはすべて同じステートメントを実行しますが、結果の日付は完全に異なります。insertステートメントは、間接的にのみ呼び出されるパッケージに埋め込まれている可能性があります。エラーが返されなかったので、後で問題が見つかる可能性があります。

SQLインジェクション

  CLEAR SCREEN;
  DROP TABLE Secrets;
  CREATE TABLE Secrets (RevealDate Date, Secret Varchar2(200));
  INSERT INTO Secrets VALUES (trunc(sysdate),   '*** Common Knowledge. ***');
  INSERT INTO Secrets VALUES (trunc(sysdate+1), '*** Don''t Let Anyone know this. ***');

  CREATE OR REPLACE PROCEDURE ShowRevealedSecrets IS
     vStatement varchar2(200);
     vOutput Varchar2(1000);
     vDate date:=sysdate;
  begin
  vStatement:='SELECT secret FROM Secrets WHERE RevealDate = ''' || vDate || '''';
  execute immediate vStatement INTO vOutput;
  DBMS_Output.Put_Line(vOutput);
  END;
  /

  --Normal Use.     
  ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YY';
  EXEC ShowRevealedSecrets();

  --Explointing SQL Injection
  ALTER SESSION SET NLS_DATE_FORMAT = '"'' OR RevealDate > sysdate--"';
  EXEC ShowRevealedSecrets();

この状況では、悪意のある個人が、通常はアクセスできないデータへのアクセスを許可するような方法で、セッションの日付形式を変更する可能性があります。


+1しかし、SQLインジェクションのケースはかなり狭いと思います。
JNK 2012年

1
@JNK同意します。コードレビューで見落とされる可能性が高くなります。
リーリフェル

1
トピック・オフが、素晴らしいですホワイトペーパーこのSQLインジェクション:accuvant.com/capability/accuvant-labs/security-research/...
Philᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.