티스토리 뷰

반응형

이번 내용은 기능(Function) 레벨에서의 Access Control 부재에 대한 내용이다.

이전에 진행했던 객체 단위의 Access Control과는 다르게 이번에는 기능 단위의 Access Control 이다.

 

첫 번째 퀴즈는 숨겨진 기능이 있는지 확인하는 것이다.

 

 

우선 눈에 보이는 메뉴로는 아래와 같이 2개 메뉴와 총 5개의 기능이 있다.

  • Account -> My Profile, Privacy/Security, Log Out
  • Messages -> Unread Messages, Compose Message

 

우선 숨겨진 기능이 무엇인지 찾으라고 하였으니, 가장 먼저 생각 나는 것은, 권한에 따라 메뉴를 숨겼는지 보기 위해 클라이언트 코드를 확인해본다.

역시 Admin 권한으로 제공되는 메뉴가 3개가 있었다.

  • Users : /access-control/users
  • Users : /access-control/users-admin-fix
  • Config : /access-control/config

이번 퀴즈에서는 2개의 답을 요구하였으니, Path가 아닌 메뉴명(Users, Config)이였을 것이다.

 

 

 

두 번째 퀴즈는 Jerry 라는 유저의 해시정보를 확인하라는 것이다.

이전 퀴즈에서 확인했었던 관리자 기능에 유저정보를 확인할 수 있는 기능이 있었으니, 이 URL을 호출해본다.

 

500 에러가 발생한 것으로 보아, 해당 URL은 사용이 가능한데, 전달된 값에 문제가 있는 것 같다.

우선 가장먼저 웹페이지로 호출하는 대신 API로 호출하기 위해 Content-Type을 Json타입으로 변경해서 다시 요청해보았다.

 

 

이렇게 하니 유저정보를 확인할 수 있었고, 여기에서 Jerry 유저의 Hash 정보를 확인할 수 있었다.

 

이렇게 확인한 Hash 정보를 제출해서 두 번째 퀴즈도 통과하였다.

 

마지막으로 세 번째 퀴즈는 위에서 사용한 URL을 사용할 수 없다는 가정하에 다시 한번 Jerry의 Hash 정보를 확인해서 제출하는 것이다.

그럼 이전에 확인했었던 다른 URL을 보면,"/access-control/users-admin-fix" 이다.

유추해보면, 아무래도 권한상승을 통해 정보를 확인해보라는 것 같다. 

 

해당 Path로 요청해보면, 이전 유저정보 확인과 같이 API인것으로 보여 JSON 타입으로 요청하였으나, 403 오류가 발생하는 것을 확인할 수 있었다. 그럼 이제 어떻게 하면 해당 기능을 이용할 수 있을까?

 

 

그런데 위 요청은 내가 정보를 확인해보기 위해 GET Method를 사용하였었는데, 실제로 내가 권한을 획득해야 하므로 POST Method를 사용하여 정보를 업데이트 해보았다. 

입력 데이터는 이전에 유저정보에서 사용자에게 제공했었던 정보 항목(username, admin, userHash)에서 Admin 권한을 부여하도록 username과 admin을 업데이트하도록 파라미터를 구성하여 전달해보았더니, 해당 요청이 성공적으로 처리 된 것을 확인할 수 있었다.

 

아마도 이로서 내 계정은 Admin 권한을 부여받았을 것이고, GET 메서드를 사용하였을 때 권한으로 거부되었었던 기능을 다시 요청해본다.

이로서 다시 모든 유저의 정보를 확인할 수 있었고, 여기서 Jerry의 Hash 정보 또한 확인하여 답을 제출할 수 있었다.

 

 

 

사실 많은 개발자들이 이러한 기능 레벨에서의 Access Control을 제대로 하지 않는 경우가 많다.

내가 경험한바로는 크게 2가지 케이스가 발생한다.

 

첫 번째는 이번 퀴즈의 내용과 비슷하게 기능에 따라 권한검증을 하지 않고 메뉴만 보이지 않도록 하는 것이다. 

두 번째는 특정권한에게만 제공되어야 하는 페이지에 대해서만 권한 검증을 하는 것이다. 예를 들어, 인사관리 페이지에 대해서는 권한검증을 수행하지만, 인사관리 데이터 다운로드에 대해서는 권한검증을 하지 않는 것이다.

 

이러한 리스크 또는 취약점을 제거하기 위해 기능별 권한검증이 반드시 필요하며, 특히 (Java기준) 각 Method 별 권한검증을 체크하는 것 보다는 Controller 전체에 대한 권한검증이 체크되도록 구현하는 것이 조금 더 안전하게 구현될 수 있다.

이는 세번째 퀴즈 또는 두 번째 케이스와 같이 기능을 제공하는 페이지에 대해서만 권한검증을 하는 것이 아닌 관련 모든 기능에 대해서 일괄적으로 권한검증이 적용될 수 있도록 하기 때문에, 개발자가 실수를 하더라도 최소한의 권한검증이 적용되므로 조금 더 리스크를 줄일 수 있다.

 

이번 퀴즈에서는 기능에 대한 권한검증 외에도 몇가지 취약점이 더 존재한다.

 

첫 번째는 유저 패스워드 정보를 제공한다는 것이다.

아무리 해시된 값이라 하더라도 패스워드 정보는 누구에게도 제공되지 않아야 한다. 유저의 패스워드를 해시하는 이유는 누구에게도 패스워드 정보가 노출되지 않도록 방지하는 것이 가장 큰 목적 중 하나이다. 해시된 데이터라 하더라도 상황에 따라 계정정보 탈취에 이용될 수 있으니 어떠한 경우에도 패스워드 정보를 제공하지 않아야 한다.

