관리 메뉴

코코야이야기

[시큐어코딩] 접근제어 본문

프로그래밍/보안

[시큐어코딩] 접근제어

코코야 2019. 7. 1. 23:12
반응형

[시큐어코딩] 접근제어

 

* 파라미터

- 사용자가 서버에 요청을 보낼 때 서버에게 전달해야 하는 값을 가지고 있는 변수

- 서버에게 전달되는 파라미터 값을 사용자가 임의적으로 변경하는 것을 "파라미터 변조"라고 함

 

* 파라미터 변조 사고의 원인

- 사용자의 요청에 대해 서버 애플리케이션에서 적절한 접근제어가 구현되어 있지 않아 발생함

 

* 파라미터 변조 사고의 대책

- 클라이언트로부터 요청되는 값(GET/POST 파라미터, 쿠키 메모리값 등)은 언제든지 조작될 수 있기 때문에 외부 입력값을 신뢰하지 말고, 반드시 검증을 수행하는 기능을 구현해야 함

 

* 파라미터 변조 4가지 진단

1) 진단 1

"파라미터 조작을 통해 허가되지 않은 작업이 실행되는가?"

- 공격자가 작업 요청이 어떤 방식으로 요청되는지를 체크해 허락되지 않은 삭제 작업을 시도할 수 있기 때문에 서버 애플리케이션이 요청되는 작업에 대한 사용자의 인가 체크가 제대로 이루어지지 않으면 파라미터나 URL 조작을 통한 침해사고가 나타날 수 있음

 

1] 대응기법 #1

허가되지 않은 작업 요청 시도를 방어하기 위해 개인정보 처리 페이지에 대한 사용자 검증 절차를 구현함

- delete 요청에 대해 요청하고 있는 사용자의 정보와 세션에 저장된 사용자의 정보를 체크하여 인가된 요청인지를 확인하도록 프로그램을 수정함

String id = request.getParameter("id");
String name = request.getParameter("name");
String action = request.getParameter("action");
String userid = request.getParameter("userid");

//실행결과 사용자에 대한 고객정보 삭제 (admin만 허용)
} else if("delete".equals(action) && "admin".equals(userid)){
  m = (MemberModel)session.getAttribute("member");
  if(m == null){
    buffer.append("사용자 정보 조회를 먼저 해주세요.");
  } else {
    service.deleteMember(m);
    session.removeAttribute("member");
    buffer.append(m.getUserId()+"님의 정보를 삭제하였습니다.");
  }
}

 

2) 진단 2

"파라미터 조작을 통해 다른 사용자의 정보 조회가 가능한가?"

 

2] 대응기법 #2

(1) Controller나 Service 컴포넌트에서 if문을 이용한 요청 유효성 검사

- 일반 사용자인 경우 반드시 세션에 저장된 사용자 ID와 조회 요청을 위해 전달된 파라미터 사용자 ID 값이 같은지 확인하는 코드를 추가함

//사용자 정보 조회 요청인 경우 DB에서 해당 사용자 정보를 조회한 결과를 응답
String userid = (String)session.getAttribute("userid");

