스터디/웹해킹

IXPLOIT 웹해킹 스터디 9주차 (1) Command injection & File-upload

leeeee.yeon 2021. 2. 12. 14:29

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 공격이 이루어진 것을 확인할 수 있다.