3주차 과제(해킹)- 여러 로그인 로직 케이스 개발

Peroro·2023년 4월 17일
0
post-custom-banner

여러 로그인 로직의 우회 기법 연구는 피곤한 관계로 이번주 내로 올릴 것이다.

우선 기본적인 형태이다.

식별&인증

//check_login.php
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <?php
    session_start();
    $host = 'localhost';
    $user = 'conn';
    $pw = 'Testnote!%89';
    $db_name = 'test';
        $mysqli = new mysqli($host, $user, $pw, $db_name);

        $username = $_POST['id'];
        $userpass = $_POST['pw'];

        $q = "SELECT * FROM member WHERE id = '$username' AND pw = '$userpass'"
        $result = $mysqli->query($q);
        $row = $result->fetch_array(MYSQLI_ASSOC);

        if($row != null){
            $_SESSION['username'] = $row['id'];
            $_SESSION['name'] =  $row['name'];
            echo "<script>location.replace('index.php');</script>";
            exit;
        }
        if($row == null){
            echo "<script>alert('Invalid username or password')</script>";
            echo "<script>location.replace('login.php')</script>";
            exit;
        }
    ?>
</body>
</html>
  • 기본적인 식별과 인증을 동시에 진행하는 형태로 SQL Injection에 취약하다.

식별/인증 분리

//check_login3.php
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <?php
    session_start();
    $host = 'localhost';
    $user = 'conn';
    $pw = 'Testnote!%89';
    $db_name = 'test';
        $mysqli = new mysqli($host, $user, $pw, $db_name);

        $username = $_POST['id'];
        $userpass = $_POST['pw'];

        $q = "SELECT pw FROM member where id = '$username'"
        $result = $mysqli->query($q);
        $row = $result->fetch_array(MYSQLI_ASSOC);

        if($row['pw'] == $userpass){
            $_SESSION['username'] = $row['id'];
            $_SESSION['name'] =  $row['name'];
            echo "<script>location.replace('index.php');</script>";
            exit;
        }
        else{
            echo "<script>alert('Invalid username or password')</script>";
            echo "<script>location.replace('login.php')</script>";
            exit;
        }
    ?>
</body>
</html>
  • 기본적인 식별과 인증이 분리된 형태로 이 역시 UNION을 통한 SQL Injection에 취약하다.

아래부터는 위의 두 방식의 여러가지 표현법이다. 여러 방법이 있겠지만, 대표적인 방법만 설명해보겠다.

식별&인증_1

$q = "SELECT * FROM member WHERE (id = '$username' AND pw = '$userpass')"

        $result = $mysqli->query($q);
        $row = $result->fetch_array(MYSQLI_ASSOC);

Where 이후로 괄호를 씌워 만약 주석(#)이 들어오게 되면 ')'가 생략이 되어 오류를 일으키게 된다. 이를 이용해 SQL Injection을 막는 방법이 있다.

식별&인증_2

 $q = "SELECT * FROM member WHERE id = '$username' AND pw = '$userpass'";
        $q1 = str_replace('#', '', $q);
        $result = $mysqli->query($q);
        $row = $result->fetch_array(MYSQLI_ASSOC);

특정 문자가 들어오게 된다면 그 문자를 생략해주는 str_replace함수를 사용한다. 이 경우에는 주석(#)이 들어오는 경우 #을 없애서 생략하고자 했던 부분을 활성화시켜 오류를 일으키게 된다. 이를 이용해 SQL Injection을 막는다.

식별&인증_3

$q = "SELECT uid
	FROM member m1 
	JOIN member m2 ON m2.pw = '$userpass' AND m1.uid = m2.uid
	WHERE m1.id = '$username'"

    $result = $mysqli->query($q);
    $row = $result->fetch_array(MYSQLI_ASSOC);

아쉽게도 MySQL에는 intersect(합집합)에 대한 내용이 없다. 그래서 (inner) Join으로 교집합을 만들어보았다. 복잡해서 이렇게 하면 제대로 인증이 되는지 모르겠다.

식별/인증 분리_1

$q1 = "SELECT pw FROM member where id = '$username'"
$q = replace(' union ', '', strtolower($q1));
$result = $mysqli->query($q);
$row = $result->fetch_array(MYSQLI_ASSOC);

식별&인증_2에서와 마찬가지로 union이라는 문자가 있다면 생략되도록 만들었다. 그리고 대문자를 이용해 공격에 성공할 수도 있기 때문에 소문자로 만들어주는 strtolower함수를 사용했다.

profile
오늘 공부한 것을 올리는 공간 / 일주일에 글 3개 / 블로그 이전 : https://perorochan321.tistory.com/
post-custom-banner

0개의 댓글