본문 바로가기
  • PunkComputing
Cyber Security/penetest_LAB

개발 보안 시리즈 [Command injection PHP 공격/대응]

by Mr.DOT 2021. 5. 4.
반응형

Command injection 이란?

웹 어플리케이션에서 system(), exec()와 같은 시스템 명령어를 실행시킬 수있는 함수를 제공하며 사용자 입력 값에 대한 필터링이 제대로 이루지지 않을 경우 공격자가 운영체제 시스템 명령어를 호출하여 백도어 설치나 관리자 권한 탈취 등 시스템 보안에 심각한 영향을 줄수 있습니다.

 

Command injection 이해 하려면 CLI에 대한 이해가 필요합니다.

왜냐하면 웹 사이트가 사용하는 웹서버의 운영체제가 리눅스인 경우 input box란에 bash 명령어가 동작하기 때문입니다.

 

취약한 php 코딩 예시 입니다 .

<html><body><pre>
<?php
$command = "ping -c 1 " . $_REQUEST["address"];
system($command);
?>
</pre></body></html>

소스 코드를 관찰하거나 확인함으로써 ping.php 스크립트가 시스템 명령을 호출하는지 확인할 수도 있습니다.

이로 인해이 스크립트에 명령 주입 취약점이 존재할 가능성이 매우 높으습니다.

 

$ ping -c 2 PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.087 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.098 ms
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.087/0.092/0.098/0.000 ms

이렇게 보면 지금 까지의 설명이 이해되하기 쉽습니다. 

 

그런 다음 이제 CLI(Command-line interface) 작동시키 려면 어떻게 하여야 하는지 알아 보겠습니다. 

 

bash 명령 목록
목록(List)은 하나 이상의 파이프라인을 연산자 ';', '&', '&' 또는 '||' 중 하나로 구분하고 선택적으로 ';', '&' 또는 새 회선 중 하나로 종단하는 순서이다.

이들 목록 연산자 중 '&&'와 '||'은 동일한 우선 순위를 가지며, ';'과 '&'이 같은 우선 순위를 갖는다.

하나 이상의 새 줄 시퀀스가 세미콜론과 같은 명령을 구분하는 목록에 나타날 수 있습니다.

명령이 제어 연산자 '&'에 의해 종료되면 셸은 명령을 하위 셸에서 비동기적으로 실행합니다. 

 

이를 백그라운드에서 명령 실행이라고 하며 이러한 명령을 비동기 명령이라고 합니다. 

셸은 명령이 완료될 때까지 기다리지 않으며 반환 상태는 0(참)입니다. 

작업 제어가 활성화되지 않은 경우(작업 제어 참조), 명시적 리디렉션이 없는 비동기 명령의 표준 입력은 /dev/null에서 리디렉션됩니다.

';'로 구분된 명령은 순차적으로 실행되며 셸은 각 명령이 차례로 종료될 때까지 기다립니다. 반환 상태는 마지막으로 실행된 명령의 종료 상태입니다.

AND 및 OR 목록은 각각 제어 연산자 '&&'와 '||'에 의해 구분된 하나 이상의 파이프라인의 시퀀스이다. AND 및 OR 목록은 왼쪽 연관성으로 실행됩니다.

AND 목록에는 양식이 있습니다.

명령 1 & & 명령 2
command2는 command1이 0(성공)의 종료 상태를 반환하는 경우에만 실행됩니다.

OR 목록에는 양식이 있습니다.

명령1 || 명령2
command2는 명령1이 0이 아닌 종료 상태를 반환하는 경우에만 실행됩니다.

AND 및 OR 목록의 반환 상태는 목록에서 마지막으로 실행된 명령의 종료 상태입니다.

$ false || echo "Oops, fail"
Oops, fail

$ true || echo "Will not be printed"
$  

$ true && echo "Things went well"
Things went well

$ false && echo "Will not be printed"
$

$ false ; echo "This will always run"
This will always run

 

'/bin' 디렉토리와 '/usr/bin' 디렉토리의 '/usr/sbin' /차이는 무엇일까? ('/bin' vs '/usr/bin')

 

/bin : /usr 파티션이 마운트되기 전에 사용할 수 있는 이진 파일입니다. 이것은 초기 부팅 단계에서 사용된 사소한 바이너리나 단일 사용자 모드로 부팅할 때 필요한 바이너리에 사용됩니다. cat, ls 등과 같은 이진수들을 생각해보세요.

/sbin : 동일하지만 수퍼유저(루트) 권한이 있는 이진 파일의 경우 필요합니다.

/usr/bin : 처음과 동일하지만 일반적인 시스템 전체 이진 파일의 경우.

/usr/sbin : 위와 동일하지만 수퍼유저(루트) 권한이 있는 바이너리의 경우 필요합니다.

 

man hier (hierarchy) lists all the directories. To get the ones just for binaries use:

$ man hier | grep -E 'bin$|sbin$|^.{7}(/bin)|^.{7}(/sbin)' -A2

       /bin   This directory contains executable programs which are needed in single user
              mode and to bring the system up or repair it.

--
       /sbin  Like  /bin,  this  directory  holds commands needed to boot the system, but
              which are usually not executed by normal users.

--
       /usr/X11R6/bin
              Binaries  which  belong  to the X-Window system; often, there is a symbolic
              link from the more traditional /usr/bin/X11 to here.
--
       /usr/bin
              This  is the primary directory for executable programs.  Most programs exe‐
              cuted by normal users which are not needed for booting or for repairing the
--
       /usr/local/bin
              Binaries for programs local to the site.

--
       /usr/local/sbin
              Locally installed programs for system administration.

--
       /usr/sbin
              This directory contains program binaries for  system  administration  which
              are  not  essential  for the boot process, for mounting /usr, or for system

만약 웹 서버가 리눅스가 아닌 윈도우 서버라면 cmd관련 CLI를 참고 하여야 합니다.

 

대응 방안

-웹 방화벽에서 특수문자 특수 구문 등을 필터링 할 수 있도록 규칙을 적용 조치

-Application은 운영체제로부터 명령어를 직접적으로 호출 하지 않도록 구현.

-입력값에 대한 파라미터 데이터의 &, |, ;, '등의 문자에 대한 필터링 조치.

 

php 시큐어 코딩

<? 
//$str = input char
function sqlfilter($str) { 
  $str = addslashes($str);
  $strdata = "'&\&\"&\&(&)&#&>&<&=&*/&/*&+&\&%&;&|&--&@&=&[&]&,";
  $search = explode("&",$strdata);
  for($i=0;$i < count($search);$i++){
    $str = str_replace($search[$i], "", $str); 
  }
  return $str;
}
?>

 

 

 

반응형

댓글