로그인 및 SQL 주입(구현 및 실습)

2023.04.14 – (모의 해킹/취업 연구를 위한 연구) – (0413 Day03) SQL Injection -01

(0413 Day03) SQL 인젝션 -01

DB: 많은 사람들이 데이터를 공유하고 사용할 목적으로 정리, 통합, 관리되는 데이터의 집합체!! DB와 엑셀을 쉽게 비교해보세요! 데이터베이스: 엑셀 파일 자체(test.xlsx) 표: 엑셀 파일 안의 엑셀 시트(시트

jisu069.tistory.com

다양한 로그인 구현!!

다양한 로그인 케이스가 있지만 먼저 두 가지로 나누어서 구현했습니다.

사례 1: 식별과 인증을 동시에

사례 2: 식별 및 인증


Login1 (식별과 인증을 동시에 하는 Case 1)

  • 지금까지 구현된 로그인 중 가장 쉬운 코드, 비교적 보기에 깔끔한 코드!
  • 다만 로그인이 너무 쉽다.. (SQL Injection은 다양한 공격을 할 수 있다…)
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');

$sql = "select * from userTestTB where userId='$userId' and userPw = '$userPw';";
$rst = mysqli_query($con, $sql);
$id = mysqli_num_rows($rst);

if(!$id){
    echo "
        <script>
            alert(\"메롱\");
            history.back();
        </script>
    ";
}else{
	$user = mysqli_fetch_array($rst);

    	$_SESSION('sIdx') = $user('userIdx');
        $_SESSION('sId') = $user('userId');
        $_SESSION('sName') = $user('userName');
        $_SESSION('sPW') = $user('userPw');
        $_SESSION('sEmail') = $user('userEmail');

        mysqli_close($con);
        echo "
            <script>
                location.href = \"./main.php\"; 
                </script>
        ";
}

?>

현재 사용자의 ID 시험그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 이용하여 우회를 시도하였으나 로그인 성공!!
  • test’or’1’=’1 로 우회를 시도했는데 로그인 성공!!
  • 위와 비슷하지만 test’ xor ‘ ‘=’ 를 이용하여 우회를 시도하여 로그인에 성공!!
  • ‘ Union select ‘1’,’1′,’1′,’1′,’1′ # 우회해서 해봤는데 로그인 성공!! )
  • ID: test / PW: ‘or’1’=’1 비밀번호를 이용하여 우회를 시도하였으나 로그인 성공!!!!









Login2 (ID로 식별하고 PW로 인증하는 경우 2)

  • 지금까지는 Case 1보다 안전하다고 생각했지만 그렇지 않았습니다.
  • 코드는 Login1보다 길고 매우 약간 복잡한 코드입니다.
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');

$sql = "select * from userTestTB where userId='$userId';";
$rst = mysqli_query($con, $sql);
$id = mysqli_num_rows($rst);

if(!$id){
    echo "
        <script>
            alert(\"메롱\");
            history.back();
        </script>
    ";
    exit;
}else{
    $user = mysqli_fetch_array($rst);
    $db_pw = $user('userPw');
    if($db_pw == $userPw){
        $_SESSION('sIdx') = $user('userIdx');
        $_SESSION('sId') = $user('userId');
	$_SESSION('sName') = $user('userName');       
	$_SESSION('sPW') = $user('userPw');
        $_SESSION('sEmail') = $user('userEmail');

        mysqli_close($con);
            echo "
                <script>
                    location.href = \"./main.php\"; 
                </script>
            ";
    }else{
        echo "
            <script>
                alert(\"메롱!!\");
                history.back();
            </script>
        ";
        exit;
    };
};
?>

현재 사용자의 ID 시험그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 이용해서 우회를 시도했지만 당연히 실패…!
  • test’or’1’=’1 로 우회를 시도했지만 실패!!
  • ‘ Union select ‘1’,’1′,’1′,’1′,’1′ # 우회 로그인 성공!!
  • ID: test / PW: ‘or’1’=’1은 비밀번호를 이용하여 우회했는데 당연히 실패…!









Login3 (Case1, 특수문자 금지!!)

  • SQL Injection을 방지하기 위해 특수문자(‘,”,#)를 차단하면서 구현해 보았습니다.
  • preg_match(pattern, character to compare) : 비교할 문자에 패턴이 있는지 찾아주는 함수!
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');
$pat="/\"|#|"/';
if(preg_match($pat, $_POST('userId')) or preg_match($pat, $_POST('userPw'))){	
    echo " 
    <script>
        alert(\"사용자는 보씨오 다음에도 사기치면 혼나오!! 양심껏 로그인 하씨오 \");
        history.back();
    </script>
    ";
    exit;
}else{
    $sql = "select * from userTestTB where userId='$userId' and userPw = '$userPw';";
    $rst = mysqli_query($con, $sql);
    $id = mysqli_num_rows($rst);
    
    if(!$id){
        echo "
            <script>
                alert(\"메롱\");
                history.back();
            </script>
        ";
    }else{
        $user = mysqli_fetch_array($rst);
    
            $_SESSION('sIdx') = $user('userIdx');
            $_SESSION('sId') = $user('userId');
            $_SESSION('sName') = $user('userName');
            $_SESSION('sPW') = $user('userPw');
            $_SESSION('sEmail') = $user('userEmail');
    
            mysqli_close($con);
            echo "
                <script>
                    location.href = \"./main.php\"; 
                    </script>
            ";
    }
}
?>

현재 사용자의 ID 시험그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 이용해서 우회를 시도했지만 당연히 실패…!
  • test’or’1’=’1 로 우회를 시도했지만 실패!!
  • ‘ union select ‘1’,’1′,’1′,’1′,’1′ # 이마저도 로그인 실패!!
  • 비밀번호 쪽 ID 사용: test / PW: ‘or’1’=’1 이것도 실패…!
  • 모두 실패…

Login4 (Case2, 특수문자 금지!!)

<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');
$pat="/\"|#|"/';
if(preg_match($pat, $_POST('userId'))){
    echo"
    <script>
        alert(\"사용자는 보씨오 다음에도 사기치면 혼나오!! 양심껏 로그인 하씨오 \");
        history.back();
    </script>
    ";
}else{
    $sql = "select * from userTestTB where userId='$userId';";
    $rst = mysqli_query($con, $sql);
    $id = mysqli_num_rows($rst);
    if(!$id){
        echo "
            <script>
                alert(\"메롱\");
                history.back();
            </script>
        ";
        exit;
    }else{
        $user = mysqli_fetch_array($rst);
        $db_pw = $user('userPw');
        if($db_pw == $userPw){
            $_SESSION('sIdx') = $user('userIdx');
            $_SESSION('sId') = $user('userId');
            $_SESSION('sName') = $user('userName');
            $_SESSION('sPW') = $user('userPw');
            $_SESSION('sEmail') = $user('userEmail');
    
            mysqli_close($con);
                echo "
                    <script>
                        location.href = \"./main.php\"; 
                    </script>
                ";
        }else{
            echo "
                <script>
                    alert(\"메롱!!\");
                    history.back();
                </script>
            ";
            exit;
        };
    };
}
?>

현재 사용자의 ID 시험그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 이용해서 우회를 시도했지만 당연히 실패…!
  • test’or’1’=’1 로 우회를 시도했지만 실패!!
  • ‘ union select ‘1’,’1′,’1′,’1′,’1′ # 이마저도 로그인 실패!!
  • 비밀번호 쪽을 이용하면 ID: test / PW: ‘or’1’=’1 이것도 당연히 실패…!
  • 이 역시 모두 실패했습니다.

Login5 (Case1, 해쉬함수 사용!!)

  • 해시 함수를 이용한 암호화(단방향 암호화!)
  • 회원가입 시 해시함수로 암호화된 비밀번호를 DB에 저장하고 로그인 시 사용한 키 값을 이용하여 사용자가 입력한 비밀번호를 암호화하여 비교합니다.
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');

$salt="$5$QOPrAVIK"."$userId".'$';
$hashPw = crypt($userPw, $salt);

$sql = "select * from userTestTB where userId='$userId' and userPw = '$hashPw';";
$rst = mysqli_query($con, $sql);
$id = mysqli_num_rows($rst);

if(!$id){
    echo "
        <script>
            alert(\"메롱\");
            history.back();
        </script>
    ";
}else{
	$user = mysqli_fetch_array($rst);

    	$_SESSION('sIdx') = $user('userIdx');
        $_SESSION('sId') = $user('userId');
        $_SESSION('sName') = $user('userName');
        $_SESSION('sPW') = $user('userPw');
        $_SESSION('sEmail') = $user('userEmail');

        mysqli_close($con);
        echo "
            <script>
                location.href = \"./main.php\"; 
                </script>
        ";
}

?>

현재 사용자의 ID 테스트 1그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#!!!를 사용하여 성공적으로 우회
  • test’or’1’=’1을 사용한 성공적인 우회!!!
  • ‘ Union select ‘1’,’1′,’1′,’1′,’1′ # 바이패스 성공!!!
  • 비밀번호 쪽을 이용해서 ‘or’1’=’1 을 사용했는데 실패!!
    • 사용자가 입력한 비밀번호가 바로 선택되는 것이 아니라 해시로 암호화되어 입력되기 때문에!!








Login6 (Case2, 해쉬함수 사용!!)

  • 식별 후 인증을 진행하고, 인증 전 사용자의 비밀번호를 해시함수를 이용하여 암호화하여 비교합니다.
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');

$salt="$5$QOPrAVIK"."$userId".'$';
$hashPw = crypt($userPw, $salt);

$sql = "select * from userTestTB where userId='$userId';";
$rst = mysqli_query($con, $sql);
$id = mysqli_num_rows($rst);

if(!$id){
    echo "
        <script>
            alert(\"메롱\");
            history.back();
        </script>
    ";
    exit;
}else{
    $user = mysqli_fetch_array($rst);
    $db_pw = $user('userPw');
    if($db_pw == $hashPw){
        $_SESSION('sIdx') = $user('userIdx');
        $_SESSION('sId') = $user('userId');
        $_SESSION('sName') = $user('userName');
        $_SESSION('sPW') = $user('userPw');
        $_SESSION('sEmail') = $user('userEmail');

        mysqli_close($con);
            echo "
                <script>
                    location.href = \"./main.php\"; 
                </script>
            ";
    }else{
        echo "
            <script>
                alert(\"메롱!!\");
                history.back();
            </script>
        ";
        exit;
    };
};
?>

현재 사용자의 ID 테스트 1그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 사용한 우회 실패!!!
  • test’or’1’=’1도 우회 실패!!!
  • ‘ union select ‘1’,’1′,’1′,’1′,’1′ # 우회 실패!!!
  • 비밀번호 쪽을 이용해서 ‘or’1’=’1 을 사용했는데 실패!!
    • 위와 같이 사용자가 입력한 비밀번호는 바로 선택되는 것이 아니라 해시로 암호화하여 입력!!







Login7 (테이블 2개로 로그인)

  • 회원가입 시 모든 정보는 메인 테이블에 저장되며, 서브 테이블에는 회원 아이디와 비밀번호만 저장됩니다.
  • 로그인 시 사용자의 아이디와 비밀번호를 서브 테이블과 비교하여 변수로 저장하고 메인 테이블 변수와 비교한다.
<?php
session_start();
include('./connect.php');

$userId = $_POST('userId');
$userPw = $_POST('userPw');
// 서브 테이블과 비교
$cmpsql = "select * from usercmpTB where userId='$userId' and userPw='$userPw';";
$cmprst = mysqli_query($con, $cmpsql);
$cmpuser = mysqli_fetch_array($cmprst);
$cmpId = $cmpuser('userId');
$cmpPw = $cmpuser('userPw');
// 메인 테이블의 정보와 서브테이블 정보 비교
$sql = "select * from userTestTB where userId='$cmpId' and userPw='$cmpPw';";
$rst = mysqli_query($con, $sql);
$id = mysqli_num_rows($rst);

if(!$id){
    echo "
    <script>
    alert(\"메롱\");
    history.back();
    </script>
    ";
    exit;
}else{
    $user = mysqli_fetch_array($rst);
    
    $db_pw = $user('userPw');
    if($db_pw == $userPw){
        $_SESSION('sIdx') = $user('userIdx');
        $_SESSION('sId') = $user('userId');
        $_SESSION('sName') = $user('userName');
        $_SESSION('sPW') = $user('userPw');
        $_SESSION('sEmail') = $user('userEmail');

        mysqli_close($con);
            echo "
                <script>
                    location.href = \"./main.php\"; 
                </script>
            ";
    }else{
        echo "
            <script>
                alert(\"메롱!!\");
                history.back();
            </script>
        ";
        exit;
    };
};
?>

현재 사용자의 ID cmp 그런데 비밀번호를 모르겠습니다. SQL Injection 취약점을 통해 로그인하자!!

  • test’#를 사용한 우회 실패!!!
  • test’or’1’=’1도 바이패스 실패!!!
  • ‘ union select ‘1’,’1′ # 사용했는데 우회 실패!!!
    • 하위 테이블에는 두 개의 열이 있으며 실패 이유는 하위 테이블과 기본 테이블의 정보가 다르기 때문입니다.
  • 비밀번호 쪽을 이용해서 ‘or’1’=’1 을 사용했는데 실패!!
    • 서브 테이블이 참이라도 메인 테이블 비밀번호와 다르기 때문에 실패!!








사용된 테이블 정보

# 메인 테이블
create table userTestTB(
	userIdx int primary key auto_increment,
	userId varchar(100) unique not null, 
	userName varchar(100) not null,
	userPw varchar(200) not null,
	userEmail varchar(100) not null
);
# 서브 테이블
create table usercmpTB(
	userId varchar(100) unique not null, 
	userPw varchar(200) not null,
);


<- Write the login logic as you think!!! Keep looking for SQL injection vulnerabilities!!->