풀이
- 승리조건 확인
| |
- 뽑은 값과 결과값 동일해야 승리: 아래와 같이 결과값 결정
| |
ticket이 없을 때 draw: 새로운 티켓 형성한 뒤
ticket이름으로 쿠키값 저장result.php에서 결과값 비교
목표: 내가 뽑은 값과 result.php가 뽑을 값을 같게 만들기
그러나 서버 draw는 랜덤 -> 값을 예측해서 맞추는 건 불가능
통제 가능한 건 쿠키(직렬화된 Ticket 객체) -> 값뿐 아니라 numbers와 results의 관계까지 내가 설계 가능
PHP 직렬화는 참조(reference)도 표현함 ->
R:n- numbers를 results의 참조로 만들면 둘이 같은 배열 하나를 가리킴
서버가
$ticket->results[$i] = $results[$i]로 draw를 쓰는 순간 numbers도 같이 바뀜- 비교되는 두 대상이 물리적으로 동일 -> 서버가 뭘 뽑든 항상 일치
페이로드 생성 (로컬 php 없으면 docker
php:8.1-cli)1 2 3 4$t = new Ticket(); $t->results = [1,2,3,4,5,6]; $t->numbers = &$t->results; // numbers를 results의 참조로 echo base64_encode(serialize($t));이 base64를
ticket쿠키 값으로 넣고 result.php 요청- 서버가 unserialize하며 참조 관계까지 복원 -> numbers와 results가 서버 안에서 같은 배열 공유
- flag: DH{91dff778784975c68312aef0ffcb1c44782da5664d9ea8369d3b70b87fb97214}
배운 점
- 직렬화/serialize(): 메모리 속 객체를 문자열로 누른 다음, 나중에 다시 객체로 되살릴 수 있게 만들기
- base64: 문자열을 안전한 문자로 포장
- 보낼 때: 객체 → serialize() → 문자열 → base64_encode → 쿠키
- 받을 때: 쿠키 → base64_decode → 문자열 → unserialize() → 객체