[normaltic 취업반 5기] 2024-02-21 16주차 내용 정리 : 인가 취약점

2024. 2. 27. 10:44normaltic 취업반 5기/내용 정리

 

인가(Authorization)

 

  인가란 '인증' 과정을 거친 클라이언트가 이후의 여러 서비스에 접근 및 사용을 하기 위해서 필요한 권한을 확인하는 과정을 의미한다.

 

 

인가 취약점 대표적인 경우

 

  인가 취약점이 발생하는 대표적인 상황들은 다음과 같으며 각각의 상황들을 문제 실습을 통해 알아보도록 하자.

 

  1. 주석으로 접근 제한 하는 경우
  2. 인가 체크를 클라이언트 측에서 하는 경우
  3. 추측으로 접근하는 경우
  4. 파라미터 변조로 접근하는 경우

 

1) 주석으로 접근 제한 하는 경우

 

 

  • 실습 문제 : authorization 1
  • 문제 목표 : 미사일 발사 버튼 클릭
  • 주어진 조건 : [ID/PW] sfUser/sfUser1234

 

 

  실습 문제의 URL로 접근하면 로그인 페이지를 볼 수 있으며 아이디와 비밀번호를 입력 후 Sign in 버튼을 클릭하는 구조로 구성되어 있다.

 

 

  주어진 아이디와 비밀번호를 활용하여 로그인을 하게 되면 핵미사일 시스템 페이지와 발사 버튼은 관리자만 이용 가능하다는 내용을 볼 수 있다. 또한 발사 버튼은 관리자가 아니면 보이지 않도록 구성되어 있는 걸로 추측된다.

 

 

  프록시툴로 해당 페이지 코드를 확인해 본 결과 발사 버튼이 주석 처리 되어있다. 이는 관리자 권한을 가지고 있다면 주석 처리 대신 'Fire' 버튼이 활성화될 것이고 관리자 권한을 가지고 있지 않다면 주석 처리 하여 'Fire' 버튼이 비활성화될 것이라 추측해볼 수 있다.

 

 

  발사 버튼은 a 태그로 구성되어 있으며 버튼을 클릭하게 되면 링크된 파일을 요청하게 된다. 이때 링크된 파일명은 fire_attack_danger.php이며 URL에 직접 입력함으로써 발사 버튼을 클릭한 것과 같은 효과를 누릴 수 있다. 따라서, URL에 버튼에 링크된 파일을 입력하여 요청하게 되면 플레그를 획득할 수 있다.

 

 

2) 인가 체크를 클라이언트 측에서 하는 경우

 

[1] authorization 2

 

 

  • 실습 문제 : authorization 2
  • 문제 목표 : 미사일 발사 버튼 클릭
  • 주어진 조건 : [ID/PW] sfUser/sfUser1234

 

 

  실습 문제의 URL로 접근하면 로그인 페이지를 볼 수 있으며 아이디와 비밀번호를 입력 후 Sign in 버튼을 클릭하는 구조로 구성되어 있다.

 

 

  주어진 아이디와 비밀번호를 활용하여 로그인을 하게 되면 핵미사일 시스템 페이지와 발사 버튼은 관리자만 이용 가능하다는 내용을 볼 수 있다.

 

 

  관리자가 아닌 사람이 발사 버튼을 누르게 되면 권한이 없다는 알림 창이 발생하며 기능이 작동하지 않는다.

 

 

  프록시툴을 사용하여 해당 페이지 소스를 분석한 결과 발사 버튼 클릭 시 goMenu()라는 자바스크립트 언어로 이루어진 함수가 작동된다는 것을 알 수 있다. goMenu() 함수의 코드를 분석할 수 있다면 해당 문제를 해결할 가능성이 존재한다.

 

 

  HTML에서 자바스크립트 언어를 사용하기 위해서는 두 가지 방법이 존재한다. 첫 번째는 script 태그 안에 직접 입력하는 방법이고 두 번째는 외부에서 .js 파일을 적용시키는 방법이다. 해당 페이지를 분석한 결과 외부에서 user.js 파일과 game.js 파일을 적용시켜 자바스크립트 언어를 사용하는 걸로 추측할 수 있다. 이제 자바스크립트 함수의 출처를 알았으니 goMenu() 함수의 내용을 알아보도록 하자.

 

 

  user.js 파일과 game.js 파일을 확인해 본 결과 goMenu() 함수는 user.js 파일에 존재하는 것이 확인되었다. goMenu() 함수의 내용을 분석해 보면 code가 '1018'일 때 user_auth_check('admin',userLevel)의 값이 true이면 /fire_nuclear_Attack.php 파일로 이동시켜 주는 것을 알 수 있다.

 

  해당 내용을 알게 됨으로써 문제를 해결하는 방법은 두 가지 정도로 생각해 볼 수 있다. 첫 번째는 URL로 발사 버튼(./fire_nuclear_Attack.php)을 직접 입력하는 방법이고 두 번째는 응답 파라미터 값을 변조하여 관리자 계정이 아니더라도 버튼을 클릭하면 누구나 관리자 권한으로 접근한 것처럼 만드는 방법이다.

 

 

  두 가지 방법 중 가장 쉬운 방법은 URL에 직접 입력하는 방법이므로 직접 입력을 하게 되면 플레그를 획득할 수 있게 된다.

 

