이 섹션에는 소스 코드 외부에 있지만 제작 중인 제품의 보안에는 여전히 중요한 내용이 모두 포함되어 있습니다. 이 섹션에서 다루는 문제들은 소스 코드와 직접적으로 관련이 없기 때문에 나머지 섹션과 분리했습니다.
allow_url_fopen
옵션이 활성화되면 HTTP 또는 FTP URL을 사용하여 원격 파일에서 작업을 수행할 파일 이름을 수락하는 PHP 함수를 허용합니다. PHP 4.0.4에서 도입되고 기본적으로 활성화되어 있는 이 옵션은 공격자가 응용 프로그램에 악성 콘텐트를 전송할 수 있기 때문에 위험합니다. 최고의 보안 상태에서 원격 파일 작업을 수행하여도 원격 파일을 수정하여 악성 콘텐트를 포함시키는 공격자에게 응용 프로그램이 취약해집니다. 공격자가 응용 프로그램이 작동하는 URL을 제어할 수 있는 최악의 경우, 공격자는 원격 서버에 URL을 제공하여 임의의 악성 콘텐트를 응용 프로그램에 삽입할 수 있습니다. $file
값이 요청 매개 변수에서 제어되므로 공격자는 URL을 원격 파일에 제공하여 프로그래머의 가정을 위반할 수 있습니다.
<?php
$file = fopen ($_GET["file"], "r");
if (!$file) {
// handle errors
}
while (!feof ($file)) {
$line = fgets ($file, 1024);
// operate on file content
}
fclose($file);
?>
allow_url_include
옵션이 활성화되면 원격 파일에서 HTTP 또는 FTP URL을 수락할 수 있도록 하는 include()
및 require()
와 같이 현재 페이지에 포함시킬 파일을 지정하는 PHP 함수를 허용합니다. PHP 5.2.0에서 도입되 기본적으로 비활성화되어 있는 이 옵션은 공격자가 응용 프로그램에 악성 콘텐트를 전송할 수 있기 때문에 위험합니다. 최고의 보안 상태에서 원격 파일 작업을 포함하여도 원격 파일을 수정하여 악성 콘텐트를 포함시키는 공격자에게 응용 프로그램이 취약해집니다. 공격자가 응용 프로그램에서 포함할 원격 파일을 지정하는 데 사용하는 URL을 제어할 수 있는 경우, 공격자는 URL을 원격 서버에 제공하여 임의의 악성 콘텐트를 응용 프로그램에 삽입할 수 있습니다.cgi.force_redirect
를 비활성화할 경우, /cgi-bin/php에 대한 접근 권한이 있는 공격자는 PHP 인터프리터에 대한 권한을 사용하여 임의의 웹 문서에 접근하고 서버에서 수행한 access control 검사를 무시하게 됩니다.dl
을 통한 동적 로드를 사용하여 open_basedir
제한을 우회할 수 있습니다.enable_dl
구성은 라이브러리의 동적 로드를 허용합니다. 공격자는 이를 통해 open_basedir 구성으로 설정된 제한을 우회할 수 있으며 시스템의 모든 파일에 대한 액세스가 허용될 수 있습니다.enable_dl
을 활성화하면 공격자가 다른 취약점을 쉽게 악용할 수 있습니다.file_uploads
옵션을 활성화하면 PHP 사용자가 임의의 파일을 서버에 업로드할 수 있습니다. 사용자에게 파일 업로드에 대한 권한을 부여하여도 보안 취약점 자체는 나타나지 않습니다. 그러나, 이 기능은 악의적인 사용자가 서버 환경에 데이터를 전송할 수 있는 경로를 제공하므로 다양한 공격이 발생할 수 있습니다.
<?php
$udir = 'upload/'; // Relative path under Web root
$ufile = $udir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $ufile)) {
echo "Valid upload received\n";
} else {
echo "Invalid upload rejected\n";
} ?>
open_basedir
구성 옵션이 있으면 PHP 프로그램이 php.ini에 지정된 디렉터리 트리 외부에서 파일을 조작할 수 없게 됩니다. open_basedir
옵션을 사용하여 지정된 디렉터리가 없는 경우 PHP에서 실행되는 프로그램은 로컬 파일 시스템에 있는 임의의 파일에 대한 전체 액세스 권한을 가지며 공격자는 이를 통해 액세스해서는 안 되는 파일을 읽거나 쓰거나 만들 수 있습니다.open_basedir
을 사용하여 제한적인 디렉터리 집합을 지정하지 않으면 공격자가 다른 취약점을 더 쉽게 악용할 수 있습니다.open_basedir
옵션이 전반적으로 보안에 이득이 되지만 이 옵션을 구현하면 공격자가 특정 환경에서 해당 제한 사항을 무시할 수 있는 race condition을 겪을 수 있습니다[2]. PHP가 액세스 권한 확인을 수행하는 시간과 파일이 열리는 시간 사이에는 TOCTOU(time-of-check, time-of-use) 경합 조건이 존재합니다. 다른 언어의 파일 시스템 경합 조건과 마찬가지로 이 경합 조건을 통해 공격자는 액세스 제어 검사를 통과하는 파일에 대한 심볼릭 링크를 테스트에 실패할 다른 심볼릭 링크로 교체하여 보호된 파일에 대한 액세스 권한을 얻을 수 있습니다.safe_mode
가 활성화되면 safe_mode_exec_dir
옵션은 지정된 디렉터리에서만 명령을 실행하도록 PHP를 제한합니다. safe_mode_exec_dir
항목이 없으면 보안 취약점이 발생하지 않지만 이 추가 사항으로 인해 다른 취약점과 함께 공격자에 의해 익스플로이트되어 익스플로이트가 더 위험해질 수 있습니다.open_basedir
구성은 변경 가능한 작업 디렉터리를 지정합니다.open_basedir
구성 옵션이 있는 경우 이 구성 옵션은 PHP 프로그램이 php.ini에 지정된 디렉터리 트리 외부의 파일에 대해 작업을 수행하지 못하도록 합니다. 작업 디렉터리가 .
으로 지정된 경우에는 공격자가 chdir()
을 사용하여 작업 디렉터리를 변경할 가능성이 있습니다.open_basedir
옵션이 전반적으로 보안에 이득이 되지만 이 옵션을 구현하면 공격자가 특정 환경에서 해당 제한 사항을 무시할 수 있는 race condition을 겪을 수 있습니다[2]. 검사 시점/사용 시점(TOCTOU) race condition은 PHP가 접근 권한 검사를 수행하는 시점과 파일을 여는 시점 사이에 존재합니다. 다른 언어의 file system race condition과 마찬가지로 이 race condition을 사용하면 공격자가 access control 검사를 통과한 파일에 대한 심볼릭 링크를 테스트에 실패한 다른 심볼릭 링크로 바꿔 보호된 파일에 대한 접근 권한을 얻을 수 있습니다.register_globals
옵션을 활성화하면 PHP가 모든 EGPCS(환경, GET, POST, 쿠키 및 서버) 변수를 전역으로 등록할 수 있습니다. 이는 모든 PHP 프로그램의 모든 범위에 접근할 수 있습니다. 이 옵션을 사용하면 프로그래머가 주로 사용하는 최초 값을 조금은 알아보기 힘든 프로그램을 작성하도록 하여 시작 환경에서 예상치 못한 동작을 일으키거나 악의적인 환경에 있는 공격자에게 문을 열어주게 됩니다. register_globals
가 위험한 보안 해석으로 인정되어 이 옵션은 PHP 4.2.0에서 기본적으로 비활성화되었으며 PHP 6에서는 더 이상 사용되지 않거나 제거되었습니다.$username
값이 서버에서 제어하는 세션에서 오지만 공격자가 요청 매개 변수로 $username
의 악의적인 값을 제공할 수 있다고 가정합니다. register_globals
가 활성화되면 이 코드에 공격자가 전송한 악의적인 값이 생성된 동적 HTML 콘텐트로 포함됩니다.
<?php
if (isset($username)) {
echo "Hello <b>$username</b>";
} else {
echo "Hello <b>Guest</b><br />";
echo "Would you like to login?";
}
?>
safe_mode
옵션은 PHP의 가장 중요한 security features 중 하나입니다. safe_mode
가 비활성화되면 PHP는 이를 호출한 사용자의 권한이 있는 파일에서 동작합니다. 이는 주로 권한 있는 사용자입니다. safe_mode
가 비활성화된 PHP를 구성하면 보안 취약점이 발생하지 않지만 이 추가 사항으로 인해 다른 취약점과 함께 공격자에 의해 익스플로이트되어 익스플로이트가 더 위험해질 수 있습니다.session.use_trans_sid
를 활성화하면 PHP가 URL의 세션 ID를 전달하게 됩니다. 이는 공격자가 활성 세션을 하이재킹하거나 공격자의 제어 하에 이미 기존 세션을 사용하는 사용자를 속이는 것을 더 쉽게 만듭니다. open_basedir
구성 옵션에는 파일 접근 race conditions에 취약한 설계 결함이 있어서 공격자가 file system에서 access control 검사를 피해갈 수 있습니다.open_basedir
구성 옵션이 있는 경우, PHP 프로그램이 php.ini에 지정된 디렉터리 트리 외부의 파일에 대해 작업을 수행하는 것을 막습니다. open_basedir
옵션이 보안에 전반적으로 이득이 되지만 구현은 공격자가 특정 환경에서 해당 제한 사항을 무시할 수 있는 race condition을 겪을 수 있습니다[2]. 검사 시점/사용 시점(TOCTOU) race condition은 PHP가 접근 권한 검사를 수행하는 시점과 파일을 여는 시점 사이에 존재합니다. 다른 언어의 file system race condition과 마찬가지로 이 취약점을 사용하면 공격자가 access control 검사를 통과한 파일에 대한 심볼릭 링크를 테스트에 실패한 다른 심볼릭 링크로 바꿔 보호된 파일에 대한 접근 권한을 얻을 수 있습니다.form-bean
항목이 여러 개 있습니다. 중복된 form-bean
이름은 종종 디버그 코드 또는 입력 오류가 남아 있음을 나타냅니다.form-bean
태그에 동일한 이름이 사용되는 경우 마지막 항목만 등록되므로 중복된 <form-bean>
이름은 아무런 소용이 없습니다.form-bean
항목이 있습니다.
<form-beans>
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="name" type="java.lang.String" />
<form-property name="password" type="java.lang.String" />
</form-bean>
<form-bean name="loginForm" type="org.apache.struts.validator.DynaActionForm">
<form-property name="favoriteColor" type="java.lang.String" />
</form-bean>
</form-beans>
path
속성을 사용하여 요청을 처리하는 데 필요한 리소스를 찾습니다. 경로는 모듈 상대 위치이므로 "/" 문자로 시작되지 않는 경로는 오류입니다.예제 2: 다음 구성은 "/" 문자로 시작되지 않는 경로를 사용합니다.
<global-exceptions>
<exception key="global.error.invalidLogin" path="" scope="request" type="InvalidLoginException" />
</global-exceptions>
<global-forwards>
<forward name="login" path="Login.jsp" />
</global-forwards>
input
속성을 생략하는 것은 검증 오류를 반환할 수 있는 오류입니다.input
속성을 요구합니다[2]. input
속성은 검증 오류가 발생할 때 오류 메시지를 표시하는 데 사용되는 페이지를 지정합니다.input
속성을 지정하지 않습니다.
<action-mappings>
<action path="/Login"
type="com.LoginAction"
name="LoginForm"
scope="request"
validate="true" />
</action-mappings>
type
속성이 없는 <exception>
태그는 사용되지 않습니다.<exception>
태그를 사용하려면 예외 유형을 정의해야 합니다. type
속성이 누락되거나 비어 있으면 불필요한 예외 처리기 또는 실수로 인한 누락을 나타냅니다. 개발자가 예외를 처리하려고 했지만 예외 유형을 정의하는 것을 잊은 경우 응용 프로그램에서 시스템에 대한 민감한 정보가 누출될 수 있습니다.<exception>
태그에서 유형을 생략합니다.
<global-exceptions>
<exception
key="error.key"
handler="com.mybank.ExceptionHandler"/>
</global-exceptions>
form-bean
을 가리키는 Struts action
은 올바르게 매핑되지 않습니다.form-bean
항목을 사용하여 HTML 양식을 작업에 매핑합니다. <action>
태그의 name
속성이 form-bean
의 이름과 일치하지 않으면 작업을 매핑할 수 없으며 불필요한 정의 또는 입력 오류가 있음을 나타냅니다.bean2
에 대한 매핑이 없습니다.
<form-beans>
<form-bean name="bean1" type="coreservlets.UserFormBean" />
</form-beans>
<action-mappings>
<action path="/actions/register1" type="coreservlets.RegisterAction1" name="bean1" scope="request" />
<action path="/actions/register2" type="coreservlets.RegisterAction2" name="bean2" scope="request" />
</action-mappings>
name
속성이 없는 form-bean
은 사용되지 않습니다.form-bean
이름을 사용하여 HTML 양식을 작업에 매핑합니다. form-bean
에 이름이 없으면 작업에 매핑할 수 없으며 불필요한 정의 또는 실수로 누락된 빈을 나타냅니다.form-bean
에는 name
속성이 비어 있습니다.
<form-beans>
<form-bean name="" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="name" type="java.lang.String" />
<form-property name="password" type="java.lang.String" />
</form-bean>
</form-beans>
type
속성이 없는 form-bean
은 올바르게 매핑되지 않습니다.form-bean
항목을 사용하여 HTML 양식을 작업에 매핑합니다. form-bean
에 유형이 없으면 작업에 매핑할 수 없습니다.form-bean
에는 type
속성이 비어 있습니다.
<form-beans>
<form-bean name="loginForm" type="">
<form-property name="name" type="java.lang.String" />
<form-property name="password" type="java.lang.String" />
</form-bean>
</form-beans>