if("view".equals(action)){
  if(id != null && !"".equals(id) &&
    ( ( !"admin".equals(userid) && id.equals(userid) ) || ("admin".equals(userid)) ) {
    m = serivce.findMember(id);
    if(m == null){
      buffer.append("등록되지 않은 사용자입니다.");
    } else {
      //조회한 사용자 정보는 세션에 저장
      session.setAttribute("member",m);
      displayResult(m);
    }
  } else {
    buffer.append("userid가 입력되지 않았습니다.");
  }
}

 

(2) Spring MVC 프레임워크 사용시 입력값 검증 : Validator, Model 컴포넌트에서 Annotation 설정으로 유효성 점검

- Model 객체의 값에 대한 유효성 검사를 위해 Annotation을 활용할 수 있음

Model 클래스 수정

- 입력값을 처리하기 위한 모델 컴포넌트에서 각각의 멤버 변수 값에 대한 유효성 체크를 Annotation으로 체크하도록 정의함

public class AccessControl{
  @NotEmpty
  private String id;
  
  @NotEmpty
  private String data;
  
  @NotEmpty
  @Length(min=4, max=6)
  private String action;
}

Validator 클래스 구현

- 입력값에 대해 해당 요청이 허가된 요청인지 확인하는 코드를 작성함

public class PersonValidator implements Validator {
  public boolean supports(Class clazz) {
    return Person.class.equals(clazz);
  }
  
  public void validate(Object obj, Errors e) {
    AccessControl ac = (AccessControl) obj;
    //해당 요청이 허가된 요청인지 확인하는 코드 작성
  }
}

Controller 클래스 수정

- 컨트롤러에서 입력 파라미터 값이 유효한지 검사가 수행될 수 있도록 @Valid Annotation을 모델 컴포넌트에 정의함

- 컨트롤러 또는 서비스 컴포넌트가 입력값에 대한 검증 작업을 수행할 수 있도록 validator 객체의 validate() 메서드가 호출되도록 코드를 작성함

@Autowired
private Validator validator;

@RequestMapping(value="/test/access_control_test.do", method=RequestMethod.POST)

@ResponseBody
public String testAccessControlPost(@Valid AccessControl control, HttpServletRequest request,
 HttpServletResponse response, HttpSession session){             
  validator.validate();
  /*
  ....
  */
}

 

3) 진단 3

"쿠키 변조를 통해 중요 정보 유출이 가능한가?"

- 쿠키에 포함된 ID 값으로 인가 받은 사용자인지 확인하는 로직이 구현되어 있는 경우, 쿠키값을 변조하여 다른 사용자 정보를 불법 취득하거나 비밀번호 변경을 통한 계정 도용이 발생할 수 있음

 

3] 대응기법 #3

중요한 쿠키값은 암호화하여 변조를 통한 중요 정보 유출을 방어함

- 쿠키에 저장되는 인증 정보는 안전하지 않지만, 쿠키 인증 방식을 사용해야 하는 환경이라면 쿠카값을 암호화해 공격자가 쿠키 안에 삽입되어 있는 인증값을 확인 및 변조할 수 없도록 해야함

- 서버로 전송되는 쿠키의 내용을 가로채더라도 암호화된 문자열을 복호화하지 않은 이상 인증값을 쉽게 변조할 수 없음

- 단 서버 선응에 영향을 줄 수 있으므로 영향도 검토 후 적용하는 것이 좋음

 

4) 진단 4

"클라이언트/서버 구조에서 사용되는 파라미터가 파라미터 조작 취약점을 가지고 있는가?"

- 파라미터 취약점은 웹에서 뿐만 아니라 서버/클라이언트 프로그램에서도 문제가 됨

 

4] 대응기법 #4

클라이언트/서버 구조에서 메모리 변조를 통한 파라미터 조작요청 위조는 서버 측에서 입력값 검증을 통해 통제할 수 있음

- 클라이언트 프로그램의 메모리에 로드되어 있는 사용자에 대한 정보를 조작하여 클라이언트 프로그램에서 읽어서 전송하게 만드는 것이 가능

- 서버 애플리케이션에서 클라이언트가 전송하는 정보를 다시 한 번 확인해 정확한 클라이언트의 정보가 수신되었는지 확인한 뒤 사용하도록 프로그램을 작성해 대응함

 

* Access Control

- 접근제어는 URL, 비즈니스 로직, 데이터, 서비스, 파일이나 리소스 등에 대해 일원화된 접근통제수행을 하기 위한 기법임

- 접근제어를 구현하기 위해서는 사용자의 정보를 세션에 저장할 때 사용자의 역할과 권한에 대한 정보도 같이 관리되어야 하며, 이런 역할과 권한에 대한 정보도 같이 관리되어야 하며, 이런 역할과 권한 정보를 기반으로 리소스에 대한 접근 통제가 가능하다록  ACL을 관리함

 

* ACL(Access Control List)

- 접근제어를 구현하기 위해 각각의 리소스에 대한 사용자의 권한이나 역할을 매핑해서 관리하는 목록임

