발자취

#05 PHP 코드 취약점 실습 (Load File Read, Remote Command Execution, Remote Code Execution) 본문

3-1/웹 어플리케이션 보안

#05 PHP 코드 취약점 실습 (Load File Read, Remote Command Execution, Remote Code Execution)

해린 2023. 3. 22. 03:50

01. Local File Read 실습

1. LocalFileRead.php와 process_local_file_read.php를 작성한다.

 

LocalFileRead.php

#!/usr/bin/php-cgi
<?php

print "<form method=\"get\"action=\"process_local_file_read.php\">";
print "<p>localfile: <input type=\"text\"name=\"localfile\"/></p>\n";
print "<p><input type=\"submit\"value=\"Apply\" /></p>\n";
print "</form>";

?>

Form을 사용해서 사용자가 local 파일명을 입력할 수 있도록 구현.

메소드는 GET으로, action은 process_local_file_read.php로 설정함.

 

 

process_local_file_read.php

#!/usr/bin/php-cgi
<?php

$localfile = $_GET['localfile'];
readfile($localfile);

?>

GET 요청을 통해 들어온 파일명에 대해 readfile 함수를 적용해서 입력된 파일을 읽음.

 

 

 

2. C:\xampp\htdocs 경로에 passwd.txt 파일과 hosts.txt 파일을 생성한다.

 

 

3. 위에서 구현한 php 파일들을 웹사이트에서 액세스 하기 위해, URL 정보를 브라우저에 입력하고 웹사이트로 이동함.

http://127.0.0.1/LocalFileRead.php

 

 

4. local 파일명으로 passwd.txt를 입력한 후, 화면에 passwd, passwd, passwd가 출력되는지 확인

http://127.0.0.1/LocalFileRead.php

 

 

Apply 버튼을 누른 후의 결과

 

 

 

5. local 파일명으로 hosts.txt를 입력한 후, 화면에 Hosts, Hosts, Hosts가 출력되는지 확인

http://127.0.0.1/LocalFileRead.php

 

 

Apply 버튼을 누른 후의 결과

 

 

6. passwd.txt와 hosts.txt 파일 내용들이 화면에 출력되는 것을 막기 위해 process_local_file_read.php에 아래의 필터링 기능을 구현함.

- "passwd" 문자열과 "hosts" 문자열이 포함된 블랙리스트를 array로 선언

- 사용자가 입력한 파일명에 블랙리스트 내용이 있으면 해당 파일에 대한 readfile 함수 수행을 차단함. (preg_match) 함수를 이용함.

-> (4), (5)을 다시 수행했을 때, passwd.txt와 hosts.txt 파일 내용 정보들이 화면에 출력되지 않는지를 확인함.

 

process_local_file_read.php

#!/usr/bin/php-cgi
<?php

$localfile = $_GET['localfile'];

$blacklist = array("/passwd/i", "/hosts/i");
$b = 0;

for ($i=0; $i<sizeof($blacklist); $i++){
	if(preg_match($blacklist[$i], $localfile)){
		$b = 1;
	}
}
if($b==0){
	readfile($localfile);
}

?>

"passwd", "hosts"를 패턴으로 가지는 blacklist라는 이름의 array를 만들고, 플래그값인 b를 0으로 초기화하여 선언한다. 

블랙리스트의 모든 요소가 로컬 파일로 들어온 문자열 안에 포함되어 있는지를 확인하기 위해 for문을 사용하고, 만약 포함되어 있다면 플래그값을 1로 바꾼다.

플래그값이 0일 경우에만 정상 출력해주면 된다.

 

 


02. Remote Command Execution 실습

1. RemoteCommandExecution.php와 process_remote_command_execution.php를 작성한다.

 

RemoteCommandExecution.php

#!/usr/bin/php-cgi
<?php

print "<form method=\"get\"action=\"process_remote_command_execution.php\">";
print "<p>command: <input type=\"text\"name=\"command\"/></p>\n";
print "<p><input type=\"submit\"value=\"Apply\" /></p>\n";
print "</form>";

?>

Form을 사용해서 사용자가 명령어를 입력할 수 있도록 구현.

메소드는 GET으로, action은 process_remote_command_execution.php로 설정함.

 

process_remote_command_execution.php

#!/usr/bin/php-cgi
<?php

