본문 바로가기

웹 해킹

[주통기반] 로컬 웹 서버 취약점 찾기 (불충분한 인증)

불충분한 인증 취약점은 중요 페이지에 접근 시 인증 절차가 불충분하여 권한이 없는 사용자가 중요 페이지에 접근할 수 있게 되는 취약점입니다. 해당 취약점으로 마이페이지 같은 중요 정보가 저장되어 있는 페이지에 접근할 수 있고, 이로 인해 정보가 노출될 위험이 있습니다.

XSS 취약점과 연계하여 해당 페이지에 접근하여 중요 정보를 가져올 수 있습니다.

 

점검 내용 : 중요 페이지 접근 시 추가 인증 요구 여부 점검

 

1. 마이페이지 

1) 로그인 후 마이페이지에 접속합니다.

로그인
마이페이지 접속

 

마이페이지 접속 시 추가 인증 없이 접속이 가능한 것을 확인할 수 있습니다.

마이페이지 같은 중요 페이지에 추가 인증이 없을 경우 위에서 설명한 것처럼 취약하다고 판단합니다.

 

[대응 방안]

해당 페이지 접근 시 추가 인증 로직을 구현하여 권한이 없는 사용자의 접근을 제한합니다.

 

접근 통제 로직은 반드시 서버 측에 구현하고 모듈화시켜야 합니다.

<!doctype html>
<html lang="en">

<head>
    <?php
    // 기본적으로 필요한 함수나 모델 가져오기
    require_once ('views/includes/head.php');
    require_once ('models/user-model.php');
    require_once ('config/cookie.php');
    require_once ('config/session.php');
    $userId = getCookie($_COOKIE);
    $userClass = new User($userId);
    $user = $userClass->getUser();
    // 만약 로그인되어 있지 않을 경우 로그인 페이지로 이동
    if (!$userId) {
        echo "<script>alert('먼저 로그인 해주세요.'); window.location.href='/login.php';</script>";
        exit;
    }
    if ($_SERVER['REQUEST_METHOD'] == 'POST') {
        $enteredPw = $_POST["password"];
        $enteredConfirmPassword = $_POST["confirmPassword"];
        if ($enteredPw != $enteredConfirmPassword) {
            echo "<script>alert('비밀번호가 올바르지 않습니다.')</script>";
        } else if (!$userClass->checkPassword($enteredPw)) {
            echo "<script>alert('비밀번호가 올바르지 않습니다.');</script>";
        } else {
            setIsAuth($user);
            header("location: mypage.php");
            exit;
        }
    }
    ?>
    <link rel="stylesheet" href="static/css/mypage.css">
    <title>Home</title>
</head>

<body>
    <div class="row" id="mypage">
        <?php
        require_once ('mypage-header.php');
        ?>
        <div class="col-8">
            <section style="margin-top: 15rem;">
                <form method="post">

                    <div class="form-floating mb-3">
                        <input type="password" class="form-control" id="floatingPassword" name="password"
                            placeholder="Password" required>
                        <label for="floatingPassword">비밀번호 입력</label>
                    </div>
                    <div class="form-floating mb-3">
                        <input type="password" class="form-control" id="floatingPassword" name="confirmPassword"
                            placeholder="Password" required>
                        <label for="floatingPassword">비밀번호 재입력</label>
                    </div>
                    <div class="end">
                        <button type="submit" id="signup" class="btn btn-outline-primary">인증하기</button>
                    </div>
                </form>
            </section>
        </div>
    </div>
</body>

 

위 코드와 같이 비밀번호 입력을 받는 페이지를 따로 만들어 회원정보 페이지에 접근하기 위해서는 해당 페이지를 거치게 만들었습니다.

인증 페이지
인증 실패

 

만약 비밀번호가 틀리거나 서로 다른 비밀번호를 입력하면 인증 실패로 원래화면으로 돌아갑니다.

인증 성공

 

인증에 성공하면 마이페이지로 리다이렉트시켜 원하는 페이지로 이동시킵니다.

 

이때, 마이페이지에서 또 제대로 된 인증을 수행하지 않으면 직접 mypage.php 접근으로 우회가 가능하기 때문에 저는 세션값에 인증을 성공했다는 정보를 추가하여 해당 세션 인증이 있는 사용자만, 접근하게 했습니다.

직접 URL 에 페이지 입력
인증 필요 요청

 

또한, 한번 접속 후 세션값을 초기화하여 다시 접속할 때마다 인증을 수행하게 했습니다.

초기화하지 않으면 한번 사용자 인증이 완료된 세션은 똑같은 위험이 발생할 수 있습니다.

다시 요청 시 인증 필요

 

좀 귀찮긴 하지만 이렇게하면 좀 더 안전할 것 같습니다.

 

패스워드 인증하는 로직을 모듈화하여 로그인 인증에서 사용한 것을 이번 추가 인증에 다시 사용하였습니다. checkPassword가 해당 함수입니다. 

    public function checkPassword($enteredPw)
    {
        $id = $this->id;
        $user = User::getUserWithSameId($id);
        $userPw = $user['password'];

        if (!$user) {
            return false;
        } else {
            $hashedPassword = hash('sha256', $enteredPw);
            if ($userPw === $hashedPassword) {
                return true;
            } else {
                return false;
            }
        }
    }

 

해당 취약점은 이러한 중요 정보가 출력되는 페이지에 추가 인증이 이루어지지 않아 발생합니다.

처음에는 세션으로 사용자를 구별하였고 해당 세션만으로 사용자를 인증할 시 세션 탈취가 발생하면 쉽게 중요 정보가 탈취당합니다.

하지만, 이렇게 추가 인증 로직을 구현하면 세션 탈취가 발생하여도 공격자는 비밀번호를 알지 못하면 해당 정보를 알 수 없습니다.