MyBatis
${} 바인딩은 "" 없이 바로 바인딩 (동적 바인딩을 위해 string처리를 해주지 않는다.)
<aside> 💡
${}와 #{}
#{} (Prepared Statement 방식)
${} (문자열 치환 방식)
MyBatis에서 외부 정보를 활용하여 SQL을 사용할 때는 가급적 #{}를 사용할 것
SQL 관련 코드 및 특수 문자 입력 방지
코드 예제
public class SqlInjectionPrevention {
// SQL 인젝션에 사용될 수 있는 특수문자 목록
private static final String SPECIAL_CHAR_PATTERN = "[\\\\'\\";--`~!@#$%^&*()+=\\\\[\\\\]{}|\\\\\\\\:<>/?]";
private static final String[] forbiddenKeywords = {"SELECT", "INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "CREATE", "UNION"};
public static boolean isSafeInput(String input) {
// 입력값이 없는 경우 안전하지 않다고 판단
if (input == null || input.trim().isEmpty()) { return false; }
// 특수문자 확인
if (Pattern.compile(SPECIAL_CHAR_PATTERN).matcher(input).find()) { return false; }
// 금지된 키워드 확인
String upperCaseInput = input.toUpperCase();
for (String keyword : forbiddenKeywords) {
if (upperCaseInput.contains(keyword)) { return false; }
}
return true;
}
}
SPECIAL_CHAR_PATTERN: 이 정규식 패턴은 SQL 인젝션에 사용될 수 있는 다양한 특수문자를 포함합니다.
\\\\' : Single Quote (')\\\\" : Double Quote ("); : Semicolon (;)- : Double Hyphen (-)\\\\ : Backslash (\\)<> : Angle Brackets (<, >)~!@#$%^&*()+=[]{}|: 흔히 SQL 인젝션에 사용될 수 있는 기타 특수문자Pattern.compile(SPECIAL_CHAR_PATTERN).matcher(input).find():
외부 입력값을 검증하지 않고 시스템 자원에 대한 식별자로 사용하는 경우
안좋은 예시 : 사용자에게서 받아 직접 사용
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a port number: ");
String portInput = scanner.nextLine();
try {
// 사용자가 입력한 포트 번호를 그대로 사용
int port = Integer.parseInt(portInput);
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server started on port: " + port);
} catch (NumberFormatException | IOException e) {
System.out.println("Invalid port number or port is not available.");
} finally {
scanner.close();
}
}
사전에 정의된 포트 목록 사용
// 사전 정의된 포트 목록
private static final Map<Integer, Integer> PORT_OPTIONS = new HashMap<>();
static {
PORT_OPTIONS.put(1, 8080);
PORT_OPTIONS.put(2, 9090);
PORT_OPTIONS.put(3, 10010);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Select a port option:");
for (Map.Entry<Integer, Integer> entry : PORT_OPTIONS.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
try {
System.out.print("Enter your choice: ");
int choice = scanner.nextInt();
// 선택한 포트 번호 가져오기
Integer port = PORT_OPTIONS.get(choice);
if (port == null) {
throw new IllegalArgumentException("Invalid choice. Please select a valid option.");
}
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server started on port: " + port);
} catch (InputMismatchException e) {
System.out.println("Invalid input. Please enter a numeric choice.");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println("Port is not available.");
} finally {
scanner.close();
}
}
웹 페이지에 악의적인 스크립트를 포함시켜 사용자 측에서 실행되도록 유도
사용자 세션 하이재킹, 쿠키 탈취, 사용자 인증 정보 도용 등의 보안 문제를 일으킬 수 있다.
XSS 방지 방법
사용자가 입력한 모든 데이터를 검증하고, HTML 특수 문자를 이스케이프하여 스크립트로 실행되지 않도록 한다.
JavaScript, HTML, URL에 대해 적절한 이스케이프 처리 사용.
// Spring에서 XSS 방지를 위한 데이터 이스케이프
import org.springframework.web.util.HtmlUtils;
// 사용자 입력 이스케이프 처리
String safeInput = HtmlUtils.htmlEscape(userInput);
// HTML에서의 사용
model.addAttribute("safeContent", safeInput);
HTML 스크립트 생성에 사용되는 문자열을 <(<) >(>) &(&) "(\)같은 형태로 변경 replaceAll()