본문 바로가기
일반IT/IT보안

🔐 내 정보는 내가 지킨다! URL 파라미터 대신 세션을 사용해야 하는 이유 (IDOR 취약점)

by gasbugs 2025. 10. 4.

안녕하세요, 개발자 여러분! 오늘은 웹 애플리케이션에서 정말 흔하게 발견되지만, 한번 터지면 걷잡을 수 없는 보안 취약점과 그 해결 방법에 대해 이야기해보려고 합니다. 👨‍💻

 

최근 코드 리뷰를 하다가 다음과 같은 수정 사항을 발견했다고 상상해 보세요.

// 수정 전 (Before) 👎
// const { userId } = req.params;

// 수정 후 (After) 👍
const { userId } = req.session;

 

단 한 줄의 변화. 하지만 이 작은 차이가 여러분의 서비스를 지옥에서 구해낼 수도 있습니다. "이게 왜 더 안전한 건가요?"라는 질문에 명쾌한 해답을 얻고 싶다면, 이 글을 끝까지 주목해주세요! 🚀

 


🤔 문제의 시작: URL에서 사용자 ID를 가져온다고?

먼저, 문제가 되는 기존 코드를 살펴보겠습니다.

// 안전하지 않은 방식
const {
    userId
} = req.params;

allocationsDAO.getByUserIdAndThreshold(userId, threshold, (err, allocations) => {
    // ... 유저 ID로 데이터를 조회해서 결과를 보여줌
});

 

이 코드는 URL 경로에 포함된 값 (req.params)에서 userId를 직접 가져와 사용하고 있습니다. 예를 들어, 사용자가 https://my-service.com/allocations/user123 이라는 주소로 접속했다면, 서버는 userId를 'user123'으로 인식하고 해당 유저의 데이터를 조회하게 됩니다.

 

겉보기엔 아무 문제 없어 보이죠? 하지만 여기에 아주 무서운 함정이 숨어있습니다.

만약 제가 악의적인 사용자 'hacker'이고, 제 ID가 'user456'이라고 가정해봅시다. 제 할당 정보를 보기 위해 https://my-service.com/allocations/user456으로 접속했겠죠. 그런데 문득 이런 생각이 듭니다.

"어라? URL 끝에 있는 ID만 바꾸면 다른 사람 정보도 볼 수 있지 않을까?"

그래서 주소창에 https://my-service.com/allocations/user123 이라고 입력하고 엔터를 누릅니다. 만약 서버가 아무런 권한 확인을 하지 않는다면... 끔찍하게도 'user123'의 정보가 제 눈앞에 펼쳐지게 됩니다! 😱

 

이것이 바로 OWASP Top 10에도 단골로 등장하는 안전하지 않은 직접 객체 참조 (Insecure Direct Object Reference, IDOR) 취약점입니다. 마치 아파트 동 호수만 알면 남의 집 문을 마음대로 열고 들어가는 것과 같은 상황이죠.


✨ 완벽한 해결책: 신뢰할 수 있는 정보는 '세션'에 있다!

그렇다면 제공해주신 수정된 코드는 이 문제를 어떻게 해결했을까요?

// Fix for A4 Insecure DOR -  take user id from session instead of from URL param
const { userId } = req.session;

allocationsDAO.getByUserIdAndThreshold(userId, threshold, (err, allocations) => {
    // ... 유저 ID로 데이터를 조회해서 결과를 보여줌
});

 

정답은 바로 req.session을 사용하는 것입니다!

  • req.params (URL 파라미터): 사용자가 브라우저 주소창에서 얼마든지 조작할 수 있는 값입니다. 절대 신뢰해서는 안 되는 외부 입력값이죠.
  • req.session (세션): 사용자가 로그인을 성공했을 때, 서버가 "이 사용자는 인증된 OOO입니다"라고 서버 내부에 저장하고 보증하는 정보입니다. 사용자는 이 세션 정보를 직접 수정할 수 없습니다. 마치 정부가 발급한 위조 불가능한 신분증과도 같습니다. 

새로운 코드는 URL에 뭐라고 적혀있든 상관하지 않습니다. 대신, 서버에 저장된 현재 로그인한 사용자의 세션 정보에서 userId를 가져옵니다.

 

따라서, 제가 'user456'으로 로그인한 상태에서 교묘하게 URL을 .../allocations/user123으로 바꿔서 요청하더라도, 서버는 이렇게 동작합니다.

  1. "어, 'user456' 사용자가 요청을 보냈네." (쿠키를 통해 세션 확인)
  2. "코드에서 req.session.userId를 쓰라고 했으니, 'user456'을 userId 변수에 할당해야겠다."
  3. "결과적으로 'user456'의 데이터를 조회해서 보여줘야지."

결국 저는 다른 사람의 정보는 절대 볼 수 없고, 오직 제 정보만 확인할 수 있게 됩니다. IDOR 취약점이 완벽하게 방어된 것이죠! 🛡️


🎯 결론: 당신의 코드는 안전한가요?

오늘 살펴본 코드 변경 사항에 대한 답변은 명확합니다.

네, URL 파라미터(req.params) 대신 세션(req.session)에서 사용자 식별자를 가져오도록 수정한 것은 보안을 대폭 강화하는 매우 올바르고 중요한 조치입니다. 👍

 

이 작은 변화는 사용자 데이터 접근에 대한 권한 부여(Authorization)를 올바르게 구현하는 핵심적인 단계입니다. 항상 기억하세요. "사용자로부터 오는 모든 입력은 잠재적인 위협이다." 특히 사용자의 신원을 확인하고 권한을 제어할 때는, 절대 사용자가 조작 가능한 값을 믿지 말고, 서버가 통제하는 신뢰할 수 있는 정보(세션)를 사용해야 합니다.

 

지금 바로 여러분의 코드를 점검해보세요. 혹시 중요한 데이터를 조회할 때 URL의 값을 그대로 사용하고 있지는 않나요? 😉

 

태그: 보안, 웹보안, Nodejs, Express, IDOR, 안전하지 않은 직접 객체 참조, 세션, 인증, 권한, 개발, 코딩