$command = $_GET['command'];

system($command);


?>

GET 요청을 통해 들어온 명령어에 대해 system 함수를 적용해서 실행시킴.

 

 

2. 위에서 구현한 php 파일들을 웹사이트에서 액세스 하기 위해, URL 정보를 브라우저에 입력하고 웹사이트로 이동함.

http://127.0.0.1/RemoteCommandExecution.php

 

 

3. 웹 사이트에서 명령어로 md test1을 입력한 후에, test1 폴더가 생성되는지 확인함.

command 입력창에 "md test1"를 입력하고 Apply를 누른 결과,

 

C:\xampp\htdocs 경로에 test1이 생긴 것을 확인할 수 있었다.

 

 

4. 웹 사이트에서 명령어로 md test2&rd test1을 입력한 후에, test2 폴더가 생성되고, test1 폴더가 삭제되었는지 확인함.

입력한 뒤 Apply를 눌러본 결과,

 

test1 폴더는 사라지고, test2 폴더가 새로 생성된 것을 확인할 수 있었다.

 

 

5. process_remote_command_execution.php에서 escapeshellcmd 함수를 이용해서 세미콜론과 &을 필터링 하는 부분을 구현함.

 

process_remote_command_execution.php

#!/usr/bin/php-cgi
<?php

$command = escapeshellcmd($_GET['command']);

system($command);


?>

 

 

6. (3)을 다시 수행했을 때 test1 폴더가 다시 생성되는지 확인함. 웹 사이트에서 md test2 명령어를 입력한 후에 test2 폴더가 생성되는지 확인함.

(3) 수행 결과, 

test1 폴더가 정상적으로 생성되는 것을 확인할 수 있었다.

 

md test2 수행 결과,

 

test1 폴더가 정상적으로 생성되는 것을 확인할 수 있었다.

 

 

7. 웹 사이트에서 명령어로 rd test2;&dir을 입력한 후에 발생되는 결과를 확인함.

입력해본 결과, test2는 정상적으로 삭제되었고 

 

dir은 정상적으로 작동하지 않는 것을 확인할 수 있다.

 


03. Remote Code Execution 실습

1. RemoteCodeExecution.php와 process_remote_code_execution.php를 작성한다.

 

RemoteCodeExecution.php

#!/usr/bin/php-cgi
<?php

print "<form method=\"get\"action=\"process_remote_code_execution.php\">";
print "<p>code: <input type=\"text\"name=\"code\"/></p>\n";
print "<p><input type=\"submit\"value=\"Apply\" /></p>\n";
print "</form>";

?>

Form을 사용해서 사용자가 코드를 입력할 수 있도록 구현.

메소드는 GET으로, action은 process_remote_code_execution.php로 설정함.

 

process_remote_code_execution.php

#!/usr/bin/php-cgi
<?php

$code = $_GET['code'];

eval($code);

?>

GET 요청을 통해 들어온 코드에 대해 eval 함수를 적용해서 실행시킴.

 

 

2. 위에서 구현한 php 파일들을 웹사이트에서 액세스 하기 위해, URL 정보를 브라우저에 입력하고 웹사이트로 이동함.

http://127.0.0.1/RemoteCodeExecution.php

 

 

3. 웹 사이트에서 코드로 phpinfo();를 입력한 후에, php 관련 정보들이 화면에 출력되는지 확인함.

입력해보면,

 

정상적으로 php 관련 정보들이 출력된다.

 

 

4. php 관련 정보들이 화면에 출력되는 것을 막기 위해 process_remote_code_execution.php에 아래의 필터링 기능을 구현함.

- ";" 문자열이 포함된 블랙리스트를 array로 선언

- 사용자가 입력한 코드에 블랙리스트 내용이 있으면 해당 코드에 대한 eval 함수 수행을 차단함. (preg_match 함수를 이용함.)

-> (3)을 다시 수행했을 때, php 관련 정보가 화면에 출력되지 않는지를 확인함.

 

process_remote_code_execution.php

#!/usr/bin/php-cgi
<?php

$code = $_GET['code'];
$blacklist = array("/;/i");

if(!preg_match($blacklist[0], $code)){
	eval($code);
}


?>

 

입력해보면, 

 

정보가 출력되지 않는 것을 확인할 수 있음.