프로세스가 외부 입력 값을 코드(명령어)로 해석·실행할 수 있고 프로세스에 검증되지 않은 외부 입 력 값을 허용한 경우 악의적인 코드가 실행 가능한 보안약점
의도하지 않은 코드를 실행
권한을 탈취
인증 우회
시스템 명령어 실행
(함수 사용 제한) 동적코드를 실행할 수 있는 함수 사용 제한
(화이트리스트방식 구현) 실행 가능한 동적코드를 입력 값으로 받지 않도록, 외부 입력 값에 대하여 화이트리스트 방식으로 구현
(사용자 입력 값 필터링) 유효한 문자만 포함하도록 동적 코드에 사용되는 사용자 입력 값을 필터링
public class CodeInjectionController {
@RequestMapping(value = "/execute", method = RequestMethod.GET)
public String execute(@RequestParam("src") String src)
throws ScriptException {
ScriptEngineManager scriptEngineManager = new
ScriptEngineManager();
ScriptEngine scriptEngine =
scriptEngineManager.getEngineByName("javascript");
// 외부 입력값인 src를 javascript eval 함수로 실행하고 있어 안전하지 않다.
String retValue = (String)scriptEngine.eval(src);
return retValue;
}
}
javax.script.ScriptEngineManager을 사용하여 ScriptEnigneManeger()로 사용자의 입력을 실행하여 출력
공격자는 조작된 인수를 입력한 공격코드를 이용하여 새로운 파일을 만들거나 덮어씌울 수 있다.
<body>
<%
String name = request.getparameter("name");
%>
...
<script>
// 외부 입력값인 name을 javascript new Function()을 이용하여 문자열을 함수로 실행하고 있다.
(new Function(<%=name%>))();
</script>
</body>
외부 입력 값을 javascript의 new Function()으로 동적으로 코드를 실행할수 있다.
@RequestMapping(value = "/execute", method = RequestMethod.GET)
public String execute(@RequestParam("src") String src) throws ScriptException {
// 정규식을 이용하여 특수문자 입력시 예외를 발생시킨다.
if (src.matches("[ \ \w]*") == false) {
throw new IllegalArgumentException();
}
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
String retValue = (String)scriptEngine.eval(src);
return retValue;
}
외부 입력 값에 실행이 가능한 코드가 포함되어 있을 경우 입력 값을 필터링 하여 사전에 검증하는 코드를 추가하면 코드삽입을 완화할 수 있다.
이런 조치를 취할 경우 입력 값의 형태에 따라 정규 표현식을 변형하여 적용해야 한다.
@RequestMapping(value = "/execute", method = RequestMethod.GET)
public String execute(@RequestParam("src") String src) throws ScriptException {
// 유효한 문자 “_” 일 경우 실행할 메소드 호출한다.
if (src.matches("UNDER_BAR“) == true) {
...
// 유효한 문자 “$” 일 경우 실행할 메소드 호출한다.
} else if (src.matches("DOLLAR“) == true) {
...
// 유효하지 않은 특수문자 입력시 예외를 발생시킨다.
} else {
throw new IllegalArgumentException();
}
...
}
스크립트 실행이 필요한 경우는 화이트리스트 방식을 적용하여 유효한 문자인 경우에만 실행되도록 하고 그 외의 경우는 모두 예외 처리한다
(동적 실행 함수를 확인) 동적코드에 사용되는 데이터가 신뢰할 수 있는 값이나 별도의 검증절차가 있는지 확인
//eval 실행 데이터가 프로그램 실행 파라미터이다.
public static void main(String[] args) throws ScriptException { ····························②
… String src = "print('" + args[1] + "');";
scriptEngine.eval(src); ·······················································································①
(정탐) PHP eval() 함수는 PHP 코드를 실행하는 함수. 검증하지 않을 경우 취약
vul.php
$myvar = 'somevalue';
$x = $_GET['arg'];
eval('$myvar = ' . $x . ';');
/vul.php?arg=1;phpinfo()
/vul.php?arg=1;system("uname -a")
/vul.php?arg=1;system("cat /etc/passwd")
/vul.php?arg=1;system("ps -ef")
(정탐) 파라미터에 악의적인 메시지를 입력하면 필터링 과정 없이 파일에 저장. PHP가 파싱하고 실행하는 과정에서 메시지 조회 기능을 수행하게 될 경우 저장된 파일을 보여주게 되어 의도하지 않은 PHP 명령어가 실행될 수 있음.
$name = $_GET["name"];
$message = $_GET["message"];
…
fwrite($handle, "$name says '$message'\n");
…
include($MessageFile);
(오탐) 위험한 모든 기호를 제거하면 문제 발생을 줄일 수 있음.
$x = $_GET['arg'];
$x=preg_replace("/[w\\^a-z0-9]/i", "", $x);
(오탐) 사용 전 필터 메소드로 검증을 수행
public static boolean filterScript(String name) { boolean returnValue = false;
//알파벳, 숫자, ‘_’ 만을 허용한다.
if (name.matches("[\\w]*")) { returnValue = true; }