IXPLOIT 웹해킹 스터디 9주차 (1) Command injection & File-upload
dreamhack.io/lecture/courses/15
Server-side Basic
-
dreamhack.io
Command injection
- OS Command를 사용 시 사용자의 입력 데이터에 의해 실행되는 Command를 변조할 수 있는 취약점
Injection : 사용자의 입력 값이 어플리케이션의 처리 과정에서 구조나 문법적인 데이터로 해석돼 발생하는 취약점
- 변조된 입력을 주입해 의도하지 않은 행위를 발생시킴
- Command injection 외에 SQL injection, Server side template injection, Path Traversal이 있다.
OS Command : linux, windows 등의 OS에서 사용하는 명령어
linux | ls, pwd, ping, zip 등 ... |
windows | dir, pwd, ping 등 ... |
웹 어플리케이션에서는 OS Command를 실행하기 위해 PHP(system), Node js(child_process), Python(os.system)과 같은 함수가 존재한다.
웹 어플리케이션에서 OS Command를 사용하는 이유 : 이미 기능을 구현한 OS 실행 파일이 존재할 때 코드 상에서 다시 구현하지 않고 이를 실행하면 더 편리하기 때문
OS Command는 내부적으로 셸을 이용해 실행하는데, 셸은 사용자 편의성을 위해 한 줄에 여러 명령어를 실행하는 특수 문자가 여럿 존재한다.
OS Command를 사용할 때 사용자의 입력 값을 검증하지 않고 함수의 인자로 전달한다면 특수 문자를 이용해 사용자가 원하는 명령어를 함께 실행할 수 있다.
메타문자 | 설명 | 예시 |
` ` | 명령어 치환 ` ` 안에 들어있는 명령어를 실행한 결과로 치환된다. |
$ echo `echo theori` 결과 : theori |
$( ) | 명령어 치환 $( ) 안에 들어있는 명령어를 실행한 결과로 치횐된다. 위와 다르게 중복 사용이 가능하다. ( echo $(echo $(echo theori))) ) |
$ echo $(echo theori) 결과: theori |
&& | 명령어 연속 실행 ( Logical And ) 한 줄에 여러 명령어를 사용하고 싶을 때 사용 앞 명령어에서 에러가 발생하지 않아야 뒷 명령어를 실행한다. |
$ echo hello && echo theori 결과 : hello theori |
| | | 명령어 연속 실행 ( Logical Or ) 한 줄에 여러 명령어를 사용하고 싶을 때 사용 앞 명령어에서 에러가 발생해야 뒷 명령어를 실행한다. |
$ cat / || echo theori 결과: cat: /: Is a directory theori |
; | 명령어 구분자 한 줄에 여러 명령어를 사용하고 싶을 때 사용 단순히 명령어를 구분하기 위해 사용 앞 명령어의 에러 유무와 관계 없이 뒷 명령어를 실행 |
$ echo hello; echo theori 결과 : hello theori |
| | 파이프 앞 명령어의 결과가 뒷 명령어의 입력으로 들어감 |
echo id | /bin/sh 결과 : uid=1001(theori) gid=1001(theori) groups=1001(theori) |
@app.route('/ping')
def ping():
ip = request.args.get('ip')
return os.system(f'ping -c 3 {ip}')
위와 같이 유저가 입력한 주소로 ping 명령어 (네트워크 상태 점검)를 실행하는 코드가 있다고 가정하자.
앞에서 배운 Meta 문자를 이용하여 id 명령어를 실행해보자.
Command injection이 발생할 경우 현재 Command를 실행하는 웹 어플리케이션의 권한으로 임의의 명령어를 실행할 수 있다.
나는 ` `를 이용하여 문제를 해결했는데,
다른 방법으로도 문제를 해결할 수 있다.
Command injection 취약점을 막기 위해서는 사용자의 입력 데이터가 Command 인자가 아닌 다른 값으로 해석되는 것을 방지해야 한다.
가장 좋은 방법은 웹 어플리케이션에서 OS Command를 사용하지 않는 것이다.
만약 OS Command에 사용자의 입력 데이터를 사용해야할 경우 필터링을 통해 Command Injection을 방지해야 한다.
- 정규식을 통한 화이트리스트 방식 필터링
ping을 보내는 페이지의 경우 사용자가 입력한 IP가 정상적인 IP 형식인지 정규식으로 검증 후 사용할 수 있다.
import re, os, ...
...
chk_ip = re.compile('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
if bool(chk_ip.match(ip)):
return run_system(f'ping -c 3 {ip}')
else:
return 'ip format error'
- OS Command에서 Meta 문자로 사용되는 값을 필터링하고 따옴표로 감싸기
ping을 보내는 페이지의 경우 사용자가 입력한 IP를 따옴표로 감싸서 사용할 수 있다.
if '\'' in ip:
return 'not allowed character'
return run_system(f'ping -c 3 \'{ip}\'')
** Double Quotes( " )를 사용할 경우 $, `가 해석되어 모든 입력을 문자열로 처리하는 Single Quotes( ' )를 사용하자.
- execve args 인자로 사용
shell meta 문자로 해석되지 않도록 입력 값을 넣는다.
subprocess.Popen(['ping', '-c', '3', ip]) # B
- 기능에 해당하는 라이브러리 사용
사용하고자하는 기능을 OS 커맨드가 아닌 구현한 라이브러리로 대체 사용
#! pip install ping3
# https://github.com/kyan001/ping3/blob/master/ping3.py
import ping3
ping3.ping(ip)
파일 업로드 취약점
- 서버의 파일 시스템에 사용자가 원하는 경로 또는 파일 명 등으로 업로드가 가능하여 악영향을 미칠 수 있는 파일이 업로드되는 취약점
File Upload : 웹 서비스를 통해 파일을 서버에 업로드하는 기능
- 파일 업로드 기능은 사용자의 파일이 서버의 파일 시스템에 저장되어 처리된다는 이유로 인해 취약점이 발생할 수 있음
파일 업로드 취약점을 통해 서버 파일 시스템에 원하는 파일 경로 또는 파일명을 업로드할 수 있다면 악의적인 공격자는 웹 어플리케이션 또는 서버의 서비스가 참조하는 파일을 업로드하여 공격에 사용할 수 있음
CGI (Common Gateway Interface) : 사용자의 요청을 받은 서버가 동적인 페이지를 구성하기 위해 엔진에 요청을 보내고 엔진이 처리한 결과를 서버에게 반환하는 기능
ex) 웹 서버 > Apache, 웹 어플리케이션 > php를 사용하는 서버가 사용자에게 요청을 보냄
>>> Apache : 사용자의 요청을 해석
>>> 사용자가 요청하는 리소스의 확장자가 .php와 같이 php엔진을 사용하는 확장자임
>>> mod_php (CGI)를 통해 사용자의 요청을 php엔진이 처리 및 실행하도록 요청
php, jsp, asp 등과 같이 CGI를 통해 서비스를 하는 형태에서는 확장자를 통해 웹 어플리케이션 엔진에 요청 여부를 판단한다.
ex)
Apache 설정 파일
<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
.php 확장자 외에도 .php3/4/5/7, .pht, .phtml 등의 확장자를 가진 파일이라면 php에서 처리되도록 핸들링 되어 있다.
이와 같이 웹 서비스가 동작하는 경로에 사용자가 원하는 파일 내용과 파일명을 업로드할 수 있다면 서버가 엔진에 요청하는 확장자를 업로드하여 서버의 웹 어플리케이션에 원하는 코드를 실행할 수 있다.
실습)
<?php
if(!empty($_FILES['file'])){
$filename = generateRandomString(); // custom function
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$path = "./uploads/" . $filename . "." . $ext;
if(move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
return true; // upload success
} else {
return false; // upload fail
}
}
?>
위 코드는 아래 실습 모듈의 업로드 부분이다. php 파일을 업로드하여 php를 실행시키거나 html 파일 등을 업로드하여 Stored XSS 취약점을 발생시킬 수 있다.
왼쪽 사진과 같이 XSS를 작성하여 업로드하였고 업로드한 파일 목록을 [ 파일 목록 ]에서 확인할 수 있었다.
파일 주소를 누르면 아래와 같이 XSS 공격이 이루어진 것을 확인할 수 있다.