https://dreamhack.io/wargame/challenges/413
Command Injection Advanced
Description Exercise: Command Injection Advanced에서 실습하는 문제입니다. 문제 수정 내역 2023.07.27 Dockerfile 제공
dreamhack.io
[1] 문제 분석
# 웹 페이지 분석
URL을 제출할 수 있는 형식의 폼이 있는 페이지이다.
<html>
<head></head>
<link rel="stylesheet" href="/static/bulma.min.css" />
<body>
<div class="container card">
<div class="card-content">
<h1 class="title">Online Curl Request</h1>
<form>
<div class="field">
<label class="label">URL</label>
<input class="input" type="text" placeholder="url" name="url" required>
</div>
<div class="control">
<input class="button is-success" type="submit" value="submit">
</div>
</form>
</div>
</div>
</body>
</html>
"url" 이라는 이름의 파라미터로 내가 입력한 값이 받아져서 전송이 되는 구조임을 알 수 있다.
.
.
.
여기까지는 알 수 있는 게 없어서 바로 다운로드한 파일을 분석해보겠다.
# 다운로드한 파일 분석
⚙️ index.php
<html>
<head></head>
<link rel="stylesheet" href="/static/bulma.min.css" />
<body>
<div class="container card">
<div class="card-content">
<h1 class="title">Online Curl Request</h1>
<?php
if(isset($_GET['url'])){
$url = $_GET['url'];
if(strpos($url, 'http') !== 0 ){
die('http only !');
}else{
$result = shell_exec('curl '. escapeshellcmd($_GET['url']));
$cache_file = './cache/'.md5($url);
file_put_contents($cache_file, $result);
echo "<p>cache file: <a href='{$cache_file}'>{$cache_file}</a></p>";
echo '<pre>'. htmlentities($result) .'</pre>';
return;
}
}else{
?>
<form>
<div class="field">
<label class="label">URL</label>
<input class="input" type="text" placeholder="url" name="url" required>
</div>
<div class="control">
<input class="button is-success" type="submit" value="submit">
</div>
</form>
<?php
}
?>
</div>
</div>
</body>
</html>
<분석 내용>
1. 내가 URL을 제출했을 때 f(isset($_GET['url'])) 블록이 실행된다.
2. 제출된 URL이 'http'로 시작하는지 확인하고, 그렇지 않으면 오류 메시지를 표시하고 종료한다. (이상한 파일을 삽입하는 것에 대비하는 역할을 한다.)
3. shell_exec 함수를 사용하여 cURL 명령을 실행하고 escapeshellcmd 함수를 사용하여 메타문자를 받아들이지 않는다.
4. 결과는 $result 변수에 저장되고, 결과를 화면에 출력하면서 동시에 결과를 파일에 저장한다.
5. 결과를 cache 디렉토리 안에 저장하는데, 파일 이름은 해당 URL의 MD5 해시 값으로 생성된다.
6. 생성된 파일에 대한 링크를 페이지에 표시한다.
.
.
.
메타 문자 앞에 백슬래시(\)를 추가하여 이스케이프 시키는 함수때문에,
어떻게 공격을 해야 하는지 방법이 떠오르지 않았다.
그래서 분석 이후에 공격 방법에 대해서는 다른 블로그의 풀이 글을 찾아보았다.
[2] 공격
escapeshellcmd 함수는 '-'문자를 이스케이프 하지 않으므로 명령어의 옵션과 인자를 조작할 수 있다.
문제 페이지 상단에 써져있는 "Online Curl Request"와, app.py에 사용된 curl 요청을 보면,
다양한 옵션들 중에 '-o' 명령을 사용해야 함을 알 수 있다.
PHP에서는 shell_exec 함수를 사용하여 커맨드 라인에서 cURL을 실행하고 그 결과를 가져올 수 있다.
.
.
.
이를 이용해서 curl의 인자를 받는 곳에 또 curl을 쓰고 -o옵션으로 파일을 생성하는 공격을 시도할 것이다.
그렇게 되면 두 번 curl이 실행되면서, 인자 안에서 실행되는 curl은 md5로 해싱되지 않을 것이다.
.
.
.
다른 사람 풀이 글에 올려져 있는 웹 셀을 만드는 방법을 참고해서,
깃허브 호스팅 서비스를 이용해 만든 내 서버에 웹 셀을 올려놓았다.
(깃허브 호스팅 서비스를 처음 이용해봐서 조금 헤맸다.)
이와 같이 익스플로잇 코드를 작성한다.
나의 웹 서버에 있는 test_curl.php를 -o 옵션으로 cache 디렉토리에 test_curl.php라는 이름으로 저장해달라는 코드이다.
(아파치의 기본적인 경로가 var/www/html인 점을 참고)
/cache/test_curl.php 경로로 가면 위와 같이 웹 쉘이 등장한다.
위와 같이 ls -al로 상세한 ls를 확인해보게 되면 잘 출력되는 것을 볼 수 있다.
flag는 파일로 되어있다고 했으니
/flag를 입력해서 flag를 실행시키고 flag를 얻을 수 있다.
문제 풀이 완료
!
[3] 참고
https://minseosavestheworld.tistory.com/156?category=1133576
[Dreamhack Wargame] Command Injection Advanced
PHP escapeshellcmd() 함수 우회 1. escapeshellcmd() 함수에 대해 - 메타 문자를 통한 커맨드 인젝션을 방지하기 위해 php에서 사용하는 함수 - 쉘 명령을 속이는 데 사용될 수 있는 문자열의 모든 문자를 이
minseosavestheworld.tistory.com
[WARGAME] 드림핵 워게임 - Command Injection Advanced
아래는 서버 코드이다.코드를 보면 1.shell_exec으로 먼저 curl을 디폴트로 실행시켜주는 것을 볼 수 있다.2.문자열에 http가 있는지 검사한다.3.이상한 파일을 삽입하는 것에 대비해 md5로 url을 해싱한
velog.io
[4] 느낀 점
학회 과제로 푼 문제인데, 좀 어렵다고 느꼈다.
escapeshellcmd 함수의 취약점에 대해 따로 공부한 적이 없었고, 서버에 웹 셀 코드를 짜서 올리는 것 또한 아직은 나 혼자서 떠올릴 수 없는 아이디어였다.
그렇지만, 나에게 어려운 문제라도 한 번 풀어보는 건 좋은 경험이다!
'Hacking (CTF) > 웹 해킹' 카테고리의 다른 글
[webhacking.kr] Challange 44 (1) | 2023.11.20 |
---|---|
[Dreamhack/드림핵] command-injection-1 (2) | 2023.11.20 |
[Dreamhack/드림핵] baby-linux (0) | 2023.11.16 |
[Dreamhack/드림핵] csrf-2 (1) | 2023.11.11 |
[Dreamhack/드림핵] csrf-1 (0) | 2023.11.10 |