본문 바로가기
프로그래밍/기타

[기타] 서비스의 일반적인 보안 취약성 - 2편

by 사바라다 2022. 11. 12.

안녕하세요. 오늘 포스팅은 이전 포스팅에서 다루지 않았던 서비스의 일반적인 보안 취약성 4가지에 대해서 알아보는 시간을 가져보겠습니다. 리마인드 해보면 이전 시간에 다루지 않은 기본 취약성 4가지는 아래와 같습니다.

  • 주입 (Injection)
  • 기밀 데이터 노출
  • 메서드 접근 제어 부족
  • 알려진 취약성이 있는 종속성 이용

주입 (Injection)

Injection 공격은 여러 범위에서 사용할 수 있는 공격입니다. 이는 서비스의 시스템에 특정 데이터를 집어넣어 서비스에서 기본적으로 제공하지 않는 정보를 취득할 수 있는 공격입니다. 여러 유형이 있으며 앞어 확인했었던 XSS 역시 주입 공격의 일종이라고 할 수 있습니다. 대표적으로는 SQL Injection, OS Command Injection 등이 있습니다.

주입 공격을 받게 되면 피해 서비스는 데이터 변경, 삭제, 무단 이용을 유발할 수 있습니다. 대표적인 SQL Injection의 예제를 한번 보도록 하겠습니다.

SELECT * FROM Users WHERE UserId = :UserId;

위의 SQL은 기본적으로 Users 라는 테이블에서 UserId를 통해 원하는 row 1개를 가져오는 일반적으로 많이 사용되는 SQL 구문입니다. :UserId 부분에 어떠한 값도 들어갈 수 있다고 해보겠습니다. 그 경우 공격자가 만약 105 OR 1=1 라고 하는 입력값을 넣었다고 해보겠습니다. 이 경우 최종적으로 완성되는 쿼리는 아래와 같습니다.

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

위 쿼리를 보시면 OR 1=1을 통해서 전 Users의 데이터가 유출 될 수 있음을 알 수 있습니다. 이러한 Injection 공격은 단순하지만 치명적이기 때문에 반드시 대비가 되어야합니다.

기밀 데이터 노출

민감한 개인 정보는 절대로 그대로 평문으로 저장하거나 로깅해서는 안됩니다. 기밀 데이터의 공개는 가장 기초적이고 단순한 취약성 이지만, 여전히 가장 많이 하고 있고 가장 많이 검출되는 취약점 중의 하나로 남아있습니다. 이러한 민감한 데이터의 노출과 관련되어서는 서비스의 콘솔 로그에 노출시키거나, MySQL에 저장, 그리고 ElasticSearch에 저장되어지기도 합니다. 이는 개발자들이 경각심을 가지고 개발할 필요가 있습니다. 특히, 잘못된 저장 방식은 법을 위배하는 행위가 될 수도 있습니다.

이뿐만 아닙니다. 예외적인 resonse 상황에서 서비스의 내부 정보를 보여주지 않는 것도 또한 중요합니다. 이를 통해 공격자는 url path, 의존성의 버전 등의 정보를 알 수 있게 될 수 있으며 이를 공격에 활용할 수 있습니다. 아래 예제를 한번 보도록 하겠습니다.

{
    "status" : 500,
    "error" : "INTERNAL SERVER ERROR",
    "message" : "not connect 10.2.1.3:8080",
    "path" : "product/123"
}

위 정보를 통해서 우리는 product/123 path로 요청을 보냈는데, 내부에서 10.2.1.3:8080의 연결에 실패했다는 것을 호출자가 알 수 있습니다. 이러한 메시지는 만약 악의를 가지고 있는 사람이 있다면 이러한 내부 정보들을 모아서 악의적인 공격에 사용할 수 있습니다.

또 다른 예제로는 java의 경우 stacktrace를 반환하는 것입니다. 아래의 예제를 보도록 하겠습니다.

java.lang.ArithmeticException: / by zero
    at ServiceController.booltest(ServiceController.java:2677)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)

위와 같은 응답을 줬을 때 클라이언트에서는 해당 서비스가 Spring Framework 기반의 서비스라는 것을 알 수 있습니다. 이는 클라이언트에서는 전혀 알 필요가 없는 정보입니다. 이런 정보 유출을 우리는 최소화 할 필요가 있습니다.

메서드 접근 제어 부족

일반적으로 서비스의 endPoints 부분에 보안 로직을 적용하고 이를 활용합니다. 하지만 경우에 따라서는 Repository 계층에도 특정한 권한을 설정할 수 있습니다. 이렇게 하면 해당 Repository를 사용함에 있어서 무조건적인 권한 체크가 필요하다는 것을 같이 일하는 팀원들이 알 수 있어서 EndPoints를 구성할 때 실수를 막을 수 있습니다.

알려진 취약성이 있는 종속성

우리는 개발할 때 다양한 Open Sources를 사용합니다. 이들은 완벽할 것이라는 기본적인 생각으로 많이 사용하기 때문에 보안에 취약할거라는 생각을 하지 않기 쉽습니다. 하지만 이 또한 우리와 같은 개발자가 만든것이기때문에 실수가 있을 수 있습니다. 이러한 동향에 기민하게 움직일 수 있다면 서비스의 보안에 조금 더 도움이 될 것입니다. 아래에서는 최근에 있었던 Open Source 보안 이슈를 몇가지 링크해보았습니다.

마무리

오늘은 이렇게 서비스 개발에서 일반적으로 발생할 수 있는 보안 취약점에 대해서 알아보는 2번째 시간을 가져보았습니다.

다음 시간부터는 Spring Security 실습을 통해서 서비스 보안을 챙겨보는 시간을 가져보도록 하겠습니다.

감사합니다.

참조

[1] 스프링 시큐리티 인 액션

[2] https://www.w3schools.com/sql/sql_injection.asp

댓글