[2] authorization 3

 

 

  • 실습 문제 : authorization 3
  • 문제 목표 : 미사일 발사 버튼 클릭
  • 주어진 조건 : [ID/PW] sfUser/sfUser1234

 

 

  실습 문제의 URL로 접근하면 로그인 페이지를 볼 수 있으며 아이디와 비밀번호를 입력 후 Sign in 버튼을 클릭하는 구조로 구성되어 있다.

 

 

  주어진 아이디와 비밀번호를 활용하여 로그인을 하게 되면 핵미사일 시스템 페이지와 발사 버튼은 관리자만 이용 가능하다는 내용을 볼 수 있다.

 

 

  관리자가 아닌 사람이 발사 버튼을 누르게 되면 권한이 없다는 알림 창이 발생하며 기능이 작동하지 않는다.

 

 

  프록시툴을 사용하여 해당 페이지 소스를 분석한 결과 발사 버튼 클릭 시 goMenu()라는 자바스크립트 언어로 이루어진 함수가 작동된다는 것을 알 수 있다. goMenu() 함수의 코드를 분석할 수 있다면 해당 문제를 해결할 가능성이 존재한다.

 

 

  HTML에서 자바스크립트 언어를 사용하기 위해서는 두 가지 방법이 존재한다. 첫 번째는 script 태그 안에 직접 입력하는 방법이고 두 번째는 외부에서 .js 파일을 적용시키는 방법이다. 해당 페이지를 분석한 결과 외부에서 user.js 파일과 game.js 파일을 적용시켜 자바스크립트 언어를 사용하는 걸로 추측할 수 있다. 이제 자바스크립트 함수의 출처를 알았으니 goMenu() 함수의 내용을 알아보도록 하자.

 

 

  user.js 파일과 game.js 파일을 확인해 본 결과 goMenu() 함수는 user.js 파일에 존재하는 것이 확인되었다. goMenu() 함수의 내용을 분석하기 위해 살펴보면 직관적으로 알 수 없도록 코드가 난독화되어있는 것을 확인할 수 있다. 이를 해독하기 위해서는 시간이 오래 걸릴 가능성이 높기 때문에 해독하지 않아도 어떤 형식으로 이루어졌는지만 알아보도록 하자.

 

 

  code가 '9999'일 때 user_auth_check('admin',userLevel)의 값이 true이면 location.href 함수가 작동하고(물론 어떤 내용인지는 모른다.) 값이 true가 아니면 권한이 없다라는 알림창을 발생시킨다는 것을 알 수 있다. 문제를 해결하기 위해서는 code가 '9999'일 때 어떤 기능이 작동되는지 알아보아야 한다. 그러기 위해서는 user_auth_check('admin',userLevel)의 값을 true로 만들어야 if 문 안의 코드를 작동시킴으로써 해당 코드가 어떤 기능을 하는지 알 수 있게 된다. 

 

  user_auth_check('admin',userLevel)의 값이 true가 되려면 userLevel의 값이 'admin'이 되어야 하고 userLevel의 값은 goMenu('9999',userLevel)에서 전달되므로 응답 파라미터 변조를 통해 goMenu 함수의 userLevel 인자값으로 'admin'을 입력해 주면 될 것이다.

 

 

  index.php 페이지의 응답 파라미터를 goMenu('9999','admin')로 변조한 후 발사 버튼을 클릭하게 되면 플레그를 획득할 수 있다.

 

 

