개발 메모장

[보안] Ajax 요청에 대한 응답값 변조, 프록시 조작 및 우회 방지 본문

보안

[보안] Ajax 요청에 대한 응답값 변조, 프록시 조작 및 우회 방지

yyyyMMdd 2024. 12. 24. 16:21
728x90
  • 문자 인증 및 암호 인증 등을 통해 민감 정보를 수정 및 조회하는 경우가 많을 것 입니다.

  • 잘못된 접근 제어 방식으로 인하여 인증 우회 및 공격을 받기도 합니다.

  • 잘못된 방식에 대해서 살펴보고 어떻게 처리해야하는지도 알아보도록 하겠습니다.

#. 현 상황

 

  • 입력받은 PW 및 데이터를 Ajax를 통해 서버단으로 보낸 뒤 유효성 검사를 하고 통과가 되면 check라는 Key에 Y라는 값을 넣어 modelMap을 통해 리턴합니다. 통과되지 못할 경우 N을 넣어 리턴합니다.

  • ajax의 success 옵션에서 리턴 받은 데이터의 check라는 키의 값이 Y이면 성공처리 후 팝업을 열고, 아니면 실패처리를 하는 방식으로 되어있습니다.
@RequestMapping("/PwCheck.do")
public ModelMap pwCheck(@RequestParam Map<String, Object> param, ModelMap modelMap) {
    String pw = service.pwCheck(param);
    String paramPw = param.get("password").toString();
    String passSecurity = SHA2.encrypt(paramPw);
    passSecurity = SHA2.getSHA512(passSecurity);

    if(pw != null && pw.equals(passSecurity) ){
        return modelMap.addAttribute("check", "Y");
    } else {
        return modelMap.addAttribute("check", "N");		
    }
}

$("#test").on("click", ".btnSave", function(event) {		
    $.getJSON("/PwCheck.do", $("#test form").serialize(), function(returnData, textStatus){
        if(textStatus ==  "success"){
            if(returnData.check =="Y"){
                    $("#testPopup").popup({
                        loadUrl: "modify.do?UserNo=${user.id}", 
                        follow: [false, false],
                        position: ["auto", "200"]
                        , escClose: false
                    }); 
                    return false;
            } else {
                alert("비밀번호가 일치하지 않습니다.");
            }
        }
    }).error(alertErrorHandler);
    return false;
});
728x90

#. 프록시 변조 테스트

 

  • 위와 같은 로직이 적용된 기능을 대상으로 테스트해보도록 하겠습니다.

  • 프록시 변조를 위해 Burp Suite을 설치하여 사용하였습니다.

  • 상단 탭의 Proxy로 이동하여 Open browser로 크로미움을 열어줍니다.

  • 프록시 변조를 위한 인터셉트가 필요한 구간에선 Intercept is on으로 켜줍니다.


  • 암호를 변경하는 팝업을 열기 전 기존 암호를 입력하는 입력창입니다.

  • Intercept is on 상태에서 입력창에 1234를 입력 후 확인을 누릅니다.


  • 아래와 같이 인터셉트 되어 정보를 볼 수 있게 됩니다.


  • 보내야하는 URI를 확인 한 뒤 우클릭 하여 Do Intercept Response to this Request를 눌러줍니다.


  • 그 후 Forward를 해주면 이전 Request에 대한 Response 값을 인터셉트 할 수 있습니다.

  • 입력한 1234는 당연히 틀린 비밀번호이기 때문에 N으로 response 받습니다.


  • 하지만 N을 Y로 바꿀 수 있으며 이로 인해 우회가 가능하게 됩니다.

  • 수정 후 Forward를 해주어 기능을 종료합니다.


  • 개인정보 및 암호를 수정할 수 있는 팝업을 정상적으로 띄우는 모습입니다.


#. 처리방법

 

  • 단순히 생각하면 Ajax 요청 및 서버단에서 modelMap을 만들고 받지 않으면 됩니다.

  • 리턴 타입을 변경하여 아래와 같이 처리하였습니다.

  • ResponseEntity를 이용해 리턴하고 HTTP 상태값을 이용하여 리턴 받은 후 처리를 해주었습니다.
public ResponseEntity<?> pwCheck(@RequestParam Map<String, Object> param, HttpSession session) {
    String pw = userInfoService.pwCheck(param);
    String paramPw = param.get("password").toString();
    String passSecurity = SHA2.encrypt(paramPw);
    passSecurity = SHA2.getSHA512(passSecurity);

    if(pw != null && pw.equals(passSecurity) ){
        session.setAttribute("authenticated", true);
        return new ResponseEntity(null, HttpStatus.OK);
    } else {
        return new ResponseEntity(null, HttpStatus.UNAUTHORIZED);
    }
}
$("#test").on("click", ".btnSave", function (event) {
    event.preventDefault();

    const formData = $("#test form").serialize();

    $.ajax({
        type: "GET", 
        url: "/PwCheck.do",
        data: formData,
        dataType: "json",
        success: function (response) {
            $("#testPopup").popup({
                loadUrl: "modify.do?UserNo=${user.id}",
                follow: [false, false],
                position: ["auto", "200"],
                escClose: false,
            });
        },
        error: function (xhr) {
            if (xhr.status === 401) {
                alert("비밀번호가 일치하지 않습니다.");
            } else {
                alert("에러 발생");
            }
        },
    });
});

#. 수정 후 테스트

  • 위와 같이 수정한 후 동일하게 프록시 변조를 위해 인터셉트 하면 아래와 같이 나타나게 됩니다.

  • ModelMap에 담은 키값이 없으므로 나오질 않으며, 그렇기에 변조할 값도 없어 우회가 불가하게 됩니다.

  • 위 내용은 modelMap에 성공/실패값을 리턴하는 모든 메서드에서 뚫릴 수 있으니 찾아서 모두 변경해주어야 합니다.

  • 오래 전부터 사용하고 있던 소스이다보니 보안에 취약한 부분이 많이 있습니다.

  • 하나하나 전부 보기엔 여러가지로 한계가 있다보니 틈틈이 찾아보고 테스트해보고 개선될 수 있도록 해야할 것 같습니다.

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!

===========================================================

728x90