는 상관없이, 어떤 언어 및 프레임 워크를 안전하지 않은 쿼리를 작성하지 항상 가능 너는 사용한다.
SQL에 변수을 연결의 순진 방법은 SQL 주입을위한 기회를 만듭니다 단순히 안전한 쿼리에 안전하지 않은 쿼리가되지 않습니다 준비된 쿼리를 사용하여
String unsafeString = "O'Reilly";
create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = '"+unsafeString+"'");
// results in SQL syntax error because of unmatched ' marks
.
SQL 쿼리에서 동적 값을 구분하기 위해 매개 변수를 사용하십시오. 이들은 실행 시간에 RDBMS 내에서 결합됩니다. 매개 변수로 인해 SQL 주입 취약점이 발생할 수있는 방법은 없습니다.
String unsafeString = "O'Reilly";
create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = ?", unsafeString);
// still OK
매개 변수를 사용할 때 변수를 이스케이프 처리 할 필요가 없습니다. 사실 은 데이터에 이스케이프 기호로 끝나기 때문에이 아니어야합니다.
매개 변수는 Java 변수를 SQL 조회로 결합하는 데 적합하지만 SQL 스칼라 값 대신에 유용합니다. 즉, SQL에서 따옴표 붙은 문자열 리터럴, 인용 된 날짜 리터럴 또는 숫자 리터럴을 일반적으로 사용하는 경우 매개 변수 자리 표시 자로 바꿀 수 있습니다.
하지만 당신은 SQL에서 다른 어떤 매개 변수를 사용할 수 없습니다
- 테이블 이름
- 열 이름, 예를 들어 값의
- 목록,
IN (...)
술어 하나 ?
자리를 사용해야합니다 위해 목록의 개별 값당
- SQL 식
- SQL 키워드
당신은 내 프리젠 테이션 SQL Injection Myths and Fallacies (video), 또는 내 책, SQL Antipatterns: Avoiding the Pitfalls of Database Programming
를 좋아할 것
다시 @rehas에서 코멘트 :
실제로
, 준비된 문을 사용하면 이 아님은 암시 적으로 매개 변수를 사용하고 있음을 나타냅니다. . 위의 예제 (첫 번째 예제)에서는 안전하지 않은 변수를 prepare()로 보내기 전에 SQL 문자열에 연결했습니다.
SQL 문자열이 RDBMS 서버에 도착하면 문자열의 어느 부분이 합법적인지, 안전하지 않은 변수로 연결된 부분을 알 수있는 방법이 없습니다. 모든 것은 SQL 문을 포함하는 하나의 문자열입니다.
매개 변수를 사용하는 것은 SQL 문자열과 (잠재적으로 안전하지 않은) 변수를 분리하는 것입니다. RDBMS 서버 내에서 ?
과 같은 매개 변수 자리 표시자를 포함하는 SQL 문자열 정지가 구문 분석됩니다. 구문 분석이 끝나면 다시 구문 분석되지 않으므로 "O'Reilly"와 같은 문자열이 따옴표 나 기타 불일치가 발생할 위험없이 매개 변수 자리 표시 자에 바인딩되는 것이 안전합니다. 매개 변수 값에 앞에 prepare()가 포함 된 경우 쿼리 구문을 변경 한 문자가 포함 된 경우에도 매개 변수의 값이 SQL 실행에서 단일 값으로 처리되도록 보장됩니다.
prepare()를 사용하면 항상 매개 변수를 사용한다는 것은 사실이 아닙니다.
매개 변수를 사용하려면 prepare() 및 execute()를 별도의 단계로 사용해야한다고 말하는 것은 정확합니다. 그러나 일부 프레임 워크는 두 단계를 모두 수행합니다. 당신이 jOOQ 소스 코드를 읽는다면 그것을 볼 수있을 것입니다.
이것은 준비된 진술에 대한 질문이 아니고 JOOQ 라이브러리에 관한 질문이기 때문에 중복되지 않습니다. 대답은 djkelly99입니다. JOOQ를 사용하면 임의의 SQL 문자열을 사용할 수있는'PlainSQL' 주석이 붙은 메소드를 사용하지 않는 한 SQL 삽입 가능성을 없앨 수 있습니다. JOOQ가 안전하다는 사실은 (보통) 준비된 진술을 사용하기 때문이 아닙니다. – Enwired