본문 바로가기

4-2. 2024-1 심화 스터디/웹 취약점 분석

[2주차] Broken Access Control 취약점 분석/실습

Broken Access Control (접근 제어 오류)

  • 권한이 없는 사용자가 민감한 데이터나 시스템에 접근할 수 있도록 허용하는 취약점. 인증 및 권한 부여가 제대로 구현되지 않았거나 이러한 제어가 실행되는 방식에 취약점이 있을 때 발생한다.
  • 사용자별 접근 제어가 제대로 적용이 되지 않는 취약점
  • 주어진 권한을 벗어난 행동을 야기함
  • 관리자 페이지 등에 공격자가 접근할 수 있음

[공격 방법]

1. Brute Force

  • 완전 탐색 알고리즘. 가능한 모든 경우의 수를 모두 탐색하면서 요구조건에 충족되는 결과만을 가져온다. 이 알고리즘은 예외 없이 100%의 확률로 정답만을 출력한다. (순차탐색, 깊이 우선 탐색, 너비 우선 탐색 사용) 때문에 툴을 사용해 가능한 모든 경우의 수를 다 탐색한 후 pw를 찾아낼 수 있게 된다.
  • 비밀번호, PIN, 암호화 키를 무작위로 계속해서 입력함으로써 해킹을 시도하는 공격 방식

    [대응방법]

  • 관리자 인터페이스: 별도의 포트 번호로 제공 or HTTPS로 구현
  • 강력한 비밀번호 사용
  • 로그인 횟수/재시도 시간 제한, 2단계 인증 등을 설정하여 방어
  • 응답을 느리게 한다. (가능하면 난수로)
  • 일정 시간동안 락킹 (아예 일정 시간동안 로그인 시도를 딜레이 해 무력화)
  • captcha 등 실제 사람이 입력하는지 확인 할 수 있는 수단을 사용

 

2. Weak Session ID

: 사용자 식별을 위해 할당되는 세션 ID가 단순하면 쉽게 위조가 가능해지고, 공격자가 타 사용자의 세션 ID를 쉽게 추측해 접근할 수 있게 된다.

 

    [대응방법]

  • 랜덤 정수 생성 함수를 이용해 매번 세션 아이디를 랜덤하게 발급하도록 한다.
  • sha1 등의 안전한 암호화 알고리즘을 통해 암호화를 진행한다.
  • session time out 등의 기능을 이용해 다른 사용자의 세션을 이용해 권한 탈취를 하기 어렵게 해야 한다.

 

3. Authorization Bypass

: 인증 우회 취약점. 공격자가 무단 액세스를 얻기 위해 장치의 인증 메커니즘을 우회할 때 발생한다. 공격자가 다른 사용자의 자격 증명을 무단으로 사용해 액세스할 수 있다.

 

    [대응 방법]

  • 잦은 패치로 앱과 서버를 최신 상태로 유지한다.
  • 다단계 인증 등의 인증을 시행해 본인이 아니면 접근할 수 없도록 조치한다.
  • 가능한 모든걸 암호화한다.
  • 데이터 파일 & 폴더를 보호한다.

[실습]

1. Brute Force

 

(1) security level: low

더보기

[국예린]: 버프스위트로 비밀번호 무차별 대입(딕셔너리 사용)

proxy → http history 탭에서 가장 최근 get 클릭

입력값 찾을 수 있음

해당 get 우클릭→ send to intruder

Intruder로 이동 → positions

선택 되어있던 부분 삭제 후 password 부분만 선택해 우측 add 클릭

페이로드로 이동 후 Brute forcer 선택

 

대입해볼 문자들이 설정되어 있음

 

문자 추가하면 경우의 수가 더 늘어난다(이거 많을수록 맞는 pw 찾는데 오래 걸린다)

 

 

길이 늘리면 늘릴수록 더 올라감

 

상부 우측 start attack 클릭 후 실행 화면 → 상부 메뉴에 Attack→pause 누르면 멈춤

각각의 라인이 하나의 요청을 의미한다

payload→ 각각 요청에 어떤 값 보냈는지 표시중

 

이렇게 기다리다보면 찾음

시간이 많이 걸리고 pw가 길면 길수록 오래걸려 효율이 떨어짐


터미널을 하나 열어서

gedit /usr/share/john/password.lst 입력

터미널을 하나 열어서 gedit /usr/share/john/password.lst 입력

 

brute force에서 simple list로 변경

 

찾아서 payload settings에 open

앞의 주석 내용들은 선택해서 remove

 

start attack ㅇㅇ.

바로 pause

 

password 하나만 응답 길이가 크게 다르다.

 

테스트 해보니 로그인 완


 

[류현주]: 소스코드 분석, 버프스위트로 무차별 대입 

