1. Description
http://3.37.8.189:5580(현재 접속 불가)
2. Write up
해당 문제는 문제 파일과 함께 접속 정보만 있다. 문제 페이지에 접속하면 위와 같은 페이지가 나오는데 웹 서비스의 기능은 크게 계정 등록, 로그인 두개만 존재한다.
웹 페이지의 동작 과정을 확인하기 위해서 계정을 등록하고 로그인을 시도했다.
•
ID : sugiri PW : sugiri
register 페이지에서 입력한 ID와 PW로 로그인을 시도한 결과 wrong password 문구가 나오는 것을 확인했다. 다른 ID, PW를 기반으로 다시 테스트해본 결과 동일한 결과가 나왔다.
문제에서 제공한 압축 파일을 해제하면 위와 같은 구조로 파일이 나오는 것을 확인할 수 있다. html 폴더와 같은 경로에 flag 파일이 있음을 확인할 수 있고 소스 코드들을 모두 확인해보면 flag값을 읽어오는 부분은 존재하지 않는다.
우선적으로 ID와 PW를 정상적으로 생성해도 로그인이 되지 않는 login.php를 분석했다. 함수 이름을 봤을 때 아래와 같이 검증하고 있다.
•
ID 또는 PW가 존재하지 않으면 invalid input 출력
•
ID 값 검증이 제대로 되지 않는 경우 invalid id 출력
•
ID가 존재하지 않는 경우 not found user 출력
•
ID와 PW를 체크하여 제대로 인증이 되지 않는 경우 wrong password 출력
두번째로 아이디를 등록하는 register.php를 분석했다. 함수 이름을 봤을 때 아래와 같이 검증하고 있다.
•
ID 또는 PW가 존재하지 않으면 invalid input 출력
•
ID 값 검증이 제대로 되지 않는 경우 invalid id 출력
•
ID가 존재하는 경우 already joined 출력
•
위 3개의 검증 로직을 다 수행 후 ID, PW 등록
ID, PW와 관련된 함수는 util.lib.php 에 정의되어 있다. 그 중에서 눈에 띄는 부분은 save_user_id() 함수이다. 일반적으로 ID와 PW는 데이터베이스에 저장하지만 해당 코드를 보면 html/dbs 경로 밑에 ID 이름으로 파일를 만들고 PW를 저장한다. 그리고 loginn_check() 함수에서 file_exists() 함수를 통해 ID파일을 검증하고 그 안에 있는 PW를 기반으로 로그인을 체크한다.
위 그림을 보면 board와 action 파라미터를 기반으로 동작하는데 이때 정규표현식으로 board 파라미터만 검증하고 action 파라미터는 검증하지 않는다.
process()함수를 보면 board와 action 파라미터를 기반으로 경로를 만들고 경로안에 php와 html문자열이 있는지 검증하여 있으면 해당 php 파일을 메인 페이지에 include한다.
// controller.lib.php
function __construct($board, $action) {
$this->board = $board;
$this->action = $action;
if(!preg_match('/^[a-z0-9:.]+$/i', $this->board)){
$this->board = 'main';
$this->action = 'index';
}
}
function process() {
$path = "{$this->board}/{$this->action}";
if(preg_match('/php|html/i', $path)){
alert('not invalid', 'back');
}
chdir('pages/');
if(!file_exists("{$path}.php")) $path = 'main/index';
include("{$path}.php");
}
// util.lib.php
function is_valid_id($str){
if(strlen($str) > 12 || preg_match('/[^a-z0-9._]/i', $str))
return false;
else
return true;
}
PHP
복사
controller.lib.php 파일을 보면 아이디 검증을 하는 함수가 있는데 문자열이 12보다 작거나 영어소문자, 숫자, 점(.), 언더바(_)가 있으면 아이디를 생성해준다. 위의 action 파라미터에서 검증하지 않는 것을 활용해서 ID를 생성할 때 .php 형태로 생성해준 뒤 PW에 flag 파일을 읽어오는 php 코드를 작성한다. 그 후 action 파라미터를 검증하지 않는 취약점을 악용하여 악성 ID 파일을 include 시킨다.
ID에 php 확장자를 붙여주고 패스워드에 file_get_contents()함수를 이용해서 플래그를 읽어오는 코드를 작성한다.
ID : exploitt.php
PW : <?php file_get_contents("../../flag"); ?>
그 후 action 파라미터에 ID 경로를 입력해서 접속을 시도하면 플래그를 확인할 수 있다.
URL : http://3.37.8.189:5580/?b=register&a=../../dbs/exploitt
3. FLAG
cce2022{fcaf4b99ec7413f8786e31f9194d1e05e856a63615ea9a50c6d00920e92ef1656c761668441168a4517f0e615af7394ee55e46ecf55b8a0b3cd94147}