ZAP에서 우아하게 Cookie 기반 Auth 테스팅하기

Web의 Authorization, Permission, Access Control 테스팅 시 어떤 방법을 활용하시나요? 보통 보안 테스팅 단계에선 권한을 바꿔가며 수동으로 테스트하거나 자동화된 도구를 통한 테스팅, 또는 두개를 병행하여 테스트합니다. 그리고 자동화된 테스팅을 위해선 Burpsuite, ZAP, CLI Tools 등 여러가지 도구를 사용합니다.

e.g

  • Burpsuite: Authz, AuthMatrix, Auth Analyzer, Autorize
  • ZAP: Access Control Testing, Scripting
  • CLI: Authz0

개인적으로 Burpsuite을 사용했을 땐 Authz, ZAP으로 넘어온 이후에는 Access Control Testing과 Scripting을 주로 사용 했었는데요. 오늘은 ZAP의 방식에서 가지고 있던 문제점을 해결한 나름대로 최적의 방법을 찾아 공유드려봅니다.

참고로 개인적이긴 하지만 ZAP, Burpsuite을 통틀어서 이 방법이 쉬우면서 유연하여 가장 좋았습니다 :D

Cookies X Endpoints

Auth 테스팅의 경우 보통 전수조사가 필요하기 떄문에 그림으로 그려보면 이렇습니다.

3 X 3이지만 복잡해보입니다. 실제 서비스에선 비교도 안되게 많은 권한과 API가 존재합니다 😵‍💫

Problem

ZAP에서 Auth 테스팅을 위해선 Access Control Testing 기능이나 Scripting을 이용해야 합니다. 다만 여기에는 불편한 점이 하나 있는데, 바로 인증 방법을 사전에 등록해야 한다는 점입니다. 물론 자동으로 인증 과정까지 포함하여 테스트하기 떄문에 떄때로 굉장히 편리하기도 하지만 로그인 구간에 복잡한 암호화 로직이나 2차 인증 등 인증 부분을 ZAP에서 추가하기 어렵거나, Scripting으로도 해결하기 어려운 경우들이 있습니다.

Method Description
Manual Authentication 자동으로 인증을 수행하지 않아요.
Form-base Authentication Login URL, Form 정보를 이용하여 인증을 수행합니다.
HTTP, NTLM Authentication HTTP Auth를 이용해 인증을 수행합니다.
Script-base Authentication 스크립트를 이용해 인증을 수행합니다. (ZAP Script)
JSON-base Authentication Form과 비슷합니다. 다만 Body가 JSON 😁

참고

Script-base가 이러한 부분들을 해결해 줄 수 있긴 하지만, 직접 구현하려면 상황에 따라 시간이 많이 걸릴 수도 있습니다. 이럴 때 가장 간절하게 느껴지는건 Cookie를 직접 사용하고 싶은 욕구입니다.

Session in Zest

기존 인증 로직을 이용하기 어려우니 Scripting쪽으로 고민하게 되었고 여러가지 테스트하다가 재미있는 사실을 하나 발견했습니다. 바로 타입이 Session Managements인 Zest script에서 첫번째 요청의 Cookies에 등록된 정보가 이후 요청에서도 재 사용한다는 점입니다. 결국 처음 요청에서 쿠키만 잘 지정하면 뒤에 요청은 모두 자동으로 적용받게 됩니다.

Testing Auth

Create a script

먼저 Zest script를 생성합니다. Record로 진행셔도 되고, Scripts에서 새로 만들거나 요청을 하나 골라 우클릭 후 추가하여 생성해셔도 됩니다. 이 때 Type이 Session Management가 되도록 변경해줍니다.

Add endpoints

이제 테스트할 API를 추가합니다. History에서 원하는 node를 선택(또는 다중선택)하고 우클릭 후 Add to Zest Script로 우리가 만들어준 스크립트로 추가합니다.

저는 7개의 페이지를 추가했습니다. 테스트 대상이 많다면 Record로 추가하는걸 추천합니다 :D

Set cookies

자 이제 Cookie 처리를 위한 dummy request 하나를 만들어줍시다. 우리가 작성하는 Script(Scripts 탭)에서 우클릭 후 Add Request를 눌러줍니다. 구별을 위해 임의로 dummy란 파라미터를 붙여서 추가했습니다.

그리고 Cookies 탭에서 세션 쿠키로 사용될 값을 넣어줍니다.

Test!

자 이게 Script Console에서 실행을 눌러주면 우리가 추가한 URL에 대해 하나씩 재생하며 테스트합니다. Zest 사용 시 Assertion을 기본으로 잡아주는데 오차 범위가 적은편이라 그냥 사용하셔도 좋습니다. 만약 좀 더 디테일하게 검증하고 싶다면, 우리가 만든 스크립트 설정에서 조정해줍니다. (Res code, size 등)

자 이제 각 Req를 보면 맨 처음 Req가 아닌 후속 Req에도 공통적으로 쿠키가 동일하게 추가되어 전송되는 것을 알 수 있습니다.

자 이제 Script의 Cookies에서 값만 수정하여 실행하면 각 세션 쿠키 별 결과를 쉽게 얻을 수 있습니다. 테스트가 필요한 권한이 많고, Endpoint가 많은 경우 정말 빠르고 꼼꼼하게 체크할 수 있습니다. 개인적인 팁이 하나 있다면 처음 dummy req의 파라미터 값에 계정명이나 권한에 대한 약자를 넣어 테스트합니다. 그러면 결과에서 어떤 계정을 테스트했는지 쉽게 확인할 수 있습닌다.

Reuse Script

테스트가 마무리되면 스크립트를 저장해두는게 좋습니다. 해당 기능이 수정되거나 주기적으로 테스트가 필요할 수 있는데, 이 떄 기존 스크립트를 재 사용하면 빠르게 테스트할 수 있습니다. (신규 API Endpoint 추가도 간단하구요)

또한 Zest 자체가 CLI 기반 실행도 가능하기 떄문에 살짝만 다듬어주면 정기적으로 해당에 대한 Auth 테스트를 쉽게 진행할 수 있습니다.

# [auth.sh]
# sed "s/pleasechangeme/$1/g" abcd_service_auth_tesing.zst > $1.zst
# ./zest -script $1.zst

# Run script
cat cookies.txt | xargs -I % ./auth.sh %

CLI 기반 실행에 대한 내용은 “Zest script in CLI” 글을 참고해주세요!

Conclusion

Burpsuite의 Addon 중 일부는 Cookie 기반의 테스팅을 지원합니다. 오늘 글과 거의 유사한 느낌이겠지만 많은 API를 선별하여 테스트하는데 있어서는 ZAP+Zest 방식이 훨씬 효율적입니다.

재사용이나 확장의 이점도 크니 ZAP 유저라면 기본 제공되는 Authentication과 Zest의 방식들을 적절히 활용하면 좋을 것 같고, Burp 유저라면 확장성을 고려한 Auth 테스팅 Addon을 한번 만들어보는 것도 좋은 아이디어가 될 것 같습니다.

저는 스크립트 뒤에 또 이것저것 붙여서 좀 더 쉬운 테스팅을 위한 방법들을 연구해 봐야겠네요 :D