XSS, CSRF, SQL Injection 개념 및 방어 기법
1. XSS (Cross-Site Scripting)(사이트 간 스크립팅)
개념
XSS는 공격자가 웹 사이트에 악성 클라이언트 측 스크립트를 삽입하여 다른 사용자의 브라우저에서 실행되게 하는 공격 기법입니다. 이 공격이 성공하면 공격자는 사용자의 쿠키나 세션 토큰을 탈취하거나, 웹 페이지를 변조하거나, 악성 코드를 실행할 수 있습니다.
XSS 유형
- 저장형(Stored) XSS: 악성 스크립트가 서버에 영구적으로 저장되어 해당 페이지를 방문하는 모든 사용자에게 영향
- 반사형(Reflected) XSS: URL 파라미터 등을 통해 전달된 악성 스크립트가 즉시 페이지에 반영
- DOM 기반 XSS: 클라이언트 측 JavaScript가 DOM을 안전하지 않게 조작할 때 발생
방어 기법
- 입력 검증과 출력 인코딩
// 잘못된 방식 String userInput = request.getParameter("comment"); response.getWriter().println("<div>" + userInput + "</div>"); // 올바른 방식 String userInput = request.getParameter("comment"); String safeInput = StringEscapeUtils.escapeHtml4(userInput); response.getWriter().println("<div>" + safeInput + "</div>");
- 콘텐츠 보안 정책(CSP) 설정
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com
- HttpOnly 쿠키 사용: 클라이언트 측 스크립트가 쿠키에 접근할 수 없게 함
Cookie cookie = new Cookie("sessionId", "abc123"); cookie.setHttpOnly(true); response.addCookie(cookie);
- 프레임워크의 보안 기능 활용
- Spring MVC의
th:text
나 React의 ``와 같은 자동 이스케이프 기능 사용
- Spring MVC의
2. CSRF (Cross-Site Request Forgery)(사이트 간 요청 위조)
개념
CSRF는 인증된 사용자가 의도하지 않은 요청을 서버에 보내도록 속이는 공격입니다. 사용자가 로그인한 상태에서 악성 웹사이트를 방문했을 때, 브라우저에 저장된 쿠키를 이용해 사용자 모르게 서버에 요청을 보내게 됩니다.
방어 기법
- CSRF 토큰 사용
// 서버 측 토큰 생성 String csrfToken = UUID.randomUUID().toString(); session.setAttribute("csrfToken", csrfToken); // 뷰에 토큰 포함 model.addAttribute("csrfToken", csrfToken); // 요청 시 토큰 검증 String receivedToken = request.getParameter("csrfToken"); String expectedToken = (String) session.getAttribute("csrfToken"); if (receivedToken == null || !receivedToken.equals(expectedToken)) { throw new ForbiddenException("CSRF 토큰이 유효하지 않습니다."); }
- SameSite 쿠키 속성 사용
Cookie cookie = new Cookie("sessionId", "abc123"); cookie.setAttribute("SameSite", "Strict"); // 또는 "Lax" response.addCookie(cookie);
- Referer 검증
String referer = request.getHeader("Referer"); if (referer == null || !referer.startsWith("https://mywebsite.com")) { throw new ForbiddenException("올바르지 않은 출처입니다."); }
- Double Submit Cookie: 쿠키와 요청 파라미터로 동일한 값을 전송하고 서버에서 일치 여부 확인
3. SQL Injection (SQL 삽입)
개념
SQL Injection은 악의적인 SQL 쿼리를 입력하여 데이터베이스를 조작하는 공격 기법입니다. 이 공격으로 데이터 유출, 수정, 삭제는 물론 서버 명령어 실행까지 가능할 수 있습니다.
위 그림에서 보면 쿼리가 데이터베이스 테이블에서 일치하는 ID를 검색했다면, 이제 쿼리는 ID를 찾거나 1이 1과 같은지 테스트합니다. 예상할 수 있듯이 이 문은 열에 있는 모든 선생님에 대해 항상 참이므로, 그 결과 데이터베이스는 선생님 테이블의 모든 데이터를 쿼리를 수행한 공격자에게 반환합니다.
-- 또다른 예시
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
-- 공격자 입력: username = "admin' --"
-- 결과 쿼리: SELECT * FROM users WHERE username = 'admin' --' AND password = ''
-- '--' 이후는 주석 처리되어 비밀번호 확인 없이 로그인 가능
방어 기법
- 파라미터화된 쿼리(Prepared Statements) 사용
String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1, username); statement.setString(2, password); ResultSet resultSet = statement.executeQuery();
- ORM 프레임워크 활용
// JPA/Hibernate 예시 User user = entityManager .createQuery("from User where username = :username and password = :password", User.class) .setParameter("username", username) .setParameter("password", password) .getSingleResult();
- 입력 값 검증 및 이스케이프
// 특수 문자 이스케이프 String safeInput = input.replaceAll("'", "''");
- 최소 권한 원칙 적용: 데이터베이스 사용자에게 필요한 최소한의 권한만 부여
4. 통합 방어 전략
- 입력 데이터 검증: 모든 사용자 입력은 서버와 클라이언트 양쪽에서 검증
if (!Pattern.matches("[a-zA-Z0-9]{1,20}", username)) { throw new ValidationException("유효하지 않은 사용자명"); }
- 보안 헤더 설정
response.setHeader("X-XSS-Protection", "1; mode=block"); response.setHeader("X-Content-Type-Options", "nosniff"); response.setHeader("X-Frame-Options", "DENY");
-
웹 애플리케이션 방화벽(WAF) 사용: 일반적인 공격 패턴 차단
- 에러 처리: 상세한 오류 정보를 외부에 노출하지 않음
try { // 데이터베이스 작업 } catch (SQLException e) { logger.error("데이터베이스 오류: ", e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "서버 오류가 발생했습니다."); }
Leave a comment