간단하게 소스코드를 훑어보면 GET 방식으로 username, password를 보내는 코드다. 그런데 md5로 해시 암호화하는 비밀번호랑 다르게 사용자 이름에는 아무런 조치도 없다!..→ sql 인젝션도 가능하다는 뜻

랜덤으로 username, password를 입력했고, 틀리다고 에러 메세지가 떴다.
우선 BurpSuite를 설치하고 브라우저를 통해 로그인 과정을 관찰한다.

GET 요청으로 username과 password 파라미터를 보낸다. admin, test로 로그인을 시도했다는 것이 보인다. 이제 이 페이로드를 intruder 탭으로 보낸다.

 

a-z, 0-9까지 문자열을 8자리로 브루트포스하니 경우의 수가 uncount될 정도였다. 시간이 너무 오래걸린다. 그래서 비밀번호를 test로 변경하고 다시 시도해본다.
시간 절약을 위해 e,s,t만 사용해서 브루트포스를 진행해보았다.
비밀번호가 일치하는 경우에는 length가 혼자 다르다!! 오른쪽 버튼을 눌러서 브라우저로 결과보기를 택했더니

 

공격이 성공했음을 알 수 있었다.

 


 

 [송연수]: 버프스위트로 비밀번호 무차별 대입(딕셔너리 사용)

아무 입력 값이나 넣어본다

 

proxy를 활용해 brute force 공격

username은 admin으로 고정 후 password만 선택

 

자주 사용되는 passwordlist 정리 파일을 활용

리스트를 로드
혼자 길이가 다른 모습을 확인

(2) security level: medium

더보기

[국예린]: 소스코드 분석,  버프스위트로 비밀번호 무차별 대입  

 

응답이 조금 느리게 옴

 

<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

login 성공시 “Welcome to the password protected area”와 이미지 출력

실패시 sleep(2)로 응답을 지연시켜 브루트 포스로 인한 비밀번호 찾기가 오래 걸리도록 방해중이다.

이와 같은 기능을 통해 해당 공격을 어느정도 대응 할 수 있게 되는 것이다.


 

[류현주]: 소스코드 분석, 버프스위트로  비밀번호 무차별 공격

 

이번에도 확실하게 차이가 나는 비밀번호다.

medium에서는 low와 공격과정은 일치하지만 브루트포스의 진행시간이 더 길다.  

view source 버튼을 눌러서 확인해보니, 공격시간이 늘어나도록 로그인 실패할 때마다 2초씩 멈추게 설정해놨다.

 


[송연수]: 소스코드 분석,  버프스위트로 비밀번호 무차별 대입 

medium은 sleep(2)로 지연을 주고 있지만 low과 동일한 공격을 하는 데에 큰 문제는 없었다

(3) security level: high

더보기

[국예린]: 소스코드 분석

일정 시간동안 sleep 후 응답

 

medium과 달리 0~3의 난수를 지정해 그 시간동안 sleep

 

정해진 시간이 아니라 난수를 쓰는 이유?

해당 시간동안 바로 응답 오지 않으면 바로 다른 요청으로 갈 수 있기 때문에

 


 

[류현주]: 소스코드 분석

이번에는 로그인을 하기 전에 유저의 토큰을 확인하는 과정을 거친다. 요청을 보낸 유저 토큰과 서버가 가지고 있는 세션 토큰이 일치해야 한다. 그렇다면 소스코드에 서버로 보낼 토큰이 있어야 하니 찾아보자.  

  로그인 실패할 때는 sleep하는 시간을 0~2초 중 랜덤으로 설정해 더욱 더 보안성을 높였다.

 

input태그가 hidden 타입으로 존재하는 것을 확인했다.

 

text 타입으로 바꿨더니 유저 토큰값이 보인다. CSRF 공격을 막는 데에는 효과적이겠지만 브루트포스에서는 아니다.

 


 

[송연수]: 버프스위트로 비밀번호, CSRF 토큰 무차별 대입

csrf 토큰이 추가됨
attack type과 positions을 설정한다

 

password 부분은 앞선 실습과 그대로 진행

 

incorrect 문자열을 찾는다고 설정 → 없으면 correct = password

 

웹 응답에서 토큰을 추출하기 위해서 extract 설정을 진행

 

리다이렉션 자동 설정 후 공격하면

발견!

 

(4) security level: impossible

더보기

[국예린]: 에러메세지 분석 

로그인 실패가 너무 많아 계정이 잠겼다고 뜬다.

아예 로그인을 15분간 차단하는 방식을 사용

이런 경우 아예 비밀번호를 틀려 15분간 사용자가 접속하지 못하게 하는 경우의 공격이 사용될 수 있음


 

[류현주]: 소스코드 분석

이번에는 드디어 POST 로 로그인 요청을 보낸다.

또한 로그인은 3번까지 기회가 있고, 15분씩 멈춘다. 브루트포스의 방법이 불가능한 대응방법이 되겠다.

 