- 일반적으로 리소스에 대한 랜덤한 값을 생성하여 랜덤값과 원본 리소스를 매핑 시켜서 관리하도록 구현하기도 함

 

* AC(Access Control)의 구현

- Access Control은 분석/설계 단계에서부터 사용자의 역할/권한, 관리 리소스, 접근 정책 등이 충분히 고려되어야 함

- 잘 만들어진 접근제어 프레임워크나 라이브러리 활용 : Spring Security ACL, ESAPI ACL ....

 

 

1) 구현기법 #1 ESAPI Access Control 예

- ESAPI는 OWASP 산하 프로젝트 그룹 중의 하나로, Enterprise Security Application Interface의 약어로 기업환경에서 사용 가능한 보안 라이브러리임

- ESAPI의 ACL 구성

통합구성요소 → 접근제어기(AC) → 접근제어 리소스(ACR) → 접근 또는 예외처리

- ESAPI의 ACL의 동작

(1) 시스템을 시작할 때 접근제어 매트릭스(ACM)가 ACR에 링크되어 있는 리소스를 읽어들임

--> AccessReferenceMap 객체로 만들어서 리소스의 접근을 통제

(2) AC는 ACR에 매핑하고 런타임 매개변수와 정적 정책파일 매개 변수를 전달함

(3) ACR은 자원을 역할에 할당하고 비정상적 복잡한 역할 요청을 평가함

 

URL 접근제어 예

String url = request.getParameter("url");
try {
  ESAPI.accessController().assertAuthorizedForURL(url)
  // 관리자권한으로 실행해야 하는 기능
} catch(AccessControlException e){
  // 관리자권한이 없는경우 실행해야 하는 기능
}

function 접근제어 예

static String BUSINESS_FUNCTION = "getCustomerName";
try{
  ESAPI.accessController().assertAuthorizedForFunction(BUSINESS_FUNCTION)
  // 업무로직 실행
} catch(AccessControlException e){
  // 업무로직 실행권한이 없는 경우 실행할 내용
}

서비스 접근제어 예

try{
  ESAPI.accessController().assertAuthorizedForService("PaymentGateway")
  // 서비스에 접근 권한이 있으면 실행할 내용
} catch(AccessControlException e){
  // 서비스에 접근 권한이 없는 경우 실행할 내용
}

파일 접근제어 예

String filename = request.getParameter("filename");
try{
  ESAPI.accessController().assertAuthorizedForFile(filename)
  // 파일에 접근 권한이 있으면 실행할 내용
} catch(AccessControlException e){
  // 업무로직 실행권한이 없는 경우 실행할 내용
}

데이터 접근제어 예

String reportName = request.getParameter("reportName");
try{
  Report report = persistenceLayer.getReport(report);
  ESAPI.accessController().assertAuthorizedForData("read", report)
  // 데이터 사용 가능
} catch(AccessControlException e){
  // ..
}

ACM(Access Control Matrix) 예

  Role 1 Role 2 Role 3
Resource1 Deny Grant SpecialCaseAccessControlRule
Resource2 Grant Deny Deny

- .csv 파일 또는 데이터베이스에 저장하여 관리하며, ACM과 정책파일(policy file)을 결합해서 Accecss Controller에 의해 실행되는 ACR을 정의함

 

간단한 ACR 샘플코드

public class EchoDynaBeanPolicyParameterACR extends DynaBeanPolicyBaseACR{
  /**
  * @return true iff policyParameter isTure is a Boolean set to true.
  * throws ClassCastException if runtimeParameter is not a Boolean.
  */
  public boolean isAuthorized(Object runtimeParameter) throws ClassCastException{
    return getPolicyParameters().getBoolean("isTrue");
  }
}

통합 컴포넌트 샘플코드

public class AccessContorlEnforcementInterceptor extends AbstractInterceptor {
  public String intercept(ActionInvocation invocation) throws Exception {
    ESAPI.accessController().enforceAuthorization(invocation.getAction(), invocation.getInvocationContext());
    return invocation.invoke();
  }
}

AccessController 컴포넌트 샘플코드

