1. 진단 개요
앞선 게시글 수정·삭제 기능의 접근통제 진단에 이어, 이번에는 댓글 기능을 대상으로 IDOR 취약점 여부를 점검했다.
댓글 작성 요청의 구조를 확인하고, 인증된 사용자가 다른 사용자가 작성한 댓글을 임의로 삭제할 수 있는지 검증했다.
진단은 Burp Suite를 이용한 동적 분석을 먼저 수행한 후, Controller와 Service 소스코드를 분석하여 접근통제 구현 방식을 확인하는 순서로 진행했다.
| 항목 |
내용 |
| 진단 환경 | Spring Boot / MySQL / Docker |
| 진단 도구 | Burp Suite Repeater |
| 진단 대상 | 댓글 작성 및 삭제 기능 |
| 진단 유형 | IDOR / 접근통제 |
| 테스트 계정 | jcob, jcob2 |
2. 댓글 작성 요청 분석
먼저 jcob 계정으로 로그인한 후 게시글 33번에 댓글을 작성하고, Burp Suite에서 HTTP 요청을 확인했다.

POST /comments/new HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=[REDACTED]
_csrf=[REDACTED]&articleId=33&content=COMMENT-TEST-001
요청 본문에는 articleId, content, _csrf 파라미터가 포함되어 있었으며, 댓글 작성자를 직접 지정하는 userId 등의 파라미터는 존재하지 않았다.
따라서 해당 요청 구조에서는 단순히 작성자 ID를 변경하여 다른 사용자 명의로 댓글을 작성하는 방식의 취약점이 확인되지 않았다.
다만 요청 파라미터만으로 서버 측 작성자 식별 방식을 확정할 수 없으므로, 실제 인증정보 처리 방식은 이후 소스코드 분석에서 확인했다.
또한 다른 사용자의 게시글에 댓글을 작성하는 행위는 일반적인 게시판의 정상 기능이므로, 게시글 작성자가 다르다는 사실만으로 IDOR 취약점으로 판단하지 않았다.
댓글 작성 기능의 XSS 및 입력값 검증은 별도 진단에서 진행할 예정이다.
3. 타인 댓글 삭제 접근통제 진단
3.1 테스트 시나리오
jcob2 계정으로 게시글 33번에 테스트 댓글을 작성한 후, jcob 계정으로 로그인하여 해당 댓글을 삭제할 수 있는지 확인했다.
| 항목 |
내용 |
| 로그인 사용자 | jcob |
| 댓글 작성자 | jcob2 |
| 대상 게시글 | 33번 (jcob 소유) |
| 삭제 대상 댓글 | 1002번 (jcob2 소유) |
| 진단 방법 | 인증정보 유지 후 댓글 ID 변조 |
3.2 HTTP 요청 변조
먼저 jcob 계정에서 본인 댓글의 삭제 요청을 Burp Suite Proxy로 확인했다.
POST /comments/1001/delete HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=[REDACTED]
_csrf=[REDACTED]&articleId=33
삭제 요청은 URL 경로에 댓글 ID를 포함하고, 요청 본문에는 게시글 ID와 CSRF 토큰을 전달하는 구조였다.
이후 해당 요청을 Repeater로 전달하고 삭제 대상 댓글 ID를 1002번으로 변경했다.
[댓글 삭제 대상]

변경 전 — 본인 댓글 삭제 요청
POST /comments/1001/delete HTTP/1.1
변경 후 — 타인 댓글 삭제 요청
POST /comments/1002/delete HTTP/1.1

로그인 세션과 CSRF 토큰은 유지하고, 삭제 대상 댓글 ID만 변경하여 요청을 전송했다.
3.3 진단 결과
변조한 삭제 요청을 전송했으나, 대상인 1002번 댓글이 삭제되지 않는 것을 확인했다.



