[SQL] 어떻게 내가 준비된 문을 사용하지 않고 SQL을 소독
SQL어떻게 내가 준비된 문을 사용하지 않고 SQL을 소독
일부 SQL 문을 위해 나는 예를 들어 준비된 문을 사용할 수 없습니다 :
SELECT MAX(AGE) FROM ?
예를 들어 나는 테이블을 변경하고자 할 때. 소독하라고 자바에서 SQL하는 유틸리티가 있습니까? 루비에서 하나가있다.
해결법
-
==============================
1.오른쪽, 준비된 명령문 쿼리 매개 변수는 단일 문자 값을 사용하는 것이 경우에만 사용할 수 있습니다. 당신은 테이블 이름, 열 이름, 값 목록, 또는 다른 SQL 구문에 대한 매개 변수를 사용할 수 없습니다.
오른쪽, 준비된 명령문 쿼리 매개 변수는 단일 문자 값을 사용하는 것이 경우에만 사용할 수 있습니다. 당신은 테이블 이름, 열 이름, 값 목록, 또는 다른 SQL 구문에 대한 매개 변수를 사용할 수 없습니다.
당신은 SQL 문자열로 응용 프로그램 변수를 보간 적절하게 문자열을 인용 할 필요가 그래서. 테이블 이름 식별자를 구분하고, 그것을 배로 인용 문자열을 탈출 인용 사용을 수행합니다
java.sql.DatabaseMetaData md = conn.getMetaData(); String q = md.getIdentifierQuoteString(); String sql = "SELECT MAX(AGE) FROM %s%s%s"; sql = String.format(sql, q, tablename.replaceAll(q, q+q), q);
테이블 이름 그대로 테이블 "이름 및 RDBMS 식별자 인용 문자는"인 경우 예를 들어, SQL 문자열을 같이 포함해야한다 :
SELECT MAX(AGE) FROM "table""name"
또한 ChssPly76의 의견 @ 동의 - 사용자 입력이 실제로 문자 테이블 이름이 아니라 기표 코드가있는 당신이 다음 보간에 SQL 쿼리, 테이블 이름에 매핑하는 것이 경우가 가장 좋습니다. 이것은 당신에게 어떤 SQL 주입이 발생하지 않도록 더 확신을 제공합니다.
HashMap h = new HashMap<String,String>(); /* user-friendly table name maps to actual, ugly table name */ h.put("accounts", "tbl_accounts123"); userTablename = ... /* user input */ if (h.containsKey(userTablename)) { tablename = h.get(userTablename); } else { throw ... /* Exception that user input is invalid */ } String sql = "SELECT MAX(AGE) FROM %s"; /* we know the table names are safe because we wrote them */ sql = String.format(sql, tablename);
-
==============================
2.가능하지 않습니다. 최고의 당신이 할 수있는 것은 문자열 # 형식을 사용하는 것입니다 ().
가능하지 않습니다. 최고의 당신이 할 수있는 것은 문자열 # 형식을 사용하는 것입니다 ().
String sql = "SELECT MAX(AGE) FROM %s"; sql = String.format(sql, tablename);
이 SQL 주입 위험을 피하지 않습니다. TABLENAME 사용자 / 클라이언트 제어 값 인 경우) (문자열 # 완전히 대체를 사용하여 소독해야 할 것입니다.
tablename = tablename.replaceAll("[^\\w]", "");
도움이 되었기를 바랍니다.
[편집] 나는 추가해야합니다 : 당신이 된 PreparedStatement를 사용하여 열 값이 사용하지 마십시오. 그냥 모든 열 값에 대해 그것을 일반적인 방법을 사용하여 계속합니다.
[Edit2가]는 최상의 사용자 / 클라이언트가 TABLENAME 그것을 원하는 방식으로 입력 할 수 못하게하는 것이나, 그래서 UI에서 (당신이 DatabaseMetaData의 # getCatalogs ()에 의해 얻을 수있는) 모든 유효한 테이블 이름이 포함 된 드롭 다운 더 나은 존재하는 사용자 / 클라이언트를 선택할 수 있습니다. 하나는 요청 매개 변수를 스푸핑 수 있기 때문에 선택이 유효한 경우 서버 측에 확인하는 것을 잊지 마십시오.
-
==============================
3.이 경우 당신은 DatabaseMetaData의에서 나열하는 표를 얻어서 사용 가능한 테이블 목록에 테이블 이름을 확인할 수 있습니다. 실제로 아마 공간, 아마도 일부 SQL 예약어를 제거하는 정규식을 사용하기가 더 쉬울 수있다 ";"등의 문자열의 사전 완전한 SQL 문을 구축 및 String.format liek 것을 사용합니다.
이 경우 당신은 DatabaseMetaData의에서 나열하는 표를 얻어서 사용 가능한 테이블 목록에 테이블 이름을 확인할 수 있습니다. 실제로 아마 공간, 아마도 일부 SQL 예약어를 제거하는 정규식을 사용하기가 더 쉬울 수있다 ";"등의 문자열의 사전 완전한 SQL 문을 구축 및 String.format liek 것을 사용합니다.
아마의 '테이블 이름을 감싸는 및 문자열처럼 탈출되어 있기 때문에 당신의 PreparedStatement를 사용할 수없는 이유입니다.
from https://stackoverflow.com/questions/1677465/how-do-i-sanitize-sql-without-using-prepared-statements by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 VBA에서 변수로 SQL 쿼리의 결과를 저장하려면? (0) | 2020.07.03 |
---|---|
[SQL] SQL - INSERT 및 ID 자동 증가 값을 잡기 (0) | 2020.07.03 |
[SQL] 와 BY와 오라클의 KEEP없이 PARTITION (0) | 2020.07.03 |
[SQL] 여러 테이블이 많은 관계로 하나가 필요합니다 (0) | 2020.07.03 |
[SQL] MySQL의 또는 일반적으로 SQL에서 BETWEEN과 IN 사이의 성능 차이가 있나요? (0) | 2020.07.03 |