Mass Assignment 취약점 (WEB-55)

WEB-55 Mass Assignment

Mass Assignment 취약점:
프로그래밍 프레임워크에서 사용자 입력을 자동으로 모델의 모든 필드에 바인딩할 때, 공격자가 role, is_admin, permissions 같은 민감한 필드를 직접 조작할 수 있습니다. 웹 폼에 없는 필드라도 POST 파라미터로 전송하면 변조됩니다.

공격 시나리오

  1. 정상 폼: username, email만 업데이트 가능하도록 설계
  2. 폼 HTML 분석: 공격자가 다른 필드 (role, is_admin)가 없음을 확인
  3. 수동 POST 요청: Burp Suite나 curl로 직접 POST 데이터 조작
  4. 필드 추가: role=admin, is_admin=1 같은 필드 추가
  5. 서버 처리: 취약한 서버가 모든 필드를 업데이트
  6. 결과: 일반 사용자가 관리자 권한 획득

현재 사용자 (ID: 1)

필드 민감도
ID 1 높음
Username user1 낮음 (변경 가능)
Email user1@example.com 낮음 (변경 가능)
Role user 매우 높음! (변경 불가)
Is Admin 일반 사용자 매우 높음! (변경 불가)
Permissions read 높음! (변경 불가)

프로필 업데이트 (취약한 구현)

공격 방법 (curl 예시)

// 정상 요청 (role 필드 없음)
curl -X POST https://app.example.com/profile \
  -d "username=attacker&email=attacker@example.com"

// 공격 요청 (role, is_admin 필드 추가)
curl -X POST https://app.example.com/profile \
  -d "username=attacker&
      email=attacker@example.com&
      role=admin&
      is_admin=1&
      permissions=read,write,delete"

// 결과: 일반 사용자가 관리자가 됨!

안전한 구현

// 방법 1: 화이트리스트 (권장)
$allowed_fields = ['username', 'email'];
$update_data = [];
foreach ($allowed_fields as $field) {
  if (isset($_POST[$field])) {
    $update_data[$field] = $_POST[$field];
  }
}
User::update($user_id, $update_data);

// 방법 2: 명시적 할당
$user->username = $_POST['username'];
$user->email = $_POST['email'];
// role, is_admin은 할당하지 않음
$user->save();

// 방법 3: Fillable 설정 (Laravel)
protected $fillable = ['username', 'email'];
// role, is_admin은 제외