즉, 인증된 사용자가 다른 사용자의 댓글 ID를 지정하여 삭제를 시도했지만, 실제 삭제로 이어지지 않았다.
4. 소스코드 분석
동적 분석에서 타인 댓글 삭제가 차단된 원인을 확인하기 위해 댓글 관련 Controller와 Service 코드를 분석했다.
4.1 댓글 작성 기능 — Controller 분석
ArticleCommentController.java
@PostMapping("/new")
public String postNewArticleComment(
@AuthenticationPrincipal BoardPrincipal boardPrincipal,
ArticleCommentRequest articleCommentRequest
) {
articleCommentService.saveArticleComment(
articleCommentRequest.toDto(boardPrincipal.toDto())
);
return "redirect:/articles/" + articleCommentRequest.articleId();
}
댓글 작성 시 @AuthenticationPrincipal을 통해 현재 로그인한 사용자의 인증정보를 가져온다.
이후 인증된 사용자 정보를 DTO로 변환하여 Service에 전달한다.
따라서 정상적인 댓글 작성 경로에서는 클라이언트가 임의로 전달하는 사용자 ID가 아닌, 서버에서 확인된 인증정보를 기반으로 댓글 작성자를 식별하도록 구현되어 있다.
4.2 댓글 삭제 기능 — Controller 분석
ArticleCommentController.java
@PostMapping("/{commentId}/delete")
public String deleteArticleComment(
@PathVariable Long commentId,
@AuthenticationPrincipal BoardPrincipal boardPrincipal,
Long articleId
) {
articleCommentService.deleteArticleComment(
commentId,
boardPrincipal.getUsername()
);
return "redirect:/articles/" + articleId;
}
댓글 삭제 요청에서는 URL에 포함된 commentId와 현재 인증된 사용자의 ID를 Service로 전달한다.
articleCommentService.deleteArticleComment(
commentId,
boardPrincipal.getUsername()
);
즉, 클라이언트에서 댓글 ID를 변경할 수는 있지만, 삭제 요청에 사용되는 사용자 ID는 현재 로그인한 사용자의 인증정보를 기반으로 결정된다.
4.3 댓글 삭제 기능 — Service 분석
ArticleCommentService.java
public void deleteArticleComment(Long articleCommentId, String userId) {
articleCommentRepository.deleteByIdAndUserAccount_UserId(
articleCommentId, userId
);
}
실제 삭제 처리는 Spring Data JPA의 파생 쿼리 메서드를 사용한다.
deleteByIdAndUserAccount_UserId(articleCommentId, userId);
해당 메서드는 삭제할 댓글을 식별할 때 댓글 ID와 댓글 작성자 ID를 함께 조건으로 사용한다.
개념적으로 다음 조건을 적용하는 것과 같다.
DELETE FROM article_comment
WHERE id = :articleCommentId
AND user_id = :userId;
※ 실제 Hibernate가 생성한 SQL이 아니라 접근통제 조건을 설명하기 위한 예시다.
이번 테스트에서 대상 댓글인 1002번의 작성자는 jcob2였지만, 삭제 요청의 인증 사용자 ID는 jcob이었다.
따라서 댓글 ID가 일치하더라도 작성자 조건을 충족하지 못해 삭제 대상에 포함되지 않는 구조다.
이러한 접근통제 방식은 앞서 분석한 게시글 삭제 기능과 동일하다.
분석 결과, 댓글 삭제 기능은 인증된 사용자 ID를 삭제 조건에 포함하여 타인 댓글의 비인가 삭제를 방지하고 있었다.
5. 추가 확인 사항 — 댓글 수정 로직의 접근통제 누락 가능성
소스코드 분석 과정에서 실제 웹 화면에는 구현되지 않은 댓글 수정 메서드가 존재하는 것을 확인했다.
ArticleCommentService.java
public void updateArticleComment(ArticleCommentDto dto) {
try {
ArticleComment articleComment =
articleCommentRepository.getReferenceById(dto.id());
if (dto.content() != null) {
articleComment.setContent(dto.content());
}
} catch (EntityNotFoundException e) {
log.warn("댓글 업데이트 실패. 댓글을 찾을 수 없습니다 - dto: {}", dto);
}
}
해당 메서드는 댓글 ID를 기준으로 수정 대상을 조회하고, 전달된 내용으로 댓글을 변경한다.
하지만 삭제 메서드와 달리 댓글 작성자와 현재 인증된 사용자의 일치 여부를 검증하는 로직이 존재하지 않는다.
다만 현재 확인한 Controller에는 댓글 수정 요청을 처리하는 엔드포인트가 존재하지 않는다.
따라서 외부에서 해당 메서드를 호출할 수 있는 경로가 확인되지 않았으므로, 현 단계에서 실제 악용 가능한 IDOR 취약점으로 확정할 수는 없다.
향후 댓글 수정 기능을 구현할 경우 인증된 사용자와 댓글 작성자의 소유권을 확인하는 접근통제 로직을 추가해야 한다.
6. 진단 결과 종합
WEB-003 — 타인 댓글 삭제 접근통제 검증
| 항목 |
내용 |
| 진단 대상 | 댓글 삭제 기능 |
| 진단 URL | POST /comments/{commentId}/delete |
| 진단 유형 | IDOR / 접근통제 검증 |
| 테스트 사용자 | jcob |
| 대상 댓글 | 1002번 (jcob2 소유) |
| 진단 방법 | 인증정보 유지 후 댓글 ID 변조 |
| 삭제 결과 | 삭제되지 않음 (화면상 확인) |
| 소스코드 분석 | 댓글 ID 및 작성자 ID 조건 적용 |
| 최종 판정 | 양호 (DB 검증 미완료) |
진단 결론
인증된 사용자가 다른 사용자의 댓글 ID를 지정하여 삭제 요청을 전송했으나, 대상 댓글이 삭제되지 않는 것을 확인했다.
소스코드 분석 결과 댓글 ID와 인증된 사용자 ID를 함께 삭제 조건으로 사용하는 로직이 존재했으며, 동적 분석 결과와 일치했다.
따라서 이번 테스트에서는 타인 댓글 삭제로 이어지는 IDOR 취약점이 재현되지 않았다.
다만 권한 없는 삭제 요청에 대해 별도의 예외 처리 없이 리다이렉트하는 구조이므로, 명시적인 권한 거부 응답을 제공하도록 개선할 수 있다.
또한 댓글 수정 Service에는 소유권 검증이 존재하지 않아, 향후 수정 기능 구현 시 접근통제 적용이 필요하다.
7. 마무리
이번 진단에서는 댓글 작성 요청 구조를 분석하고, 다른 사용자가 작성한 댓글에 대한 삭제 권한을 검증했다.
Burp Suite에서 인증정보를 유지한 상태로 댓글 ID를 변조했으나 삭제가 이루어지지 않았으며, 소스코드 분석을 통해 댓글 ID와 사용자 ID를 함께 조건으로 사용하는 접근통제 로직을 확인했다.
또한 외부에 노출되지 않은 Service 메서드에서도 접근통제 누락 가능성을 발견했다.
이번 실습을 통해 동적 분석에서 확인된 결과를 소스코드와 연결하여 접근통제 구현 방식을 검증할 수 있었다.
다음 단계에서는 댓글 작성 및 출력 기능을 대상으로 Stored XSS 취약점을 분석할 예정이다.
'Web Hacking > Web Security Projects' 카테고리의 다른 글
| [웹 모의해킹 프로젝트 #02] Spring Boot 게시판 게시글 접근통제(IDOR) 취약점 진단 및 소스코드 분석 (0) | 2026.10.24 |
|---|---|
| [웹 모의해킹 프로젝트 #01] Spring Boot 게시판 Docker 환경 구축 및 초기 데이터 설정 (0) | 2026.10.24 |






























































































