2012-03-16 35 views
13

Tôi có một trường hợp đặc biệt yêu cầu tôi tạo một phần của mệnh đề WHERE của SQL từ giá trị đầu vào do người dùng cung cấp. Tôi muốn ngăn chặn bất kỳ loại lỗ hổng SQL Injection nào. Tôi đã đi lên với đoạn mã sau:Làm thế nào để an toàn thoát chuỗi tùy ý cho SQL trong PostgreSQL bằng cách sử dụng Java

private String encodeSafeSqlStrForPostgresSQL(String str) { 

    //Replace all apostrophes with double apostrophes 
    String safeStr = str.replace("'", "''"); 

    //Replace all backslashes with double backslashes 
    safeStr = safeStr.replace("\\", "\\\\"); 

    //Replace all non-alphanumeric and punctuation characters (per ASCII only) 
    safeStr = safeStr.replaceAll("[^\\p{Alnum}\\p{Punct}]", ""); 

    //Use PostgreSQL's special escape string modifier 
    safeStr = "E'" + safeStr + "'"; 

    return safeStr; 
} 

Câu hỏi:

  • Bạn có thấy bất kỳ vấn đề?
  • Bạn có thể cung cấp giải pháp tốt hơn không?
  • Có thư viện nào để trợ giúp việc này không?

Ghi chú:

  • Đây là câu hỏi phổ biến trên SO và các nơi khác, nhưng câu trả lời duy nhất mà tôi đã nhìn thấy là luôn luôn sử dụng PreparedStatements. Fwiw, tôi đang sử dụng JasperReports. Tôi muốn giữ truy vấn bên trong JasperReports. Hàm tham số Jasper tích hợp để xử lý tham số truy vấn (bao gồm các hàm X {}) không đủ cho những gì tôi cần để tham số. Tôi có thể thử tạo một Jasper QueryExecutor tùy chỉnh cho phép tôi chèn các hàm X {} của riêng mình, nhưng điều đó phức tạp hơn là chỉ tạo ra một mệnh đề SQL động với cú pháp $ P! {} Của Jasper.

  • Tôi đã xem OWASP libraries. Họ chưa có codec PostgresSQL. Tôi nhìn vào OracleCodec mặc dù và thoát của nó có vẻ đơn giản. Tôi không chắc chắn nó sẽ giúp ích nhiều trong việc ngăn chặn các cuộc tấn công SQL injection.

  • Trong mã của tôi, tôi đang thêm E để không phụ thuộc vào cài đặt standard_conforming_strings của PostgreSQL. Lý tưởng nhất là tôi sẽ không phải thêm nó và sau đó chức năng sẽ không phải là PostgreSQL cụ thể. Thông tin thêm: http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE.

Lý tưởng nhất tôi sẽ thích một giải pháp chung và mạnh mẽ hơn mà tôi biết sẽ an toàn và hỗ trợ tất cả các chuỗi UTF-8 có thể.

+1

'BaseConnection.escapeString()' có vẻ bao gồm http://jdbc.postgresql.org/development/privateapi/org/postgresql/core/BaseConnection.html#escapeString(java.lang.String) –

+1

@FrankFarmer tuyệt vời này ý tưởng xem xét nguồn trình điều khiển JDBC. Nhìn vào BaseConnection dẫn tôi đến lớp Utils: http://jdbc.postgresql.org/development/privateapi/org/postgresql/core/Utils.html. Nhìn vào nguồn cho điều đó, họ bật cờ phù hợp, và sau đó thoát khỏi dấu ngoặc kép/dấu nháy đơn tương tự như những gì tôi đã làm. Họ chỉ có xử lý đặc biệt cho ký tự \ 0 và để mọi thứ khác đi qua. Vì vậy ... Tôi đoán đó là an toàn và loại bỏ của tôi của mỗi phi tiêu chuẩn ký tự vượt quá \ 0 là overkill? Vui lòng đăng nhận xét của bạn dưới dạng câu trả lời mà tôi có thể chấp nhận. – kaliatech

Trả lời

13

Cách đơn giản nhất nhất là nên sử dụng PostgreSQL của Dollar Quoting trong sự kết hợp với một nhỏ ngẫu nhiên tag:

  • Đối với mỗi invocation tính toán một, thẻ ngẫu nhiên nhỏ (ví dụ 4 ký tự) (dư thừa)
  • Xem liệu thẻ trích dẫn có phải là một phần của chuỗi đầu vào hay không.
  • Nếu có, hãy tính lại một thẻ ngẫu nhiên mới.
  • Nếu không xây dựng truy vấn của bạn như thế này:

    $tag$inputString$tag$ 
    

Bằng cách này bạn thoát khỏi toàn bộ rắc rối khác nhau kỹ thuật trích dẫn lồng nhau bạn cũng thiết lập một mục tiêu di động bằng cách sử dụng một thẻ ngẫu nhiên.

Tùy thuộc vào yêu cầu bảo mật của bạn, điều này có thể thực hiện công việc hay không. :-)

+0

Thú vị. Tôi không biết cú pháp chuỗi được trích dẫn bằng đô la. Tôi đã thử nó ngay bây giờ và nó dường như đã hoạt động. Hai lưu ý mặc dù: 1) Bạn là đúng để chỉ ra sự cần thiết phải ngẫu nhiên các thẻ xung quanh vì lý do an ninh. Tôi nghĩ đó là tiêu cực chính liên quan đến cách tiếp cận này. 2) Qua thử nghiệm, tôi đã xác định rằng cú pháp đô la vẫn yêu cầu rằng \ 0 ký tự được loại bỏ khỏi chuỗi (nếu không một ngoại lệ được ném từ Postgres ... mà vẫn còn tốt hơn cho phép một lỗ hổng thông qua). – kaliatech

+1

+1 cho báo giá đô la. Tuy nhiên, có một sự thừa trong logic của bạn. Nếu bạn kiểm tra đầu vào của người dùng cho anyways tag-quote, không cần phải ngẫu nhiên ban đầu. Bạn chỉ cần thay đổi, nếu thẻ báo giá sẽ bật lên, điều thực tế chỉ xảy ra nếu kẻ tấn công đọc mã của bạn. Chỉ sau đó bạn phải đột biến, mà foils các vector tấn công. Tôi lấy sự tự do để vượt qua bước dư thừa. –

+0

@ErwinBrandstetter: Không sử dụng một thẻ ngẫu nhiên ngay từ đầu migh mở một số lỗ nếu kẻ tấn công có thể che giấu việc sử dụng nhiệm vụ của mình bằng cách nào đó. Đây là một handwaving khá một chút ngay bây giờ, nhưng tôi có thể tưởng tượng một số vấn đề mã hóa giữa mã hóa máy chủ và mã hóa khách hàng có thể làm các trick. ISO 2022 (sic?) Sẽ là phỏng đoán đầu tiên của tôi. Nhưng tôi sẽ suy nghĩ về điều này trong khi đang trên một dòng chậm :-) –

1

Tôi đã hỏi similar question ở đây, nhưng tôi nghĩ rằng điều tốt nhất cần làm là sử dụng org.postgresql.core.Utils.escapeLiteral. Đây là thư viện Postgres nên việc sử dụng thư viện phải an toàn. Nếu/khi Postgres thêm các dấu phân tách chuỗi mới, phương thức này sẽ được cập nhật.

Các vấn đề liên quan