본문 바로가기
Cert/소프트웨어(SW) 보안약점 진단원

구현단계 보안약점 기준 - 코드 삽입

by 브루노W 2024. 9. 9.
유형 입력데이터 검증 및 표현
보안약점 코드 삽입
개요 공격자가 소프트웨어의 의도된 동작을 변경하도록 임의 코드를 삽입하여 소프트웨어가 비정상적으로 동작하도록 하는 보안약점을 말한다. 코드 삽입은 프로그래밍 언어 자체의 기능에 의해서만 제한된다는 점에서 운영체제 명령어 삽입과 다르다.

취약한 프로그램에서 사용자의 입력값에 코드가 포함되는 것을 허용할 경우, 공격자는 개발자가 의도하지 않은 코드를 실행하여 권한을 탈취하거나 인증 우회, 시스템 명령어 실행 등을 할 수 있다.
보안대책 동적코드를 실행할 수 있는 함수를 사용하지 않는다.

필요 시, 실행 가능한 동적코드를 입력값으로 받지 않도록, 외부 입력값에 대하여 화이트리스트 방식으로 구현한다. 또는 유효한 문자만 포함하도록 동적코드에 사용되는 사용자 입력값을 필터링한다.
진단방법 각 언어에서 제공하고 있는 동적실행 함수를 확인한다.

동적코드 실행에 사용되는 데이터가 신뢰할 수 있는 값인지 확인한다.
이 때, 데이터가 신뢰할 수 없는 값이나 별도의 검증절차가 없으면 취약하다고 판단한다.
연관된 설계단계 기준 시스템 자원 접근 및 명령어 수행 입력값 검증

 

코드예제

 

● 안전하지 않은 코드 예 (Java)

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;
    }
}

조작된 인수를 입력한 공격코드를 이용하여 새로운 파일을 만들거나 덮어씌울 수 있다.

 

● 안전하지 않은 코드 예 (JSP)

<body>
    <%
    String name = request.getparameter("name");
    %>

    <script>
        // 외부 입력값인 name을 javascript new Function()을 이용하여 문자열을 함수로 실행하고 있다.
        (new Function(<%=name%>))();
    </script>
</body>

javascript new Function()으로 동적으로 코드를 실행할 수 있다.

 

● 안전한 코드 예 (Java)

@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;
}

외부 입력값을 필터링하여 사전 검증하는 코드를 추가한다.

 

● 안전한 코드 예 (Java)

@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();
	}
}

 

 

진단방법

 

 

각 언어에서 제공하고 있는 동적실행 함수를 확인한다.(①)

동적코드 실행에 사용되는 데이터가 신뢰할 수 있는 값인지 확인한다.(②)
이때, 데이터가 신뢰할 수 없는 값이나 별도의 검증절차가 없으면 취약하다고 판단한다.

 

● 일반적인 진단의 예

public class CodeInjection {
    // eval 실행 데이터가 프로그램 실행 파라미터이다.
    public static void main(String[] args) throws ScriptException { ·····················②
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine= scriptEngineManager.getEngineByName("javascript");
        String src = "print('" + args[1] + "');";
        scriptEngine.eval(src); ·························································①
    }
}