2. Weak Session ID

 

(1) security level: low

더보기

[국예린]: 소스코드 분석, 세션 ID 발급해 관찰

proxy http history에서 가장 최근 post 파트를 클릭해보면 

새로운 dvwaSession이 1임을 볼 수 있다.

 

Generate를 한번 더 눌러보면 2로 새로 발급된 것을 확인할 수 있다.

 

소스코드를 한번 보고자 한다

 

last session에서 하나 증가한 값을 계속 쿠키값으로 설정하고 있다. (매우 단순한 방법)

 

이로 인해 공격자가 타인의 세션을 훔칠 수 있게 된다.

 

 

(2)  security level: medium

더보기

[국예린]: 소스코드 분석, 세션 ID 관찰

레벨 변경 후 세션아이디

첫 번째로는 1710174492가 나왔다. low 레벨의 정수와는 다르다.

 

두 번째로는 1710174604. 뒤의 세자리가 바뀌었다.

 

세 번째로는 1710174667… 패턴 예측이 잘 안되어 소스코드를 보겠다

 

time 함수를 사용해 쿠키값을 설정하는 모습이다.

쉽게 대응할 수 없도록 지금까지 지나온 초를 정수형태로 리턴해주는 time 함수를 사용해 접근에 대응하고 있다.

(3)  security level: high

더보기

[국예린] : 소스코드 분석, 세션 ID 관찰

이것저것 다 섞인 긴 값을 쿠키로 사용.

 

두 번째도 발급해 보았지만 별다른 규칙성이 눈에 띄지 않는다.

 

쿠키의 만료 시간을 현재 시간에서 3600초. 즉 한시간 후로 정하고 있고 지난 세션 변수의 값을 하나 증가시킨 후,

그 값을 md5 해시로 변환해 쿠키로 저장한다.

쿠키에 해시값을 적용해 접근을 대응하고 있다.

그러나 해당 내용도 md5 알고리즘을 알면 그렇게 어려운 내용이 아니다.

1,2,3,4,5 … 1씩 증가한 값을 md5로 암호화하면 해당 세션 값이 나온다.

높은 수준의 보안은 아니다.

(4)  security level: impossible

더보기

[국예린]:  소스코드 분석, 세션 ID 관찰

이전보다 더 길고 무작위해보이는 값이 나왔다.

바로 소스코드를 보았다.

 

sha1(mt_rand(),time(),&rdquo;impossible&rdquo;)

mt_rand()로 무작위 정수를 생성하고, 현재 시간을 초 단위로 반환한다. 랜덤 생성된 정수를 md5보다 강력한 sha1 암호 알고리즘을 활용해 바꾸었다.

쉽게 추측할 수 없도록 쿠키값을 바꾸어 접근을 대응하고 있다.

 

 

3. Authorization Bypass

 

(1) security level: low

더보기

[국예린]:  페이지 경로 직접 접속 실습

 

다른 브라우저로 예시 속 다른 유저 godeonb로 로그인한다.

아까까지 있던 authorisation bypass가 사라졌다.

admin으로 로그인 되어있던 브라우저의 proxy 탭을 활용해 해당 페이지의 경로값을 복사한다.

 

 

링크에 첨부

gordonb 계정으로 접속된 모습이다.

 


 

[송연수]:  페이지 경로 직접 접속 실습

해당 페이지에 second user로 접근하는 것이 목표

 

로그인

보여지는 화면에서만 숨겨져있고

authbypass에 직접 접근 가능

 

(2) security level: medium

더보기

[국예린]: API 직접 접속 실습

당연히 해당 페이지가 없다

low 처럼 경로 붙여넣기 시 권한없음이 뜬다

 

해당 페이지 get 부분을 repeater로 보내보겠다.

 

get 요청 부분을

OPTIONS로 변경 → send

 

권한 X

HEAD로 변경 → send  

우클릭 → change request methond → send

 

권한 X

 

admin 로그인 시 볼 수 있는 get_user_data.php 페이지를 경로에 입력해본다

 

 

회원정보 DB 열람 가능

 


 

[송연수]: API 직접 접속 실습

vulnerabilities/authbypass 경로는 막혔지만

 

사용자 데이터를 반환하는 API에 직접 액세스 가능(get방식 처리가 안됨)

 

(3) security level: high

더보기

[송연수]: 

 

high로 넘어오면 get_user_data.php도 막힌 걸 알 수 있다 

이를 우회하기 위해 update 쪽을 공략 (post방식은 안 막힘) 

gordonb로 로그인 했을 때의 쿠키를 복사해서

 

post 요청을 repeater를 이용해서

 

값을 변경 후

보내주면

접근 권한이 없는 페이지에서의 update가 가능하다

 


+ 참고)

실습 참고 링크

공격을 위한 proxy 설정