※ 주의 : 보안 관련 학습은 자유이지만, 학습 내용을 사용한 경우 법적 책임은 행위자에게 있습니다. (Note: Security-related learning is allowed, but the individual is solely responsible for any legal consequences arising from the use of the acquired knowledge.)
※ 공부 기록용 포스트이며, 검수를 하고 올리지만 간혹 잘 못된 정보가 있을 수도 있습니다.
[보안 공부] 14주 차 - 파일 업로드 취약점 1
PC 화면에서 보시기 적합하도록 작성되었습니다.
파일 업로드 취약점 1(File Upload vulnerability)
파일 업로드로 인하여 발생하는 취약점이다.
현시대의 웹 페이지는 대부분 동적 웹 페이지로, HTML 뿐만 아니라 PHP와 같은 웹 프로그래밍 언어로 코드를 작성하고, 서버 측에 있는 WAS(Web Application Server)가 웹 프로그래밍 코드를 해석하여 코드를 실행한다. 동적 웹 페이지는 정적 웹 페이지에 비하여 DB서버와 연동 가능, 세션 관리 가능, API 연동 가능 등 여러 가지 기능이 있으며 그중에 프로필 이미지, 게시글이나 메일의 첨부파일 등 파일을 업로드하는 기능도 있다.
파일이 업로드되면, 웹 서버 입장에서는 별도의 파일 서버가 있다면 파일 서버에 저장하고, 없다면 웹 서버에 디렉터리를 만들어서 저장하게 된다. 만약 독립적인 파일 서버가 존재한다면, 업로드되는 파일을 실행코드가 아닌 파일로만 취급하면 되기 때문에, 파일 업로드 취약점 방어에 매우 유리하다.
하지만, 파일 서버가 없어서 업로드된 파일을 웹 서버와 같은 곳에 저장한다면 문제가 발생할 수 있다. 공격자가 attack.php라는 파일에 악성코드를 작성하고, 파일로 업로드를 한 뒤, 경로를 알아내어 주소창에 http://~~~~/attack.php를 입력하면 WAS는 확장자가 PHP인 것을 보고 코드를 실행하게 된다.
이때, 공격자가 작성한 코드가 시스템에 명령을 내릴 수 있는 함수로 이루어진 웹 쉘(Web Shell)이라면 서버에 직접 명령어를 입력할 수 있게 되어, 서버의 제어권을 쥐게 되고, 이때까지 배운 모든 보안 취약점을 구현하거나 찾아낼 수 있게 된다. 참고로, WAS서버가 아니라면 명령을 내릴 수 없기 때문에 공격 가능한 범위가 디렉터리 트래버셜(다른 민감한 파일에 접근), 악성 파일 업로드 정도로 상당히 좁아진다.
아래는 php로 작성한 간단한 웹 쉘코드이다. 웹 쉘코드가 적힌 test.php
http://~~/test.php?cmd=명령어 형태로 사용이 가능하다.
실습을 해본다. 글로 길게 적는 것보다, 한 번 해보면 어느 부분에 몇 단계에 걸쳐서 취약점이 있어야 공격에 성공을 하는지, 어떻게 방어를 해야 하는지, 어떤 기교가 있을지 구상해 볼 수 있다.
<?php//webshell 연습코드
if (isset($_GET['cmd'])){
$output = shell_exec($_GET['cmd']);
echo"<pre>$output</pre>";
}
else{
echo"No command";
}
?>
system() 함수 작동이 안 되어서 shell_exec() 함수로 대체하였다.
테스트를 위해 본인 서버에 업로드 후 접속하여, GET method로 명령어를 넣어 보았다. GET method로 cmd 매개변수에 리눅스 명령어를 넣으면 결과가 출력된다. 주소에 경로를 입력했다는 것은, 파일이 업로드되는 위치를 알아야 한다는 뜻이다. 경로를 쉽게 들키지 않게 server 설정에서 경로를 보이지 않게(디렉터리 트래버셜 방지) 하는 게 좋을 것 같고, 파급력을 낮추기 위해 웹 루트를 위치를 조정한다던가, 권한을 제한하는 방법을 사용하는 게 좋을 것 같다.
당연히 php를 실행할 수 있는 서버라서 php로 작성했다. php가 지원되지 않는 WAS라면 php코드는 무용지물이다. find 명령어로 /etc 폴더안의 파일 목록을 조회해보았다.
서버의 실행 중인 계정의 권한에 따라 권한은 제한되겠지만, 상당히 파급력이 큰 공격이다.
/etc/passwd는 확인이 가능했고, /etc/shadow는 확인을 못하는 것으로 봐서 아파치를 실행 시, root가 아닌 user권한만큼 설정되어 있는 것 같다. 웹 검색을 해보니 root로 아파치 서비스를 시작하더라도, 보안상 제한된 권한으로 실행된다고 한다.
방어 방법 실습을 한 번 해보면 충분히 유추해 낼 수 있는 것이지만, 파일 업로드 제한 및 검증에 있어서 MIME에 대한 이해가 필요하고, 파일 확장자가 jpg나 png이더라도 파일을 변조해서 php로 실행 가능한 방법을 연구해 볼 필요가 있다.
업로드 파일 유형 제한 및 검증
저장 경로 검증 및 제한, 경로 비공개 설정
실행 권한, 접근 권한 제한
WAF(Web Application Firewall) 설정
웹 쉘은 테스트 후 반드시 바로 삭제하기! 혹시나 다른 사람이 접속할까 봐 실시간으로 로그를 띄워놓고 테스트했다.