应该在 SQL 语句中指定日期格式吗?

Lei*_*fel 8 oracle sql-injection

我看到开发人员使用隐式日期转换的代码。我想要一个明确的答案,为什么他们不应该这样做。

SELECT * from dba_objects WHERE Created >= '06-MAR-2012';
Run Code Online (Sandbox Code Playgroud)

JNK*_*JNK 15

因为'2012/12/1'在美国是 11 个月后在欧洲相同的字符串日期。

允许隐式转换意味着您受位置设置的支配。

如果您能说出 11 个月是可接受的误差幅度的企业,我会印象深刻。

  • 事实上,“01/01/11”可能是 10 年。+1 (6认同)
  • “命名一个企业,其中 11 个月是可接受的误差范围”——在搜索注册时,家谱引擎往往允许输入年份的任一侧两年。 (2认同)

Lei*_*fel 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
Run Code Online (Sandbox Code Playgroud)

坏数据

  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;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,因为每个更改/插入语句都可以由不同的用户完成。它们都将运行相同的语句,但产生的日期将完全不同。插入语句可能隐藏在一个仅被间接调用的包中。因为没有返回错误,所以可能要很久以后才能发现问题。

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();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,恶意个人可能会更改会话日期格式,从而使他们能够访问通常无法访问的数据。