SQL Injection
1. 공격 원리
SQL Injection는 코드 인젝션의 한 기법으로 클라이언트의 입력 값을 조작하여 서버의 데이터베이스를 공격할 수 있는 공격 방법이다. 문법적 의미가 있는 싱글쿼터(‘)와 주석(#)을 이용해 완성된 쿼리문을 주입해 공격자는 로그인 우회, 데이터 추출 등의 악의적인 행동을 취할 수 있다.
SQL Injection의 공격 종류는 다음과 같다.
종류 |
대상/특징 |
Union SQLi |
UNION 절을 이용하여 두 개 이상의 쿼리를 묶어 원하는 정보를 DB에서 추출하는 공격 기법 |
Error Base SQLi |
데이터베이스의 문법에 맞지 않은 쿼리문 입력 시 반환되는 에러 정보를 기반으로 공격하는 기법 |
Blind SQLi |
True인 쿼리문과 False인 쿼리문 삽입 시 반환되는 데이터를 비교하여 정보를 추출하는 공격 |
2.1.1. SQL Injection 일반
1. 공격실습
No. |
실습 위치 |
비고 |
1 |
관리자 로그인 |
2. 페이지 구현
<?php
$link = mysqli_connect('localhost', 'myuser1', 'password','myuser1');
if(!$link)
{
die("Could not connect to the server: " .mysql_error());
}
?>
/connect.php
connect.php 파일은 DB와 연결하기 위한 php 코드이다.
<?php
include("connect.php");
$message = "";
?>
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>로그인</title>
<style>
body { font-family: sans-serif; font-size: 14px; }
input, button { font-family: inherit; font-size: inherit; }
</style>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="/css/loginstyle.css"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
<link rel="stylesheet" type="text/css" href="/css/common.css" />
</head>
<body>
<?php
if(isset($_POST["form"]))
{
$id = $_POST["username"];
$password = $_POST["password"];
$sql = "SELECT * from sqliLogin1 WHERE id = '" . $id . "' and pw='" . $password . "'";
// echo $sql;
$recordset = mysqli_query($link, $sql);
if(!$recordset){
echo "<br>";
die("Error: " .mysqli_error($link));
}
else{
$row = mysqli_fetch_array($recordset);
if($row["id"]){
$message = "<font color=\"white\">Login SUCCESS! <br>" . $row["id"] . " Welcome!</b></font>";
}
else{
$message = "<font color=\"yellow\">계정 정보를 잘못 입력했습니다.</font>";
}
}
mysqli_close($link);
}
?>
<div class="center-block">
<p class="bg-danger"><?php echo $message; ?></p>
</div>
<div class="login">
<form action="adminlogin.php" method="post">
<label for="username">
<i class="fas fa-user"></i>
</label>
<input type="text" name="username" placeholder="Username" id="username" required>
<label for="password">
<i class="fas fa-lock"></i>
</label>
<input type="password" name="password" placeholder="Password" id="password" required>
<div class="msg">관리자용 로그인</div>
<button type="submit" class="btn btn-success" name="form" value="submit">LOGIN</button>
</form>
</div>
</body></html>
/adminlogin.php
로그인 페이지는 폼으로 ID(username)과 패스워드(password)를 받아 로그인 버튼 클릭시 POST로 요청을 전송한다. 로그인 성공 시 Login SUCCESS! 와 성공한 계정 정보를 메시지로 보여주고, 실패 시 "계정 정보를 잘못 입력했습니다" 라는 오류 메시지를 보여준다.
$sql 구문에서 SQL Injection에 취약한 구문으로 입력값을 받는 것을 알 수 있다.
공격 실습
Step1. SQL Injection 공격 가능 여부를 확인하기 위해 ID 입력 폼에 싱글 쿼터(')를 입력하여 반응을 살펴본다.
웹사이트에서 특수문자 입력에 대한 처리를 적절하게 하지 않았거나 php 에러 메시지를 표시하게 한 경우 SQL Injection 공격 성공의 가능성이 있다고 볼 수 있다.
Step2.Username을 입력하는 폼에 SQL Injection 구문을 삽입하여 공격한다.
입력구문 : ‘ or 1=1#
입력 구문을 통해 로그인을 시도했을 때 php 코드 상에서 SQL 구문은 다음과 같이 처리된다.
$sql = "SELECT * from sqliLogin1 WHERE id = '' or 1=1# and pw='1234';
or 1=1 구문을 통해 항상 결과가 참인 구문이 되고 #의 사용은 뒤에 따라오는 구문을 주석처리하여 해석하지 않도록 한다.
SELECT * from sqliLogin1 WHERE id = '" . id입력값 . "' and pw='" . $password입력값 . "' 을 통해 값을 검증하고 있으므로 id를 입력 받는 부분에서 ‘ or 1=1# 를 입력하게 되면 and pw 부분부터 주석처리가 되며 어떠한 경우에도 참인 쿼리가 된다. 이때 정보를 가져오는 값은 쿼리문을 실행 시켰을 때 불러오는 마지막 값이며 정렬 기능을 이용해 다른 값으로도 로그인에 성공할 수 있다.
Case2 로그인 인증 우회
Step1.관리자 로그인 페이지 접속 후 SQL injection 공격 구문을 입력하고 인증 우회에 성공한다.
입력구문 : admin’#
해당 쿼리문은 식별과 인증이 동시에 이루어진다. 때문에 SQL Injection을 이용해 인증을 우회할 수 있으며 사용자 식별과 인증은 분리하여 작성하는 것이 좋다.
'Security > WEB' 카테고리의 다른 글
[모의해킹 실습] Stored XSS 취약 페이지 구현 및 공격 실습 2 (4) | 2021.07.13 |
---|---|
[모의해킹 실습] XSS 취약 페이지 구현 및 공격 실습 (0) | 2021.07.10 |
[모의해킹 실습] Blind SQL Injection 게시판 구현 및 공격실습 3 (0) | 2021.07.08 |
[모의해킹 실습] Union SQL Injection 게시판 구현 및 공격실습 2 (0) | 2021.05.25 |
[모의해킹] 실습환경 구성하기 (0) | 2021.05.04 |