소스 취약점 점검 1차~4차

📌 소스 취약점 점검

최근 진행했던 1년짜리 프로젝트를 마무리 하며 오픈전 테스트 기간동안 소스취약점 점검을 받고 그에 따른 조치를 4차까지 진행했다.

프로젝트 기간이 긴 만큼 소스량도 방대했는데 조치해야할 코드도 정말 많았다.

가장 많았던 대표적인 소스 취약점들로는

▪ sysout으로 찍힌 개발자 고의 출력
▪ XSS
▪ SQL injection
▪ eval, 예외처리시 printStack 및 getMessage로 인한 직접적인 error 사용자 노출
▪ 상대경로
▪ log4j

이외에도 자잘하게 많은것들이 있었는데 가장 많이 나온 조치내용과 중요한 부분들만 정리를 해보려고 한다.

✅ sysout으로 찍힌 개발자 고의 출력

우선 sysout과 같은 출력은 모두 삭제조치를 했고 나중에 유지보수를 위해 필요한 부분들은 주석및 log4j를 이용해 logger로 남겨두었다.

✅ XSS

egov에서 지원하는 HTMLTagFilter를 사용했는데 1차부터 3차까지 계속 조치내용에 걸려서 담당자에게 따로 물어봤더니 방어되는 태그가 부족하기도 하고 조금 오래된 방어법이라는 답변이 왔다.

엥,,😶? 전화를 끊고 바로 메이븐폴더에 있는 라이브러리를 직접 눈으로 확인해보니

(아래 사진은 예시. velog작성할때는 pom.xml에서 HTMLTagFilter를 지워버려서 메이븐에 없었다,,ㅎ)

❗❗(꿀팁! 배포파일로 묶인 .war나 .jar 같이 클래스파일들에 한해서 코드를 열어보고 싶다면 역컴파일러를 통해서 소스 확인이 가능하다!! 무료 툴중에 자바 디컴파일러(jd) gui 버전 추천합니다ㅎ)

취약점 점검 담당자의 추천으로 naver에서 개발한 lucy필터를 적용하기로 했다.

lucy필터 적용까지는 문제 없었는데

여기서 가장 큰 문제는 lucy필터는 서블릿 설정으로 적용을 했기 때문에 form-data에 대해서만 적용되고 @RequestBody로 넘어가는 JSON에 대해서는 처리해주지 않는다는 단점이 있었다.🤦‍♂️

무한 구글구글구글구글구글구글링을 통해,,⏱

아래와 같이 특수문자를 코딩 해줄수 있는 클래스 파일을 만들고

public class HtmlEscapingObjectMapperFactory implements FactoryBean<ObjectMapper> {

    private final ObjectMapper objectMapper;

	public HtmlEscapingObjectMapperFactory() {
        objectMapper = new ObjectMapper();
        objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public ObjectMapper getObject() throws Exception {
        return objectMapper;
    }

    @Override
    public Class<?> getObjectType() {
        return ObjectMapper.class;
    }



    @Override
    public boolean isSingleton() {
        return true;
    }


    public static class HTMLCharacterEscapes extends CharacterEscapes {

		private static final long serialVersionUID = 1L;
		private final int[] asciiEscapes;

        public HTMLCharacterEscapes() {
            // start with set of characters known to require escaping (double-quote, backslash etc)
            asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
            // and force escaping of a few others:
            asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
            asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
            asciiEscapes['&'] = CharacterEscapes.ESCAPE_CUSTOM;
            asciiEscapes['"'] = CharacterEscapes.ESCAPE_CUSTOM;
            asciiEscapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
        }

        @Override
        public int[] getEscapeCodesForAscii() {
            return asciiEscapes;
        }

        // and this for others; we don't need anything special here
        @Override
        public SerializableString getEscapeSequence(int ch) {
            return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
        }
    }
}

bean설정을 통해 적용할수 있었다.

<bean id="htmlEscapingObjectMapper" class="[패키지명].HtmlEscapingObjectMapperFactory" />
 <mvc:annotation-driven>
 <mvc:message-converters>
	        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" >
	        	<property name="objectMapper" ref="htmlEscapingObjectMapper"></property>
	        </bean>
</mvc:message-converters>
</mvc:annotation-driven>

구글 만세!!!!!!!👍👍👍👍👍👍👍

✅ SQL injection

SQL 인젝션의 경우 Mybatis Framework #{}를 사용하여 preparedstatement 객체를 사용하도록 쿼리가 작성되어있었다.

기본적으로 PreparedStatement는 값을 바인딩 하는 시점에서 전달된 값에 대한 특수문자, 쿼리등을 필터링하여 SQLinjection을 막는다.

아마 확인 담당자가 소스 제출시 쿼리단까지 직접 열어보지는 않은것 같다.
조치 예외로 인해 pass 내용이지만 중요 내용이라 적어보았다.

✅ eval, 예외처리시 printStack 및 getMessage로 인한 직접적인 error 사용자 노출

  • eval() 함수 : 인자로 들어온 문자열을 코드로 인식하는 함수

때문에 eval 안에 직접적으로 악성코드를 삽입하여 xss공격이 일어날수 있으므로 반드시 대체해야한다.

진행했던 프로젝트에서 대부분의 eval사용은 서로간의 함수호출시 전달한 파라미터의 id값으로 이벤트 지정을 위해 사용해서 getDoucmentById 함수로 대체했다(웹스퀘어5기준)

그 외에 e.printStacke.getMessage를 통한 error 메세지를 직접적으로 노출하는 내용도 모두 로그로 남겨두었다.

✅ 상대경로

파일 첨부시 임시 저장경로에 저장 후 was에 올리도록 해두었는데 (중앙화 서버로 파일을 올리고 내릴때 파일을 암복호화 하는 경우가 있어 임시저장경로에 두고 암복호화 로직 수행후 업로드및 다운로드)
개발서버와 운영서버로 나누어져 임시저장경로를 프로퍼티를 구분해두었는데(배포시 프로퍼티 덮어쓰기 설정)
임시 저장경로 + 파일명 -> 이런식으로 되어있어서 절대경로가 아닌 상대경로로 탐지오류가 있었던거 같다.
해당 내용도 조치예외지만 중요 내용이라 적었다.
상대경로 진행시 예상 밖의 영역에 대한 경로 문자열이 가능해져 시스템 정보누출, 서비스 장애 등을 유발 시킬 수 있기 때문에 절대경로를 통한 파일첨부가 올바르다.

✅ log4j

log4j 문제가 화두로 올라왔을때 아직 서비스를 오픈한 상태는 아니여서 출근해서 조치 절차에 따라 조치했다.

다행이도 아파치의 빠른 대처로 인해 단순 버전업을 통해 해결할수 있었는데 만약 실제 서비스 오픈중이였으면 새벽에 불려갔을까,,? 하는 끔찍한 생각이 들었다🙄🙄

좋은 웹페이지 즐겨찾기