public void enforceAuthorization(Object key, Object runtimeParameter)
  throws org.owasp.esapi.errors.AccessControlException{
    boolean isAuthorized = false;
    try{
      AccessControlRule rule = (AccessControlRule)ruleMap.get(key);
      if(rule == null){
        throw new AccessControlException("AccessControlRule was not fount for key:"+key,"");
      }
      System.out.println("Enforcing Authorization Rule \"" +
        key + "\" Using class: " + rule.getClass().getCanonicalName());
      isAuthorized = rule.isAuthorized(runtimeParameter);
    } catch(Exception e) {
      throw new AccessControlException("An unhandled Exception was " +
        "caught, so we are recasting it as an " +
        "AccessControlException","",e);
    }
    if(!isAuthorized){
      throw new AccessControlException("Access Denied for key: " + key +
        " runtimeParameter: " + runtimeParameter,"");
    }
}

 

2) 구현기법 #2 Spring Security Access Control List

ACL 관리를 위한 정보 구축

- entry : 모든사용자와 모든 보안관련 테이블을 참조해서 요청한 사용자가 권한을 체크하기 위한 메인 테이블

- OBJECT IDENTITY : 관리대상인 오브젝트를 목록화

- SID : 오브젝트를 사용하는 사용자들을 목록화

- CLASS : 도메인 오브젝트의 식별 이름으로 자바의 풀 클래스 명을 목록화

- ACL 목록정보 : 애플리케이션 업무로직을 구현할 때 참조되어 사용자의 인가를 체크

 

Q : 파라미터 변조는 웹방화벽과 같은 보안솔루션으로 방어가 가능한가?

A :

일부는 가능하지만 정상적인 사용자가 정상적인 요청 범위 안에서 행하는 파라미터 변조 공격은 웹 방화벽으로는 차단 할 수없다.

일반적으로 WAF에는 애플리케이션 접근제어(URL ACL)기능을 제공한다.

하지만 이 기능은 웹서버의 모든 자원 중 사용자에게 허용해야 할 URL 리스트로 설정된 URL에 대한 접근만 허용하는 정책임. 이 허용 URL 설정을 통해서 의도되지 않은 중요 파일의 노출이나 서비스와 관계없는 취약한 프로그램의 노출을 차단할 수 있음. 하지만 허용된 범위 안에서의 조작된 요청은 차단하기 어렵다.

폼 필드 검사기능(Parameter ACL)은 웹 애플리케이션에 대한 공격의 대부분은 폼필드를 처리하는 action URL에 해당하는 프로그램에 대한 공격이며 애플리케이션에 대한 입력은 대부분 폼필드를 통해 이루어지기 때문에 웹방화벽의 핵심 기능도 폼필드 입력에 대한 검시가능으로 구현되어있다.

하지만 방화벽의 파라미터 ACL도 필드 길이제한, 형식제한, 상수값 변조검사, 차단패턴 검사기능을 제공하기 때문에 정상적인 입력값을 이용한 파라미터 변조공격은 웹방화벽에서 차단하기 어렵다.

 

* 총정리

파라미터 변조의 개넘과 취약점

- 파라미터는 클라이언트가 서버에게 작업을 요청할 때 "어떤 데이터에 대한 어떤 작업" 이라는 것을 정의하기 위해 전달하는 변수값을 말함

- 이 변수값은 이미 정해져 있는 값인 경우도 있고, 사용자가 입력하는 값일 수도 있음

- 서버 애플리케이션에서 사용자가 전송하는 파라미터 값에 대한 철저한 검증 작업을 수행하지 않고 요청을 처리하는 경우 사용자에게 허가되지 않은 작업이 수행되어 중요 정보가 노출되는 침해사고가 발생할 수 있음

접근제어

- 각 사용자별, 리소스별 역할과 권한을 할당하여 외부 사용자의 요청에 대해 해당 사용자가 해당 리소스에 대한 접근 권한이 있는지 확인한 뒤 사용 또는 예외 처리를 하여 권한이 없는 사용자가 리소스에 접근하지 못하도록 통제하는 "파라미터 변조" 취약점에 대한 보안 대응책임

반응형
Comments