Mass Assignment란 무엇인가
Mass Assignment는 사용자가 보낸 요청 데이터를 검증 없이 객체나 모델에 한꺼번에 바인딩할 때 발생하는 취약점입니다. 많은 웹 프레임워크는 개발 편의를 위해 요청 파라미터를 모델 필드에 자동으로 매핑해주는 기능을 제공합니다. 예를 들어 Ruby on Rails, Spring, Laravel 같은 프레임워크는 폼 데이터를 객체에 자동으로 채워 넣어줍니다. 문제는 이 과정에서 개발자가 의도하지 않은 필드까지 사용자가 임의로 값을 지정해 변경할 수 있다는 점입니다.
예를 들어 회원가입 API가 name, email, password 필드만 받도록 설계되었다고 가정해봅시다. 하지만 실제 User 모델에는 isAdmin이라는 필드도 존재합니다. 만약 서버가 요청 바디를 검증 없이 그대로 모델에 매핑한다면, 공격자는 요청에 isAdmin: true를 추가로 넣어 보낼 수 있습니다. 서버는 이를 걸러내지 못하고 그대로 반영해버려, 일반 사용자가 관리자 권한을 획득하는 심각한 보안 사고로 이어질 수 있습니다.
동작 원리와 실제 예시
이 취약점을 이해하려면 ‘우편함에 넣은 편지를 그대로 집 안에 배달하는 시스템’을 떠올리면 쉽습니다. 원래는 편지 내용만 전달해야 하는데, 봉투에 ‘이 집 열쇠도 같이 바꿔주세요’라는 메모를 몰래 넣으면 그대로 실행되는 셈입니다. 서버가 요청 데이터의 ‘봉투 안 내용’을 하나하나 검사하지 않고 통째로 믿어버리기 때문에 발생하는 문제입니다.
실제 코드에서는 다음과 같은 상황에서 자주 나타납니다.
- ORM에서 update(req.body)처럼 요청 객체 전체를 그대로 저장 로직에 전달하는 경우
- DTO(Data Transfer Object) 없이 Entity를 그대로 요청 바인딩에 사용하는 경우
- 화이트리스트 없이 모든 필드를 허용하는 설정을 그대로 사용하는 경우
예를 들어 Node.js에서 User.update(req.body)를 그대로 실행하면, req.body에 role: ‘admin’이 포함되어 있어도 그대로 반영됩니다. 반면 User.update({ name: req.body.name, email: req.body.email })처럼 필요한 필드만 명시적으로 추출하면 공격을 막을 수 있습니다.
실무에서의 방어 전략
실무에서는 이 취약점을 막기 위해 몇 가지 원칙을 지킵니다. 첫째, 화이트리스트 방식으로 허용된 필드만 명시적으로 매핑합니다. 둘째, 요청 전용 DTO를 별도로 정의해 내부 모델과 분리합니다. 셋째, Rails의 strong parameters나 Spring의 ‘@JsonIgnore’, DTO 검증 라이브러리 등 프레임워크가 제공하는 보호 기능을 적극 활용합니다.
결국 Mass Assignment 방어의 핵심은 ‘클라이언트가 보낸 데이터를 그대로 믿지 않는다’는 원칙입니다. 편의성과 보안은 항상 트레이드오프 관계에 있으므로, 자동 바인딩 기능을 사용할 때는 반드시 어떤 필드까지 노출되는지 점검하는 습관이 필요합니다.