[java] Java-SQL 삽입을 방지하는 이스케이프 문자열

자바에서 안티 SQL 주입을 시도하고 있는데 “replaceAll”문자열 함수로 작업하기가 매우 어렵다는 것을 알게되었습니다. 궁극적으로 내가 기존 변환하는 기능을 필요 \\\있는, "\", 어떤 '대상을 \', 어떤 \n\\n너무 문자열이 MySQL의 SQL 주입에 의해 평가 될 때이 차단됩니다.

내가 일하고있는 코드를 훔 쳤고 \\\\\\\\\\\함수의 모든 것이 내 눈을 멀게합니다. 누구든지 이것에 대한 예가 있다면 크게 감사하겠습니다.



답변

PreparedStatement는 SQL 삽입을 불가능하게하기 때문에 갈 길입니다. 다음은 사용자 입력을 매개 변수로 사용하는 간단한 예입니다.

public insertUser(String name, String email) {
   Connection conn = null;
   PreparedStatement stmt = null;
   try {
      conn = setupTheDatabaseConnectionSomehow();
      stmt = conn.prepareStatement("INSERT INTO person (name, email) values (?, ?)");
      stmt.setString(1, name);
      stmt.setString(2, email);
      stmt.executeUpdate();
   }
   finally {
      try {
         if (stmt != null) { stmt.close(); }
      }
      catch (Exception e) {
         // log this error
      }
      try {
         if (conn != null) { conn.close(); }
      }
      catch (Exception e) {
         // log this error
      }
   }
}

이름과 이메일에있는 문자가 무엇이든 해당 문자는 데이터베이스에 직접 배치됩니다. 어떤 식 으로든 INSERT 문에 영향을 미치지 않습니다.

각기 다른 데이터 유형에 대해 서로 다른 설정 방법이 있습니다. 사용하는 방법은 데이터베이스 필드에 따라 다릅니다. 예를 들어, 데이터베이스에 INTEGER 열이 있으면 setInt메소드를 사용해야합니다 . PreparedStatement 문서 에는 데이터 설정 및 가져 오기에 사용할 수있는 다양한 방법이 모두 나열되어 있습니다.


답변

SQL 삽입을 방지하는 유일한 방법은 매개 변수화 된 SQL을 사용하는 것입니다. 생계를 위해 SQL을 해킹하는 사람들보다 똑똑한 필터를 구축하는 것은 불가능합니다.

따라서 모든 입력, 업데이트 및 where 절에 매개 변수를 사용하십시오. 동적 SQL은 해커에게 개방 된 문이며 저장 프로 시저의 동적 SQL을 포함합니다. 파라미터 화, 파라미터 화, 파라미터 화.


답변

실제로 방어 옵션 1 : 준비된 문 (매개 변수화 된 쿼리) 또는 방어 옵션 2 : 저장 프로 시저 를 사용할 수없는 경우 자체 도구를 작성하지 말고 OWASP Enterprise Security API를 사용하십시오 . Google 코드에서 호스팅 되는 OWASP ESAPI 에서 :

자신의 보안 통제를 작성하지 마십시오! 모든 웹 애플리케이션 또는 웹 서비스에 대한 보안 제어를 개발할 때 바퀴를 재창조하면 시간 낭비와 막대한 보안 허점이 발생합니다. ESWA (Enterprise Security API) 툴킷은 소프트웨어 개발자가 보안 관련 설계 및 구현 결함을 방지하도록 도와줍니다.

자세한 내용 은 Java 에서 SQL 주입 방지SQL 주입 방지 치트 시트를 참조하십시오 .

방어 옵션 3 : OWASP ESAPI 프로젝트 를 소개하는 모든 사용자 제공 입력 탈출에 특별한주의를 기울이십시오 ).


답변

(이것은 원래 질문에 대한 OP의 의견에 대한 답변입니다. 나는 PreparedStatement가 정규식이 아닌이 작업을위한 도구라는 것에 완전히 동의합니다.)

말할 때 \n시퀀스 \+ n또는 실제 줄 바꿈 문자를 의미합니까? 그것의 경우 \+ n, 작업은 매우 간단합니다 :

s = s.replaceAll("['\"\\\\]", "\\\\$0");

입력에서 하나의 백 슬래시를 일치 시키려면 4 개를 정규식 문자열에 넣습니다. 하나의 백 슬래시를 출력에 넣으려면 그 중 4 개를 대체 문자열에 넣습니다. 이것은 Java 문자열 리터럴 형식으로 정규식 및 대체를 작성한다고 가정합니다. 다른 방법으로 (예 : 파일에서 읽음) 작성하면 이중 이스케이프를 모두 수행 할 필요는 없습니다.

입력에 줄 바꿈 문자가 있고 이스케이프 시퀀스로 바꾸려면 다음을 사용하여 입력을 다시 통과시킬 수 있습니다.

s = s.replaceAll("\n", "\\\\n");

또는 두 개의 백 슬래시를 원할 수도 있습니다 (나는 그것에 대해 명확하지 않습니다).

s = s.replaceAll("\n", "\\\\\\\\n");


답변

PreparedStatement는 대부분의 경우 진행되는 방법이지만 모든 경우에 적용되는 것은 아닙니다. 때로는 쿼리 또는 쿼리의 일부를 나중에 사용하기 위해 문자열로 작성하여 저장해야하는 상황에 처할 수도 있습니다. 다른 프로그래밍 언어의 API 및 자세한 내용 은 OWASP 사이트 에서 SQL Injection Prevention Cheat Sheet 를 참조하십시오.


답변

준비된 문장이 가장 좋은 솔루션이지만 실제로 수동으로해야하는 경우 StringEscapeUtilsApache Commons-Lang 라이브러리 의 클래스를 사용할 수도 있습니다 . escapeSql(String)사용할 수 있는 방법이 있습니다.

import org.apache.commons.lang.StringEscapeUtils;

String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);


답변

정규식을 사용하여 텍스트를 제거하면 SQL 문이 SQL 문이 Statement아닌을 통해 데이터베이스로 전송되는 것처럼 들립니다 PreparedStatement.

처음에 SQL 삽입을 방지하는 가장 쉬운 방법 중 하나는 PreparedStatement문자열을 연결하여 데이터베이스에 전송할 SQL 문을 작성하지 않는 플레이스 홀더를 사용하여 데이터를 SQL 문으로 대체 할 수있는을 사용하는 것입니다.

자세한 내용은 문 준비 사용 에서 자바 튜토리얼 시작하기에 좋은 장소가 될 것입니다.