[모의해킹 실습] SQL Injection 게시판 구현 및 공격실습 1

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

localhost/adminlogin

관리자 로그인

 

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#

SQL Injection 공격 및 로그인 성공

입력 구문을 통해 로그인을 시도했을 때 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 공격 및 admin 계정으로 로그인 성공

해당 쿼리문은 식별과 인증이 동시에 이루어진다. 때문에 SQL Injection을 이용해 인증을 우회할 수 있으며 사용자 식별과 인증은 분리하여 작성하는 것이 좋다.

반응형