3) 추측으로 접근하는 경우

 

 

  • 실습 문제 : authorization 4
  • 문제 목표 : 관리자 권한으로 공지사항에 게시글 작성
  • 주어진 조건 : [ID/PW] sfUser/sfUser1234

 

 

  실습 문제의 URL로 접근하면 Login 버튼과 문의 게시판 버튼을 볼 수 있으며 Login 버튼을 클릭하면 로그인 페이지로 이동하게 된다. 로그인 페이지는 아이디와 비밀번호를 입력 후 Log In 버튼을 클릭하는 구조로 구성되어 있다.

 

 

  주어진 아이디와 비밀번호를 활용하여 로그인을 하게 되면 세 버튼이 보이는데 이중 '공지 사항' 버튼을 클릭하게 되면 하나의 게시글이 작성된 게시판 페이지로 이동하게 된다. 문제의 목표는 해당 페이지에서 게시글을 작성하는 것이나 게시글을 작성하기 위한 버튼 같은 것이 존재하지 않는다.

 

 

  게시판 페이지에서 딱히 원하는 정보가 없기에 작성되어 있는 게시글 내용을 확인해 보았다. 그렇지만 이마저도 아무런 정보가 주어지지 않았다. 그렇다면 아무런 정보가 없는 시점에서는 맨땅에 헤딩하듯이 추측을 통한 해결 방법을 찾아야 한다. 

 

 

  여기서 한 가지 추측해 볼 점은 바로 각 파일의 이름이다. 게시판 페이지의 이름은 notice_list로 이루어져 있고 게시글의 내용을 읽는 페이지 이름은 notice_read로 이루어져 있다. 그렇다면 게시글을 작성하는 페이지 이름은 작성하다는 의미의 영단어인 write를 사용하여 notice_write라는 이름으로 작성되지 않았을까라는 추측을 해볼 수 있다. 

 

 

  위 추측에 따라 URL에 notice_write.php 페이지를 요청했더니 게시글을 작성할 수 있는 페이지로 이동되었다. 

 

 

  게시글의 제목과 내용을 적고 create 버튼을 클릭했더니 플레그를 획득할 수 있었다.

 

 

