Command Injection
웹 애플리케이션에서 시스템 명령을 사용할 때, 세미콜론 혹은 &, && 를 사용하여 하나의 Command를 Injection 하여
두 개의 명령어가 실행되게 하는 공격
실습
여기 ip를 입력하면 ping을 4번 때린 결과를 볼 수 있는 기능이 있다.
코드를 살펴보면
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
?>
shell_exec() 함수를 통해 리눅스 명령어를 사용하는것을 볼수 있다.
PHP에서 명령어를 실행할 수 있는 함수로는
system() , passthru() , exec() , shell_exec() 등이 자주 사용된다.
이외에도 escapeshellcmd() , pcntl_exec() , proc_open() , curl_exec() , curl_multi_exec() 등이 있다.
그림으로 이해를 하자면 아래와 같다.
따라서 다음과 같이 ; 혹은 &을 이용해서 추가 명령어를 실행한다.
이를 이용해서 민감 정보 혹은 파일을 심어서 서버를 마음대로 조작할 수 있는 파급력있는 취약점이지만 이러한 취약점을 가지고 있는 웹은 찾기 힘들다.
민감정보가 노출되는 모습
대처 방법
다음은 원래기능인 ping 기능만 실행하기 위해 입력 받은 ip를 검사해주는 코드를 추가한 것이다.
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST["ip"];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode(".", $target);
// Check IF each octet is an integer
if ((is_numeric($octet[0])) && (is_numeric($octet[1])) && (is_numeric($octet[2])) && (is_numeric($octet[3])) && (sizeof($octet) == 4) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0].'.'.$octet[1].'.'.$octet[2].'.'.$octet[3];
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
else {
echo '<pre>ERROR: You have entered an invalid IP</pre>';
}
}
?>