2024. 4. 27. 11:25ㆍProject/Web Application-모의해킹
시큐어 코딩 : Prepared Statement
1) 개요
Project:Web Site 웹 사이트 로그인 페이지 user_id 파라미터에서 발견된 SQL Injection 취약점을 방지하기 위하여 대응 방안 중 하나인 Prepared Statement 기능을 구현하고 적용시켜 실제로 SQL Injection 공격을 방지할 수 있는지 확인한다.
2) 방법
Prepared Statement 기능은 사용자 입력 값과 마찬가지로 Client Side에서 구현을 하게 되면 공격자에 의해 변조될 가능성이 존재하므로 보안을 위해 Server Side에서 구현을 한다.
3) 시큐어 코딩
[1] login_proc.php 페이지 전문
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
<?php
// 로그인 페이지에서 전송된 변수 저장
$user_id = $_POST['user_id'];
$user_pass = $_POST['user_pass'];
session_start();
// URL 직접 입력 접근 방지
if(!strlen($user_id) || !strlen($user_pass))
{?>
<script>
alert('권한이 없습니다.');
window.location.replace('/php/login.php');
</script>
<?php
exit();
}
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'db_id');
define('DB_PASSWORD', 'db_pass');
define('DB_NAME', 'db_name');
$connect = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
$sql= "SELECT * FROM test_user WHERE user_id=?";
$stmt = $connect->stmt_init();
$stmt = $connect->prepare($sql);
$stmt->bind_param('s', $user_id);
$stmt -> execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$stmt->close();
// 입력된 비밀번호와 데이터베이스의 비밀번호가 일치여부를 비교하여 일치하면 TRUE, 불일치하면 FALSE를 반환한다.
$match_pass = password_verify($user_pass, $row['user_pass']);
// $match_pass 값이 TRUE인 경우(비밀번호 일치)
if($match_pass){
$_SESSION['user_id'] = $row['user_id'];
header("Location:/php/");
exit();
}
// $match_pass 값이 FALSE인 경우(비밀번호 불일치)
else{?>
<script>
alert('아이디 혹은 비밀번호가 틀렸습니다.');
window.location.replace('/php/login.php');
</script>
<?php
}
?>
|
cs |
[2] Prepared Statement 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?php
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'db_id');
define('DB_PASSWORD', 'db_pass');
define('DB_NAME', 'db_name');
$connect = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
$sql= "SELECT * FROM test_user WHERE user_id=?";
$stmt = $connect->stmt_init();
$stmt = $connect->prepare($sql);
$stmt->bind_param('s', $user_id);
$stmt -> execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$stmt->close();
?>
|
cs |
login_proc.php 페이지에서 사용된 Preparde Statement 코드는 19번 라인부터 33번 라인까지이다. Prepared Statement 코드는 DB로 전달하는 SQL 쿼리의 사용자 입력 값을 바인드 변수인 '?'로 입력해야 한다. 위 코드에서 $sql 변수에 입력된 SQL 쿼리를 보면 user_id의 사용자 입력 값이 '?'로 되어있는 것을 볼 수 있다. 해당 위치의 실제 값은 12번 라인의bind_param() 함수를 통해 입력할 수 있다. 위 코드처럼 구현을 하게 된다면 더 이상 $user_id 파라미터에서는 SQL Injection 공격이 통하지 않게 된다.
[3] 동작 화면
로그인 페이지에 접속하여 로그인 가능한 계정 정보를 입력하고 로그인 버튼을 클릭한다. 사용된 계정은 vanhart, 비밀번호는 123123이다.
페이로드 : vanhart' and '1'='1
모의해킹에서 SQL Injection 취약점을 발견했을 때 사용한 페이로드를 입력하고 로그인 가능한지 확인한다. 위 페이로드를 아이디 입력 칸에 입력하고 로그인 버튼을 클릭한다.
로그인 버튼을 클릭하게 되면 '아이디 혹은 비밀번호가 틀렸습니다.'라는 경고문과 함께 로그인 페이지로 이동된다.
페이로드 : vanhart'+and+'1'='2
위와 같은 페이로드를 입력하여 다시 시도해봐도 '아이디 혹은 비밀번호가 틀렸습니다.'라는 경고문과 함께 로그인 페이지로 이동되는 것으로 보아 SQL Injection 공격이 통하지 않는다는 것을 확인할 수 있다.
'Project > Web Application-모의해킹' 카테고리의 다른 글
[Web Application-모의해킹] 디렉터리 인덱싱 : 시큐어 코딩(디렉터리 내 초기 페이지 설정) #4-2 (0) | 2024.04.30 |
---|---|
[Web Application-모의해킹] 디렉터리 인덱싱 : 대응 방안 #4-1 (0) | 2024.04.30 |
[Web Application-모의해킹] SQL Injection : 시큐어 코딩(에러 메시지 출력 방지) #3-3 (0) | 2024.04.27 |
[Web Application-모의해킹] SQL Injection : 시큐어 코딩(사용자 입력 값 검증) #3-2 (0) | 2024.04.26 |
[Web Application-모의해킹] SQL Injection : 대응 방안 #3-1 (0) | 2024.04.25 |