4) 파라미터 변조로 접근하는 경우

 

 

  • 실습 문제 : authorization 5
  • 문제 목표 : 관리자 권한으로 공지글 읽기
  • 주어진 조건 : [ID/PW] sfUser/sfUser1234

 

 

  실습 문제의 URL로 접근하면 Login 버튼과 문의 게시판 버튼을 볼 수 있으며 Login 버튼을 클릭하면 로그인 페이지로 이동하게 된다. 로그인 페이지는 아이디와 비밀번호를 입력 후 Log In 버튼을 클릭하는 구조로 구성되어 있다.

 

 

 

 

  주어진 아이디와 비밀번호를 활용하여 로그인을 하게 되면 세 버튼이 보이는데 이중 '공지 사항' 버튼을 클릭하게 되면 게시글이 작성된 게시판 페이지로 이동하게 된다. 문제의 목표는 해당 페이지에서 admin이 작성한 게시글을 읽는 것이 목표이다.

 

 

  'flag 임시 저장'이라는 제목을 가진 게시글을 클릭하여 읽으려고 하면 권한이 없다는 알림 창이 발생하여 읽을 수 없게 된다.

 

 

  프록시툴을 사용하여 확인해 봐도 해당 게시글의 내용을 읽을 수 있는 별다른 정보가 없는 걸로 판단이 되었다. 그렇다면 문제의 목표인 관리자가 작성한 게시글의 내용을 읽는 방법은 없는 것인가?라는 물음에 대한 답으로 한 가지 얘기할 수 있지만 이는 웹 개발을 어느 정도 해본 사람이어야 이해하기 어렵지 않다.

 

  웹을 개발하는 과정에서 게시판 관련으로 개발을 하다 보면 어떤 메커니즘으로 작동되는지 어느 정도 알게 된다. 게시글을 작성하면 작성된 게시글을 식별하는 넘버가 같이 DB에 저장되고 작성된 게시글의 내용을 HTML 상에 출력을 할 때에는 식별 넘버로 구분 후 DB에서 조회를 하는 구조이다. 즉, 각 게시글마다 식별 넘버가 존재하고 원하는 게시글의 내용을 출력하고 싶을 때 해당하는 게시글의 식별 넘버를 파라미터 값으로 입력한다면 해당 게시글의 내용을 알 수 있다는 얘기이다.

 

  위 내용은 각 게시글이 어떤 방식으로 구분되는지를 설명한 거고, 다음으로는 게시글의 내용을 출력하는 페이지가 한 곳이 아니라는 점을 알아야 한다. 게시글의 내용을 읽기 위해서는 게시글의 내용이 출력되는 페이지를 요청하면 되는데, 게시글의 내용이 출력되는 페이지는 최소 두 곳이 존재한다. 하나는 게시글의 내용을 읽는 페이지, 다른 하나는 게시글의 내용을 수정하는 페이지이다.

 

  위에서 설명한 내용들을 토대로 추측해 본 문제 해결을 위한 시나리오는 읽고 싶은 게시글의 식별 넘버를 확인한 후 게시글 수정 페이지의 파라미터 값으로 식별 넘버를 입력한다면 해당하는 게시글의 내용이 출력될 것이다라는 내용이다. 물론 이 시나리오에서 가정된 조건은 게시글을 읽는 페이지에서만 권한이 제한되어 있고, 게시글 수정 페이지에는 권한이 제한되어 있지 않다는 점이다. 그렇다면 위 시나리오대로 문제 해결을 위한 작업을 수행해 보도록 하자.

 

 

  먼저 읽고 싶은 게시글의 식별 넘버를 확인한다. 게시글의 제목을 클릭하면 권한이 없습니다라는 내용과 함께 알림 창이 발생하지만 해당 게시글의 URL은 표시된다. 게시글의 식별 넘버는 '42'로 확인이 되었다. 그다음으로는 게시글 수정 페이지의 URL을 확인하는 작업이다.

 

 

  게시글 수정 페이지로 이동하려면 먼저 게시글을 작성해야 한다. 게시글의 제목과 내용으로 'TEST'를 입력하고 게시글을 작성한다.

 

 

  작성한 게시글을 읽기 위해서 게시글을 클릭하게 되면 아래의 세 버튼이 존재하는 걸 확인할 수 있다. 이곳에서 '수정'이란 버튼을 클릭하게 되면 게시글을 수정하는 페이지로 이동하게 된다. 게시글 수정 페이지로 이동하여 URL을 확인하도록 하자.

 

 

  게시글 수정 페이지 이름은 notice_update.php이며 게시글 식별 넘버를 파라미터로 받고 있는 것을 확인할 수 있다. 다음으로 아까 확인한 게시글의 식별 넘버인 '42'를 '119' 대신 입력하도록 하자.

 

 

  그러면 식별 넘버 '42'인 게시글의 내용이 출력되어야 하는데 권한이 없다는 알림 창이 발생함과 동시에 게시판 페이지로 이동이 되었다. 

 

 

  프록시툴로 확인해 본 결과 빨간 박스 안에 있는 코드들로 인해 식별 넘버 42 게시글의 수정 페이지로 이동되지 않는 것을 확인할 수 있었다.

 

 

  이는 응답 파라미터를 변조함으로써 해결을 할 수 있으므로 인터셉트하여 문제가 되는 자바스크립트 코드를 제거했더니 게시글의 내용이 출력되었고 플레그를 획득할 수 있었다.