Tiny Bunny

Study/AWS 취약점 진단

취약점 점검 (4)

bento 2023. 12. 30. 23:21

WEB

 

5.

  취약 여부 항목 중요도 항목 코드
크로스사이트 리퀘스트 변조(CSRF) 취약 CF

 

취약점 설명

사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹 사이트에 요청하게 하는 공격

 

보안 위협

사용자의 신뢰(인증) 정보 내에서 사용자의 요청(Request)을 변조함으로써 해당 사용자의 권한으로 악의적인 공격 수행 가능

 

점검

데이터 수정 페이지에서 전송되는 요청 정보를 분석하여 임의의 명령을 수행하는 스크립트 삽입 후 해당 게시글을 타 사용자가 열람하였을 경우 스크립트가 실행되는지 확인

 

img 태그를 이용한 스크립트

  • 글 작성 
<img src="#" onmouseover="location.href='http://43.200.169.96:8080/board/writeAction.jsp?boardTitle=ABCD&boardContent=fool&boardFile=';">
<img src="#" onmouseover="location.href='https://zrr.kr/flsU';"> - url 단축

csrf 스크립트 삽입

csrf 스크립트 삽입 확인

csrf 스크립트 작동 확인

csrf 스크립트로 작성된 게시글 

 

  • 정보 수정
- <img src="#" onmouseover="location.href='http://43.200.169.96:8080/user/editAction.jsp?userPassword=fool&userName=fool&userPhone=00011111111&userEmail=fool@mail.com&userAge=1&userAddress=';">
- <img src="#" onmouseover="location.href='https://zrr.kr/G4eE';">- url 단축

기존 회원 정보

csrf 스크립트 삽입

csrf 스크립트 확인

csrf 스크립트 작동 확인

csrf 스크립트로 변경된 회원 정보

 

조치

csrf 토큰 삽입

 

공격 방지 코드의 예

write.jsp

<%@ page import="java.util.UUID" %>

<body>
    <%
        request.setCharacterEncoding("UTF-8");

        if (userId == null) {
            response.sendRedirect("../user/login.jsp");
            return;
        }
    
        String csrfToken = UUID.randomUUID().toString();
        session.setAttribute("csrfToken", csrfToken);
    %>
    <div class="forms">
        <form method="POST" action="writeAction.jsp" enctype="multipart/form-data">
            <input type="hidden" name="csrfToken" value="<%=csrfToken%>">
            <div class="mb-3">
                <input class="form-control border-dark" type="text" placeholder="제목을 입력하세요" max-length="50" name="boardTitle">
            </div>

            ...

        </form>
    </div>
</body>

 

board/writeAction.jsp

<%
    request.setCharacterEncoding("UTF-8");

    String directory = application.getRealPath("files/");
    int maxSize = 1024 * 1024 * 100;
    String encoding = "UTF-8";

    MultipartRequest multipartRequest = new MultipartRequest(request, directory, maxSize, encoding, new DefaultFileRenamePolicy());

    String userId = (String) session.getAttribute("userId");
    String boardTitle = multipartRequest.getParameter("boardTitle");
    String boardContent = multipartRequest.getParameter("boardContent");
    String fileName = multipartRequest.getOriginalFileName("boardFile");
    String fileRealName = multipartRequest.getFilesystemName("boardFile");

    String userCSRFToken = multipartRequest.getParameter("csrfToken");
    String sessionCSRFToken = (String) session.getAttribute("csrfToken");

    if (userCSRFToken == null || !userCSRFToken.equals(sessionCSRFToken)) {
        PrintWriter script = response.getWriter();
        script.println("<script>");
        script.println("alert('잘못된 접근입니다.');");
        script.println("history.back();");
        script.println("</script>");
        script.close();
        return;
    }

    ...

%>

 

profile.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="user.userDTO"%>
<%@ page import="user.userDAO"%>
<%@ include file="../layout/header.jsp"%>
<%@ page import="java.util.UUID" %>

<html>
<head>
    <title>Edit Profile</title>
    <link rel="stylesheet" type="text/css" href="../css/user/profile.css">
</head>
<body>
    <%
        request.setCharacterEncoding("UTF-8");

        if (userId == null) {
            response.sendRedirect("login.jsp");
            return;
        }

    String userCSRFToken = UUID.randomUUID().toString();
    session.setAttribute("sessionCSRFToken", userCSRFToken);

        userDAO userDao = new userDAO();
        userDTO userDto = userDao.userInfo(userId);
    %>
    <div class="form-profile">
        <h2 class="mb-5">회원 정보</h2>
        <form method="post">
					<input type="hidden" name="csrfToken" value="<%=userCSRFToken%>">
            <div class="mb-3 row justify-content-between">
                <label for="staticId" class="col-auto col-form-label">* 아이디</label>
                
                ...
                
            <div class="button-container">
                <button type="submit" class="btn btn-outline-dark btn-sm" formaction="updateAction.jsp">수정 완료</button>
                <button type="submit" class="btn btn-outline-dark btn-sm" formaction="deleteAction.jsp">회원 탈퇴</button>
            </div>
        </form>
    </div>
</body>
</html>

 

updateAction.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="user.userDTO"%>
<%@ page import="user.userDAO"%>
<%@ page import="java.io.PrintWriter"%>
<%
    request.setCharacterEncoding("UTF-8");

    String userId = (String) session.getAttribute("userId");
    String userPassword = request.getParameter("userPassword");
    String userName = request.getParameter("userName");
    String userPhone = request.getParameter("userPhone");
    String userEmail = request.getParameter("userEmail");
    String userAgeStr = request.getParameter("userAge");
    int userAge;
    String userAddress = request.getParameter("userAddress");

    String sessionCSRFToken = (String) session.getAttribute("sessionCSRFToken");
    String userCSRFToken = request.getParameter("csrfToken");

    if (userCSRFToken == null || !userCSRFToken.equals(sessionCSRFToken)) {
        PrintWriter script = response.getWriter();
        script.println("<script>");
        script.println("alert('잘못된 접근입니다.');");
        script.println("history.back();");
        script.println("</script>");
        script.close();
        return;
    }
    if (userPassword.isEmpty() || userPassword == null) {
        PrintWriter script = response.getWriter();
        script.println("<script>");
        script.println("alert('비밀번호를 입력해주세요.');");
        script.println("history.back();");
        script.println("</script>");
        script.close();
        return;
    }
    
    ...
    
    if (result == 1) {
        PrintWriter script = response.getWriter();
        script.println("<script>");
        script.println("alert('수정을 완료하였습니다.');");
        script.println("history.back();");
        script.println("</script>");
        script.close();
        return;
    } else {
        PrintWriter script = response.getWriter();
        script.println("<script>");
        script.println("alert('프로필 업데이트에 실패하였습니다.');");
        script.println("history.back();");
        script.println("</script>");
        script.close();
    }
%>
728x90

'Study > AWS 취약점 진단' 카테고리의 다른 글

최종 보고서  (0) 2024.05.13
취약점 점검 (5)  (0) 2023.12.30
취약점 점검 (3)  (0) 2023.12.30
취약점 점검 (2)  (0) 2023.12.30
취약점 점검 (1)  (0) 2023.12.30