src/main/java/org/owasp/webgoat/lessons/missingac/MissingFunctionACUsers.java
src/main/java/org/owasp/webgoat/lessons/missingac/DisplayUser.java

 

두 번째는 관리자가 패스워드를 변경할 수 있다는 것이다. 

이 부분은 패스워드 초기화 기능에서도 많이 언급되는 부분인데, 관리자가 본인의 패스워드가 아닌 다른 유저의 패스워드를 직접 입력하게 될 경우, 관리자에게 패스워드 정보가 노출된다. 패스워든 정보는 어느 누구에게도 노출되지 않아야 하기 때문에 관리자에 의해 입력되지 않도록 해야 한다. 만약 유저의 패스워드를 초기화 해야 할 경우라면, 유저의 이메일 등으로 패스워드 초기화 링크를 전달하여, 유저에 의해 직접 패스워드를 변경할 수 있도록 하거나, 아니면 소스코드를 통해 패스워드 정책이 적용된 임시 패스워드를 생성하여 SMS 또는 EMail로 전달하고, 임시 패스워드를 사용하여 로그인 시 패스워드 변경 페이지로 리다이렉트 하여 사용자가 패스워드를 직접 변경하여 사용하도록 가이드 하는 것이 좋다. 

src/it/java/org/owasp/webgoat/AccessControlIntegrationTest.java

 

세 번째는 변경이 불가능해야 하는 정보를 변경할 수 있다는 것이다.

이 부분은 위 내용과 연결이 되는 부분이기도 하다. 만약 패스워드 변경 기능에 사용된 기능(/users-admin-fix)이 패스워드 변경이 아닌 권한 변경만을 위한 기능으로 설계되었었다면, 변경이 불가능해야 하는 정보(여기서는 Password)를 전달하더라도 서버 측 코드에서 해당 정보는 업데이트가 되지 않도록 로직 및 쿼리를 구성해야 한다. 하지만 해당 코드 및 쿼리는 객체 단위로 데이터를 전달받아 사용하고 있고, 변경이 불가능해야 하는 정보가 포함되어 있더라도 함께 정보를 업데이트 하고 있다. 특히 Profile 변경 기능에서 이러한 케이스가 많이 발견된다. 이는 아이디, 이름, 주소, 휴대폰번호 등과 같이 변경이 불가능해야 하는 정보이거나 점유인증이 필요로 하는 정보를 제한없이 변경하여 인증도용 등에 활용될 수 있다.

 

네 번째는 안전하지 않은 Hash 알고리즘이 사용되었다는 것이다.

현재 소스코드에서는 단순히 보여주기 위해 Hash가 사용되었으나, 만약 이러한 Hash 알고리즘이 패스워드 저장에도 사용되었다면, 이는 안전하지 않은 알고리즘이 사용되었다고 할 수 있다. 현재 소스코드에서는 단순히 SHA-256 알고리즘을 사용하고 있으나, 최근에 패스워드를 안전하게 저장하기 위해서는 PBKDF2 또는 BCrypt 와 같은 안전한 암호화 알고리즘 사용이 권장되고 있다. 

(참고: https://nordvpn.com/ko/blog/what-is-bcrypt/)

src/main/java/org/owasp/webgoat/lessons/missingac/DisplayUser.java

 

다섯 번째는 관리자 기능을 제공한다는 것이다.

일반 서비스 내 관리자 기능을 함께 제공하는 것은 상당히 위험하다. 일반 서비스(특히 외부 오픈된 서비스)에는 누가 접속할지 모르고 누구에게나 접근을 허용할 수 있기 때문에 악의적인 사용자에 의해 다양한 사이버 공격이 시도될 수 있다. 그렇기 때문에, 이렇게 관리자 기능을 함께 제공한다는 것은 해커와 같은 악의적 사용자에게 관리자 기능을 접근하도록 허용해 줄 수 있는 구멍을 제공해 줄 수 있게 된다. 그렇기 때문에 관리자 기능은 별도의 서비스로 분리하여 제공해야 한다. 

 

여섯 번째는 권한 상승에 대해 제한이 없다는 것이다.

이 부분은 현재 권한이 일반유저와 관리자로 2개만 존재해서, 기능 레벨의 권한검증과 비슷한 사항이 포함되기는 하지만, 일반적으로 권한을 상승시킬 때, (특정 케이스를 제외하고 대부분) 자신이 가진 권한보다 높은 권한을 부여하지 않도록 제한되어야 한다. 하지만 해당 기능에서는 현재 권한으로 어디까지 권한을 변경시킬 수 있는지에 대한 제한로직이 구성되어 있지 않다.

src/main/java/org/owasp/webgoat/lessons/missingac/MissingFunctionACUsers.java

 

일곱 번째는 중요기능에 대해 감사로그가 충분하지 않다는 것이다.

권한 변경과 같은 중요기능은 감사로그를 통해 누가 누구의 권한을 어떤 권한으로 변경하였는가 등의 내용을 기록해야 한다. 이는 악의적인 사용자에 의해 발생한 권한상승인지, 정상적인 운영을 위해 발생한 권한상승인지 알 수 없기 때문에, 이러한 권한상승에 따른 사이버 공격이 발생하였을 때 문제 원인을 찾거나 사후처리를 하는 것에 매우 어려움을 제공할 수 있기 때문에, 반드시 권한변경에 대해서 감사로그를 기록해야 한다.

 

 

 

 

 

반응형
댓글
반응형
최근에 올라온 글
Total
Today
Yesterday