Các định dạng ngày có nên được chỉ định trong các câu lệnh SQL không?


8

Tôi thấy mã từ các nhà phát triển sử dụng chuyển đổi ngày ẩn. Tôi muốn một câu trả lời dứt khoát về lý do tại sao họ không nên làm điều này.

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

1
Bạn có một số ví dụ?
Thất vọngWithFormsDesigner

1
@Frustrated Đã thêm một ví dụ.
Leigh Riffel

Tôi thậm chí sẽ đi xa đến mức bạn không nên sử dụng tên tháng viết tắt trừ khi tham số NLS_DATE_LANGUAGE cũng được sử dụng trong cuộc gọi to_date ()
a_horse_with_no_name

Câu trả lời:


15

Bởi vì '2012/12/1'ở Mỹ là 11 tháng sau ngày chuỗi tương tự ở châu Âu.

Cho phép chuyển đổi ngầm định có nghĩa là bạn đang tự hào về cài đặt vị trí.

Nếu bạn có thể đặt tên cho một doanh nghiệp trong đó 11 tháng là một lỗi sai có thể chấp nhận được, tôi sẽ rất ấn tượng.


6
Thật vậy, '01 / 01/11 'có thể là 10 năm. +1
Leigh Riffel

@LeighRiffel: Hoặc thậm chí 110 năm nữa ...
ypercubeᵀᴹ

+1, người ta không bao giờ nên dựa vào chuyển đổi DATE ngầm định (hoặc bất kỳ việc truyền kiểu dữ liệu ngầm nào)
a_horse_with_no_name

2
"Đặt tên cho một doanh nghiệp trong đó 11 tháng là một sai số có thể chấp nhận được" - các công cụ phả hệ có xu hướng cho phép hai năm ở hai bên của năm đầu vào khi tìm kiếm các thanh ghi.
onedaywhen

1
@encedaywhen câu trả lời tốt - như đã nêu, tôi rất ấn tượng!
JNK

14

Có những vấn đề sẽ xảy ra nếu một phiên có định dạng ngày khác chạy mã.

Tuyên bố thất bại

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

Dữ liệu xấu

  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;

Trong tình huống này bởi vì mỗi câu lệnh thay đổi / chèn có thể được thực hiện bởi những người dùng khác nhau. Tất cả họ sẽ chạy cùng một tuyên bố, nhưng ngày kết quả sẽ hoàn toàn khác nhau. Các câu lệnh chèn có thể được chôn trong một gói chỉ được gọi gián tiếp. Bởi vì không có lỗi nào được trả về, vấn đề có thể không được tìm thấy cho đến sau này.

Tiêm 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();

Trong tình huống này, một cá nhân độc hại có thể thay đổi định dạng ngày theo phiên để cung cấp cho họ quyền truy cập vào dữ liệu mà thông thường họ không có quyền truy cập.


+1 nhưng tôi nghĩ trường hợp tiêm SQL khá hẹp.
JNK

1
@JNK Tôi đồng ý, và điều đó làm cho nó có nhiều khả năng bị bỏ qua trong đánh giá mã.
Leigh Riffel

1
Off-topic, nhưng SQL-injection này whitepaper là rực rỡ: accuvant.com/capability/accuvant-labs/security-research/...
Philᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.