Open Redirect

회원만 글을작성할수 있는 게시판에서 로그인을 하지 않은 채로 글 작성 버튼을 클릭 시 보통의 웹 사이트 들에서는 "로그인 후 이용 가능합니다" 등과 같은 알림창을 띄운 뒤 로그인 페이지로 강제 이동 시킵니다. 그리고 사용자가 로그인을 했을 땐, 로그인을 하지 않아 실패했던 요청으로 돌아가서 글을 작성하는 페이지로 이동되는 로직을 흔하게 경험할 수 있습니다.

Open Redirect 취약점은 이처럼 서버가 특정 조건에서 클라이언트를 강제적으로 리다이렉션 시킬 때, 리다이렉션 되는 경로를 공격자가 조작할 때 발생하는 취약점입니다. 아래는 로그인 페이지에서 유효한 계정 정보를 입력 후, 패킷을 조작하지 않은 요청 패킷입니다. 현재 서버에서는 from 파라미터를 통하여 리다이렉션 할 경로를 GET 방식으로 전달하고 있습니다.

로그인 페이지 Request 패킷

실제 서버의 loginAction.php 코드를 확인해보면 전달받은 파라미터를 통해서 from 파라미터가 존재할 시, 어떠한 입력값 검증 과정 없이 리다이렉션 시키는 것이 확인됩니다.

$from = isset($_GET['from']) ? $_GET['from'] : '';
if ($gubun == 'user'){
    $query = "SELECT * FROM users WHERE id = ?";
    $stmt = $db_conn->prepare($query);
    $stmt->bind_param("s", $user_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $num = ($result && $result->num_rows) ? $result->num_rows : 0;
    $row = $result->fetch_assoc();
    $real_password = isset($row['password']) ? $row['password'] : '';
    if($real_password == $user_pw){
        $_SESSION['id'] = $user_id;
        $_SESSION['login'] = hash("sha256",$user_id); // 세션 변수 설정
        if ($from != ''){
            header("Location: $from");
            exit();
        }
        header("Location: ../index.php"); // 대시보드 페이지로 리디렉션
        exit(); // 스크립트 실행 중지
    }else{
        echo "<script>alert('아이디 혹은 패스워드가 일치하지 않습니다.');history.back(-1)</script>";
        exit;
    }

이를 통해서 공격자는 로그인 페이지의 from 파라미터에 공격자의 피싱 서버 주소를 삽입하여 사용자들이 로그인 시에 피싱 사이트에서 활동하도록 유도할 수 있습니다.

로그인 페이지의 from 파라미터를 Google로 변경
조작된 리다이렉션 경로로 이동된 모습

대응 방안

  1. 서버에서 리다이렉션 하는 로직을 경로와 함께 하드코딩

  2. 리다이렉션 경로를 클라이언트 동적으로 받을 필요가 있을 경우 POST 요청을 통해 수신

  3. 리다이렉션 직전, 안전한 경로를 화이트리스트로 관리하여 입력값 검증

Last updated

Was this helpful?