진행한 업무 중 웹 취약점으로 평가되어 조치를 진행한 업무에 대해 간단히 기록하고자 합니다.
취약점 조치 방법
취약점 조치는 위험 수용, 위험 예외, 위험 조치 세 가지로 분리할 수 있고, 각각의 의미는 다음과 같습니다.
- 위험 수용 : 문제를 해결하지 않고 수용한다.
- 위험 예외 : 문제가 아닌 것으로 판단하고 예외 처리한다.
- 위험 조치 : 문제를 해결해서 취약점을 제거한다.
취약점으로 평가된 문제점은 XSS, 부적절한 오류 처리(톰캣 버전 노출), 매개변수 조작 문제 등이 있었습니다.
이를 조치하느냐 수용하느냐는 여러 상황(context) 아래에 판단을 할 수 있는데, 각 문제에 대한 risk값을 매기는 척도가 있습니다.
본인은 이 중 매개변수 조작 문제만 위험 조치로 판단하고 해결하는 것을 진행하였습니다.
(XSS는 내부 어드민 사이트에서 발생한 문제였고,
부적절한 오류 처리는 개발자들이 테스트했을 때 따로 톰캣 버전이 노출되지 않아서 재확인 요청드해리니 이미 해결된 문제였어서 위험 예외 처리하였습니다.)
매개변수 조작 문제점
총 세가지를 조치해야 했습니다. (본인이 주로 맡았던 2,3번에 집중해서 설명 예정)
- 관리자 리스트에서 비활동 회원 삭제 요청 시, 다른 활동 회원을 삭제하는 공격
- 게시글 등록 시 최초 등록자명을 사용자와 다른 이름으로 수정하는 공격
- 게시글 수정 시 이미 지정된 최초 등록자명을 다른 이름으로 수정하는 공격
Burp Suite 이라는 툴을 사용해 패킷을 바꾸는 공격을 하여 문제를 재현했습니다.
2,3번 문제를 재현하면서, body에 담긴 값들이 모두 인코딩된 것을 확인하였습니다.
POST로 요청시 프론트에서 지정된 인코딩 방식으로 body를 인코딩하여 전달하고 자동으로 디코딩되어 DTO로 변환해주는 것을 확인했고,
그렇기 때문에 일반 문자로는 수정이 먹히지 않았지만, 동일 방식으로의 인코딩한 문자로 수정해보니 변경되어 전달되는 문제가 여전히 발생하였습니다.
해결 과정
- 1번 문제
공격자에 의해 삭제 대상이 바뀐 경우 DB 조회를 통해 활동 중인 데이터는 삭제되지 않도록 조건문을 추가하였습니다.
- 2,3번 문제
로직 상에서 공격자에 의해 수정된 패킷인지를 검증하는 것을 추가했습니다.
이 때 등록의 경우 세션값을(등록 상황에서는 DB에 값이 없으므로),
수정의 경우 DB의 데이터를 이용하여 비교하는 방식을 제안했습니다.
(세션값에 대한 검증 로직을 필수적으로 거치기 때문에, 세션값은 신뢰성있다고 판단하였습니다.)
해결 방식
- 활동 중인 회원의 경우 삭제되지 않도록 조건문 추가
- 현재 로그인된 세션값에서 사용자명을 가져와서 최초 등록자명 인자(writerName)와 일치하는지 비교
- 다를 경우, 세션값의 사용자가 최초등록자가 되어야하므로, 세션값의 사용자로 재설정합니다.
- DB에 등록된 게시글의 최초 등록자명과 인자(writerName)가 일치하는지 비교
- 다를 경우, DB에서 조회한 데이터가 올바른 정보이므로, DB에서 조회한 데이터로 재설정합니다.
이렇게 함으로써, 공격을 받아도 이를 알리 없는 사용자에게는 사용자가 원했던 흐름 그대로 값이 설정되도록 하였습니다.
잘못된 부분은 댓글 부탁드립니다.