<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>access.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요</description>
        <lastBuildDate>Sun, 06 Apr 2025 11:38:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>access.log</title>
            <url>https://velog.velcdn.com/images/song-_-/profile/61400616-aa29-4dc5-b841-decde41cbf96/image.webp</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. access.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/song-_-" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Python] Kali pip 설정]]></title>
            <link>https://velog.io/@song-_-/Python-Kali-pip-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@song-_-/Python-Kali-pip-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sun, 06 Apr 2025 11:38:34 GMT</pubDate>
            <description><![CDATA[<p>Kali를 설치하고 pip를 사용하려는데 이런 에러 메세지가 출력됐다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/487e3928-1151-45c1-8226-a64baaf840e5/image.png" alt=""></p>
<blockquote>
<p><strong>PEP 668 (Python 3.13 이상)</strong>
Python 3.13부터 배포판에서 제공하는 Python 환경을 보호하기 위한 보안 메커니즘이 도입.</p>
</blockquote>
<ul>
<li>시스템 Python에 pip로 직접 패키지를 설치하는 걸 막음</li>
<li>패키지 의존성 충돌, 시스템 안정성 문제를 예방</li>
</ul>
<p>시스템 파이썬은 리눅스 OS 설치 시 함께 제공되는 기본 Python 인터프리터로, 단순히 스크립트를 돌릴 때만 사용하는 게 아닌, OS 내부의 수많은 기능들이 의존하고 있는 핵심 기능이다. </p>
<p>때문에 pip를 통해 패키지를 잘못 설치했다가는 apt가 안먹히거나, 프로그램이 실행이 안되거나, OS 자체가 깨지는 경우가 생길 수 있음.</p>
<p>이를 위해 가상 환경으로 만들어 특정 프로젝트를 위한 영역을 분리할 수 있음.</p>
<hr>
<h3 id="방법-1">방법 1</h3>
<pre><code># python3 -m venv [프로젝트 이름]
# source [프로젝트 이름]/bin/activate
# pip install [설치할 패키지]</code></pre><p><img src="https://velog.velcdn.com/images/song-_-/post/c074929d-9982-488d-8124-528d998640dc/image.png" alt=""></p>
<p>실행할 경우 유저 이름 앞에 (프로젝트 이름)이 붙음.</p>
<p><strong>비활성화</strong></p>
<pre><code>deactivate</code></pre><h3 id="방법-2">방법 2</h3>
<pre><code>sudo apt install pipx 
pipx install [설치할 패키지]</code></pre><p>pipx는 자동으로 가상환경을 만들어서 설치해주고 명령어는 글로벌하게 노출시켜줌.</p>
<p>위 방법을 사용하면 시스템 python과 분리시켜 안전하게 python 패키지를 설치, 제거할 수 있게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - csrf-1]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-csrf-1</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-csrf-1</guid>
            <pubDate>Tue, 18 Mar 2025 19:00:24 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d290b7d7-5a66-4834-a761-2cf0400e8613/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<p>이전 xss-1과 전체적으로 코드가 유사하지만 한가지 다른점은 xss 필터와 /admin/notice_flag 경로가 추가되었다는 점이다.</p>
<pre><code class="language-python">@app.route(&quot;/vuln&quot;)
def vuln():
    param = request.args.get(&quot;param&quot;, &quot;&quot;).lower()
    xss_filter = [&quot;frame&quot;, &quot;script&quot;, &quot;on&quot;]
    for _ in xss_filter:
        param = param.replace(_, &quot;*&quot;)
    return param</code></pre>
<p>xss 필터는 파라미터에 frame, script, on이 들어가면 *로 변환한다. 이 필터로 js 코드를 실행할 수 있는 방법이 거의다 막히기 때문에 js 코드는사용이 불가능해진다.</p>
<pre><code class="language-python">@app.route(&quot;/admin/notice_flag&quot;)
def admin_notice_flag():
    global memo_text
    if request.remote_addr != &quot;127.0.0.1&quot;:
        return &quot;Access Denied&quot;
    if request.args.get(&quot;userid&quot;, &quot;&quot;) != &quot;admin&quot;:
        return &quot;Access Denied 2&quot;
    memo_text += f&quot;[Notice] flag is {FLAG}\n&quot;
    return &quot;Ok&quot;</code></pre>
<p>/admin/notice_flag 경로는 /memo 경로에서 사용되는 memo_text를 전역변수로 선언하고, 2가지 조건을 통과하면 flag 값을 memo_text에 저장한다.</p>
<p>조건은 로컬이면서 get으로 받아온 파라미터 userid가 admin이어야 한다는 것. 즉, get 요청을 내가 보내면 안되고 서버에서 보내게끔 만들어야 한다.</p>
<pre><code class="language-python">@app.route(&quot;/memo&quot;)
def memo():
    global memo_text
    text = request.args.get(&quot;memo&quot;, None)
    if text:
        memo_text += text
    return render_template(&quot;memo.html&quot;, memo=memo_text)</code></pre>
<p>memo_text는 /memo 페이지에서 memo 파라미터의 기본값으로 사용되는데, memo_text는 전역변수이기 때문에 /admin/notice_flag에서 성공적으로 조건문을 통과했다면 프로세스가 유효한 이상 flag 값을 담고 있다. 그래서 한 프로세스에서 /admin/notice_flag에 대한 get 요청과 /memo에 대한 get 요청이 둘 다 성공할 경우, flag 값이 페이지에 출력되게 된다.</p>
<p>흐름으로 보면</p>
<blockquote>
<p>/flag -&gt; check_csrf() -&gt; read_url() -&gt; /vuln -&gt; /admin/notice_flag -&gt; /memo</p>
</blockquote>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/50c984ce-a1fe-4e67-bbee-a188eba95255/image.png" alt=""></p>
<p>JS 없이 GET 요청을 전송하는 방법은 <code>&lt;img src=&quot;url&quot;&gt;</code>이 있다. <code>&lt;img&gt;</code> 태그의 <code>src</code> 속성은 작성한 url에 get 요청을 전송해서 이미지 파일을 받아온다.(POST는 안됌)</p>
<p>테스트를 위해 /vuln 경로에서 <code>&lt;img&gt;</code> 태그의 src 속성으로 /admin/notice_flag와 /memo 경로에 순서대로 get 요청을 보낸다. 코드는 아래와 같다.</p>
<p><code>&lt;img src=&quot;/admin/notice_flag?userid=admin&quot;&gt;&lt;img src=&quot;/memo?memo=aaaaaa&quot;&gt;</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b0520b82-4c6e-4e19-91c7-ae40cf2d2c57/image.png" alt=""></p>
<p>/memo 페이지로 이동해보면 제대로 실행된 것을 볼 수 있다.</p>
<p>이제 해당 코드를 /flag 페이지에서 입력.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/7dd1c0d8-05b1-452c-8b28-ec38f6b0ed1d/image.png" alt=""></p>
<p>성공적으로 flag를 받아왔다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - xss-2]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-xss-2</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-xss-2</guid>
            <pubDate>Tue, 18 Mar 2025 14:59:55 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3d9f70af-af10-4547-8750-8cee44561eed/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">@app.route(&quot;/vuln&quot;)
def vuln():
    return render_template(&quot;vuln.html&quot;)</code></pre>
<p>소스코드는 이전 xss-1과 비교했을 때 /vuln 경로에서 param을 리턴하는 대신 html 파일 자체를 리턴하는 걸로 바뀐 것을 제외하면 전부 동일하다.</p>
<hr>
<h2 id="풀이">풀이</h2>
<p>우선 /vuln 페이지에서 동일하게 스크립트를 작성해본다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/fcb93a9b-b8a4-45e3-aa8a-edc39d7c6dcc/image.png" alt=""></p>
<p>스크립트가 동작하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/f460eac6-8946-43bb-85ab-df6570ebcdea/image.png" alt=""></p>
<p>소스코드를 보니 <code>&lt;script&gt;</code> 태그가 정상적으로 들어가있지만 태그 안쪽의 내용은 단순 문자열 처리를 한 것으로 보인다.</p>
<p>이번엔 <code>&lt;img&gt;</code> 태그를 입력해본다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4b143e08-1cc3-43b6-bd24-2ddd3655c6f0/image.png" alt=""></p>
<p><code>&lt;img&gt;</code> 태그는 정상적으로 작동한다.</p>
<p>해당 태그에 js를 실행시킬 수 있는 <code>onerror</code> 속성을 추가하고 이전에 사용했던 리다이렉션 코드를 값으로 입력한다. 이때 에러 발생 유도를 위해 <code>src</code> 속성을 추가해 아무 값이나 입력한다.</p>
<p><code>&lt;img src=&quot;x&quot; onerror=&quot;window.location.href=&#39;/memo?memo=&#39;document.cookie&quot;&gt;&lt;/img&gt;</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c8da9f1a-3c1c-423a-9fb7-6577377192ed/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - simple_sqli]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-simplesqli</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-simplesqli</guid>
            <pubDate>Mon, 10 Mar 2025 13:48:36 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/048e38f8-5b5f-481c-b709-fdaf9d4c91f7/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p>보통 SQLI 취약점을 탐색하기 위해 첫 번째로 &#39; 또는 &quot;를 넣어 테스트한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/7a46e391-0958-4250-b3f2-68cb627dfbb5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/13f05565-c5d5-4a8c-b9e5-24b73e3777d3/image.png" alt=""></p>
<p>틀렸다고 나온다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b2455729-c2bc-47f9-a333-9acc52678dc9/image.png" alt=""></p>
<p>이번엔 &quot;(쌍따옴표)</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b84d9ce1-3ac2-4a79-8751-5df91492dc75/image.png" alt=""></p>
<p>쌍따옴표를 넣으니 서버 에러가 출력되었다. 이는 서버에서 &quot;를 query에 넣어 처리한다는 의미이다.</p>
<p>여기에 DB에서 주석을 의미하는 <code>--</code>을 붙여 넣는다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/bc68e50b-4938-42c7-88f5-fccba12fd7f0/image.png" alt=""></p>
<p>그러면 패스워드 검증 부분이 주석처리되어 아이디만을 가지고도 로그인이 가능해진다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/90a26eb3-d5b4-483e-8fba-527d8f4ddc8e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - xss-1]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-xss-1</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-xss-1</guid>
            <pubDate>Mon, 10 Mar 2025 11:54:18 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/f270a0f3-6ed7-4bb0-9078-9a272b510f9b/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<p>우선 소스코드부터 확인.</p>
<pre><code class="language-python">def read_url(url, cookie={&quot;name&quot;: &quot;name&quot;, &quot;value&quot;: &quot;value&quot;}):
    cookie.update({&quot;domain&quot;: &quot;127.0.0.1&quot;})
    try:
        service = Service(executable_path=&quot;/chromedriver&quot;)
        options = webdriver.ChromeOptions()
        for _ in [
            &quot;headless&quot;,
            &quot;window-size=1920x1080&quot;,
            &quot;disable-gpu&quot;,
            &quot;no-sandbox&quot;,
            &quot;disable-dev-shm-usage&quot;,
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome(service=service, options=options)
        driver.implicitly_wait(3)
        driver.set_page_load_timeout(3)
        driver.get(&quot;http://127.0.0.1:8000/&quot;)
        driver.add_cookie(cookie)
        driver.get(url)
    except Exception as e:
        driver.quit()
        # return str(e)
        return False
    driver.quit()
    return True</code></pre>
<p>read_url() 이라는 함수가 정의되어 있다. url과 cookie 값을 받아 selenium으로 페이지를 로드한다. driver.add_cookie(cookie)로 입력받은 쿠키를 추가하고 driver.get(url)으로 해당 페이지를 로드한다.</p>
<blockquote>
<ul>
<li><strong>driver.get(url)</strong> : 내부적으로 GET 요청을 보내긴 하지만, 단순히 HTML을 받아오는 것만이 아니라, 페이지의 모든 리소스와 JavaScript도 로드하는 브라우저 기반 GET 요청.</li>
</ul>
</blockquote>
<ul>
<li><strong>브라우저 기반 요청</strong> : 실제 웹 브라우저(Chrome, Firefox, Edge 등)를 실행하여 웹 페이지를 로드하고, 사용자처럼 상호작용하는 방식.</li>
</ul>
<pre><code class="language-python">def check_xss(param, cookie={&quot;name&quot;: &quot;name&quot;, &quot;value&quot;: &quot;value&quot;}):
    url = f&quot;http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}&quot;
    return read_url(url, cookie)</code></pre>
<p>다음은 check_xss(). param과 cookie 값을 받아 url을 생성하고 read_url() 함수의 인자로 넣어 read_url() 함수를 반환한다.</p>
<pre><code class="language-python">@app.route(&quot;/&quot;)
def index():
    return render_template(&quot;index.html&quot;)


@app.route(&quot;/vuln&quot;)
def vuln():
    param = request.args.get(&quot;param&quot;, &quot;&quot;)
    return param


@app.route(&quot;/flag&quot;, methods=[&quot;GET&quot;, &quot;POST&quot;])
def flag():
    if request.method == &quot;GET&quot;:
        return render_template(&quot;flag.html&quot;)
    elif request.method == &quot;POST&quot;:
        param = request.form.get(&quot;param&quot;)
        if not check_xss(param, {&quot;name&quot;: &quot;flag&quot;, &quot;value&quot;: FLAG.strip()}):
            return &#39;&lt;script&gt;alert(&quot;wrong??&quot;);history.go(-1);&lt;/script&gt;&#39;

        return &#39;&lt;script&gt;alert(&quot;good&quot;);history.go(-1);&lt;/script&gt;&#39;</code></pre>
<p>다음은 라우팅에 대한 설명이다. 라우팅은 기본 페이지와 /vuln, /flag, /memo가 있는데 /vuln에선 파라미터로 param을 받아 그대로 반환한다. 접속해보면 기본적으로 alert() 함수가 실행되는 걸 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/087caaf2-9364-468d-985d-2923276e8c72/image.png" alt=""></p>
<p>중요한 건 /flag. 코드 중간에 <code>if not check_xss()</code> 조건문을 통해 check_xss() 함수에 사용자가 입력한 parma 값과, 쿠키로 flag 값을 전달하고 있다.</p>
<pre><code>memo_text = &quot;&quot;


   @app.route(&quot;/memo&quot;)
def memo():
    global memo_text
    text = request.args.get(&quot;memo&quot;, &quot;&quot;)
    memo_text += text + &quot;\n&quot;
    return render_template(&quot;memo.html&quot;, memo=memo_text)


app.run(host=&quot;0.0.0.0&quot;, port=8000)</code></pre><p>/memo는 사용자가 파라미터로 전달한 값을 페이지에 영구적으로 작성한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/eafe3196-fb91-4028-ac01-0196372e4711/image.png" alt=""></p>
<p>해당 페이지에 접속할 때마다 기본적으로 hello라는 문구가 작성된다.</p>
<p>정리해보면 /flag에서 데이터를 전송하면 플래그 값을 쿠키에 담고, param 값을 /vuln 페이지의 파라미터로 입력해 url 변수를 생성한다. 그렇게 생성된 param과 url을 read_url() 함수에 전달해 해당 페이지를 로드한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/75bdcf9c-f295-473c-b9bd-4b1e01d9ba8e/image.png" alt=""></p>
<p>/vuln 페이지는 xss 공격이 실행되는 페이지기 때문에 /flag에서 코드를 작성해 보내면 그대로 실행이 될 것이다. 그럼 코드를 작성해 /memo 경로로 쿠키값을 담아 리다이렉트 시키면 플래그가 /memo 경로에 작성될 것.</p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/6855ce3c-fb53-4e16-b6b9-269dc7f96a98/image.png" alt=""></p>
<p>여기에 <code>&lt;script&gt;document.location.href=&#39;/memo?memo=&#39;+document.cookie&lt;/script&gt;</code>를 입력한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/fe5aed0c-ae24-4f91-885c-95dd47304dfa/image.png" alt=""></p>
<p>good이라는 문구가 뜨면 성공적으로 전송된 것. 이제 /memo 페이지로 이동하면 플래그를 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/2341fb6a-edaf-44d5-9e34-37ad5388c462/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - session-basic]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-</guid>
            <pubDate>Mon, 10 Mar 2025 04:36:27 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/71c06a03-833b-4aaf-9cd6-dbcc33c3f63f/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/5ddfef44-5f45-4bf4-9306-98c877ba3025/image.png" alt=""></p>
<p>우측 상단에 로그인 버튼이 보인다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/f455d89c-3d9e-4714-8363-1e4660d51d1e/image.png" alt=""></p>
<p>F12를 눌러 소스코드를 보니 디폴트 계정이 guest/guest라고 나와있다. 해당 계정으로 로그인해보자.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a0d36f9c-7f74-48de-a7b7-6d73ff830672/image.png" alt=""></p>
<p>guest로 로그인이 되며 세션 ID가 부여된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c1e2971a-60d7-4adb-a173-2079b9c5dea0/image.png" alt=""></p>
<p>세션 ID는 로그인 할 때마다 무작위로 변경되는 것으로 보인다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/9d9eeec5-5845-42f2-b2e6-f1ef64a3eee4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/ed7dea18-a011-42d1-a3e6-81f37a5223ed/image.png" alt=""></p>
<p>변하는 값에 어떠한 패턴도 찾지 못해 때려맞추는 건 불가능할 것 같고, 길이가 너무 길어 브루트포스도 소용없을 것 같다.</p>
<p>이쯤에서 문제 파일 확인.</p>
<hr>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for

app = Flask(__name__)

try:
    FLAG = open(&#39;./flag.txt&#39;, &#39;r&#39;).read()
except:
    FLAG = &#39;[**FLAG**]&#39;

users = {
    &#39;guest&#39;: &#39;guest&#39;,
    &#39;user&#39;: &#39;user1234&#39;,
    &#39;admin&#39;: FLAG
}


# this is our session storage
session_storage = {
}</code></pre>
<p>users에 guest, user, admin 총 3개의 계정이 있고, 세션 저장소가 생성되어 있다.</p>
<pre><code class="language-python">@app.route(&#39;/&#39;)
def index():
    session_id = request.cookies.get(&#39;sessionid&#39;, None)
    try:
        # get username from session_storage
        username = session_storage[session_id]
    except KeyError:
        return render_template(&#39;index.html&#39;)

    return render_template(&#39;index.html&#39;, text=f&#39;Hello {username}, {&quot;flag is &quot; + FLAG if username == &quot;admin&quot; else &quot;you are not admin&quot;}&#39;)</code></pre>
<p>이 부분은 세션 스토리지에서 세션 아이디 값으로 username을 가져와 username에 맞는 화면을 표시해주는 역할이다. 즉, 세션 아이디 값과 username이 매핑되어 있고, 세션 아이디 값이 틀리면 평범한 index.html 페이지를 받게된다.</p>
<pre><code class="language-python">@app.route(&#39;/login&#39;, methods=[&#39;GET&#39;, &#39;POST&#39;])
def login():
    if request.method == &#39;GET&#39;:
        return render_template(&#39;login.html&#39;)
    elif request.method == &#39;POST&#39;:
        username = request.form.get(&#39;username&#39;)
        password = request.form.get(&#39;password&#39;)
        try:
            # you cannot know admin&#39;s pw
            pw = users[username]
        except:
            return &#39;&lt;script&gt;alert(&quot;not found user&quot;);history.go(-1);&lt;/script&gt;&#39;
        if pw == password:
            resp = make_response(redirect(url_for(&#39;index&#39;)) )
            session_id = os.urandom(32).hex()
            session_storage[session_id] = username
            resp.set_cookie(&#39;sessionid&#39;, session_id)
            return resp
        return &#39;&lt;script&gt;alert(&quot;wrong password&quot;);history.go(-1);&lt;/script&gt;&#39;</code></pre>
<p>입력한 username 값으로 users 리스트에서 패스워드(pw)를 가져온다. 그리고 내가 입력한 패스워드(password)와 비교해 동일할 경우 세션 아이디를 32자 랜덤 값으로 생성 후 세션 아이디와 입력한 username 값을 매핑시켜 세션 스토리지에 저장한다. 정리하면, username과 password를 users에 저장된 대로 정확히 입력했을 때 32자 랜덤 값으로 생성된 세션 아이디를 부여받으며 로그인이 된다.</p>
<p>그렇다면 현재 상황에서는 브루트포스 말고는 로그인 할 방법이 없다. 하지만 아래에 /admin 페이지가 존재하는 것을 볼 수 있다.</p>
<pre><code class="language-python">@app.route(&#39;/admin&#39;)
def admin():
    # developer&#39;s note: review below commented code and uncomment it (TODO)

    #session_id = request.cookies.get(&#39;sessionid&#39;, None)
    #username = session_storage[session_id]
    #if username != &#39;admin&#39;:
    #    return render_template(&#39;index.html&#39;)

    return session_storage</code></pre>
<p>코드를 보면 /admin 경로에 접속했을 때 세션 ID가 admin의 것이 아니면 평범한 index.html을 표시하는 코드가 작성되어 있다. 그러나, return을 제외하고 모든 줄이 주석처리 되어있다. 즉, /admin 경로에 접속하면 누구나 세션 저장소를 확인 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/9345601a-85e9-4893-ba7b-853fe9365ff4/image.png" alt=""></p>
<p>접속해보니 실제로 그동안 생성된 세션 아이디가 존재한다. admin 계정에 부여된 세션 아이디로 요청을 보내면 플래그를 얻을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/74789c49-5658-414f-b8d0-8afc757ec5ed/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - web-misconf-1]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-web-misconf-1-zbblo0ku</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-web-misconf-1-zbblo0ku</guid>
            <pubDate>Thu, 14 Nov 2024 08:46:28 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/434e71f3-b4f5-4cbc-8fc0-839ad7ee21ac/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/66f7e102-7791-454e-91e2-f3457fac8fe9/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 -
🌱 simple-web-request]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-simple-web-request</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-simple-web-request</guid>
            <pubDate>Thu, 14 Nov 2024 08:20:45 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/134824b4-ce52-403f-a1cc-71cdd94088bf/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/147992bc-1d28-471a-95a1-fae4bdf31067/image.png" alt=""></p>
<p>/step1 경로에서 param, param2 값을 입력받고 있는데, param에 getget, param2에 rerequest를 입력할 경우 다음 단계로 redirect된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/8ebb1e69-7068-46f6-b11f-a51d606b4024/image.png" alt=""></p>
<p>다음 단계에서도 prm1, prm2를 입력 받는데, prm1에 pooost, prm2에 requeeest를 입력하면 flag 페이지로 이동하며 flag 값을 얻을 수 있다.</p>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c8a0513e-a68e-4ef8-a44e-69c384b18376/image.png" alt=""></p>
<p><strong>param</strong> : getget
<strong>param2</strong> : rerequest</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d60df91e-8a48-4928-b047-1fc33a8680cb/image.png" alt=""></p>
<p><strong>prm1</strong> : pooost
<strong>prm2</strong> : requeeest</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/17f27c4a-d3fb-4815-861b-5cb2ba597b35/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - Session]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-Session</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-Session</guid>
            <pubDate>Thu, 14 Nov 2024 08:06:35 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a92e3a30-db56-48e2-bcf8-19341ca139dd/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">users = {
    &#39;guest&#39;: &#39;guest&#39;,
    &#39;user&#39;: &#39;user1234&#39;,
    &#39;admin&#39;: FLAG
}</code></pre>
<p>문제 파일에 있는 app.py를 보면 각 유저 정보가 적혀있는 걸 볼 수 있다.</p>
<pre><code class="language-python">@app.route(&#39;/&#39;)
def index():
    session_id = request.cookies.get(&#39;sessionid&#39;, None)
    try:
        username = session_storage[session_id]
    except KeyError:
        return render_template(&#39;index.html&#39;)

    return render_template(&#39;index.html&#39;, text=f&#39;Hello {username}, {&quot;flag is &quot; + FLAG if username == &quot;admin&quot; else &quot;you are not admin&quot;}&#39;)</code></pre>
<p>그리고 아래에는 username이 admin인 경우 flag 값을 출력하도록 코드가 작성되어있다. sessionid 값을 알아내 admin으로 로그인하면 바로 flag 값이 나오는 구조이다.</p>
<pre><code class="language-python">if __name__ == &#39;__main__&#39;:
    import os
    session_storage[os.urandom(1).hex()] = &#39;admin&#39;
    print(session_storage)
    app.run(host=&#39;0.0.0.0&#39;, port=8000)</code></pre>
<p>그리고 맨 아래를 보면 <code>session_storage[os.urandom(1).hex()] = &#39;admin&#39;</code> 코드가 적혀있는데, 이는 session 저장소에 1바이트의 랜덤 값을 16진수로 변경한 값을 admin의 키로 저장하는 코드이다. 즉, 1바이트의 랜덤 16진수 값을 알아내면 admin으로 로그인이 된다는 의미이다.</p>
<p>1바이트를 16진수로 변환하면 2자리가 나온다. 이를 bruteforce 공격을 통해 알아내보자.</p>
<hr>
<h2 id="풀이">풀이</h2>
<pre><code class="language-python">import requests as req

URL = &quot;http://host1.dreamhack.games:16646/&quot;

for i in range(0xff):

    print(&quot;Trying session {}&quot;.format(f&#39;{i:02x}&#39;))
    res = req.get(URL, cookies={&quot;sessionid&quot; : f&#39;{i:02x}&#39;})

    if &quot;flag is&quot; in res.text:
        print(&quot;----------------------------------\nSuccess Attack&quot;)
        print(res.text)
        break;</code></pre>
<p>admin의 sessionid 값은 16진수 2자리이기 때문에 range 인자값을 2자리 16진수 최댓값인 0xff로 입력한다. 그러면 i 값에 0부터 255까지의 정수 값이 차례로 저장된다. 이 값을 get 메서드를 사용해 서버로 요청을 전송할 때 i 값을 16진수로 변환해서 sessionid 키의 값으로 입력해주어야 한다. </p>
<p>16진수 변환은 형식 지정자를 이용한다. f&#39;{i:02x}&#39;에서 02는 2자리 수를 의미하고, x는 소문자 16진수를 의미한다.</p>
<p>마지막으로, 받아온 응답에 &quot;flag is&quot; 문자열이 포함되어 있으면 반복문을 멈추고 받아온 응답을 출력한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c3060531-67bd-42b9-8c40-efd4431a3783/image.png" alt=""></p>
<p>코드를 실행하면 위처럼 2자리 16진수를 하나씩 대입하다가 &quot;flag is&quot; 문자열을 발견하면 success 구문과 받아온 응답을 출력한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/99e1b927-3ab8-487b-8f8d-39193d69a8d7/image.png" alt=""></p>
<p>Squeezed text 버튼을 눌러보면 전체 응답 코드가 출력되고, 아래로 내려보면 플래그 값을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3de40721-1f29-4181-a3b1-0591810ca492/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - Flying Chars]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-phpreg-1qkx7r8b</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-phpreg-1qkx7r8b</guid>
            <pubDate>Thu, 14 Nov 2024 02:35:58 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/84a80c35-dfa3-40b5-befb-f13aae99c6cd/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b79f65a4-0585-4511-8f86-eee503b75ffc/image.png" alt=""></p>
<p>서버에 접속하면 문자들이 마구잡이로 날라다니는 것을 볼 수 있다. 문제 해결을 위해 우선 javascript 코드를 확인한다.</p>
<pre><code class="language-js">    const img_files = [&quot;/static/images/10.png&quot;, &quot;/static/images/17.png&quot;, &quot;/static/images/13.png&quot;,
                       &quot;/static/images/7.png&quot;,&quot;/static/images/16.png&quot;, &quot;/static/images/8.png&quot;,
                       &quot;/static/images/14.png&quot;, &quot;/static/images/2.png&quot;, &quot;/static/images/9.png&quot;,
                       &quot;/static/images/5.png&quot;, &quot;/static/images/11.png&quot;, &quot;/static/images/6.png&quot;,
                       &quot;/static/images/12.png&quot;, &quot;/static/images/3.png&quot;, &quot;/static/images/0.png&quot;,
                       &quot;/static/images/19.png&quot;, &quot;/static/images/4.png&quot;, &quot;/static/images/15.png&quot;
                       , &quot;/static/images/18.png&quot;, &quot;/static/images/1.png&quot;];</code></pre>
<p>소스 코드를 보면 img_files 안에 그림 파일들의 경로를 저장하고 있다. 이 그림들이 날라다니는 문자들 일 것 같다. 해당 경로로 이동해 그림 파일들을 하나씩 확인하는 것도 하나의 방법이다.</p>
<pre><code class="language-js">    const max_pos = self.innerWidth;
    function anim(elem, pos, dis){
      function move() {
        pos += dis;
        if (pos &gt; max_pos) {
          pos = 0;
        }
        elem.style.transform = `translateX(${pos}px)`;
        requestAnimationFrame(move);
      }
      move();
    }</code></pre>
<p>여기가 중요한 부분인데, 이 부분에 anim() 함수와 move() 함수가 정의되어 있다. anim() 함수는 elem(요소), pos(위치), dis(이동할 값)를 입력받아서 pos에 dis 값을 더하고, translateX() 함수를 사용해 요소를 ${pos}px만큼 X축으로 이동시킨다. 그리고 requestAnimationFrame() 함수를 사용해 move 함수를 재호출한다. 이렇게 되면 스탑 코드가 없기 때문에 위 과정이 무한정 반복된다.</p>
<pre><code class="language-js">    for(var i = 0; i &lt; 20; i++){
      anim(imgs[i], 0, Math.random()*60+20);
    }</code></pre>
<p>맨 아래에는 anim() 함수에 그림을 순서대로 입력해 위 함수를 실행하는 코드가 작성되어 있다. </p>
<p>정리하면, anim() 함수에 요소와 시작 위치 값, 그리고 이동시킬 값을 입력해 특정 요소를 X축으로 무한정 이동시키고 초기화하고를 반복하는 것이다.</p>
<p>여기서는 이 문제를 콘솔창을 이용해 마지막 for 반복문 코드를 변경해서 해결했다.</p>
<pre><code class="language-js">for(var i = 0; i &lt; 20; i++){
     anim(imgs[i], 50, 0);
   }</code></pre>
<p>기존 for 반복문을 보면 anim() 함수에 인자를 전달하고 있는데, 여기서 pos와 dis 인자 값을 50, 0으로 변경해주면, 시작 위치가 50px, 증가값이 0이기 때문에 모든 문자가 50px 위치에 고정되어 움직이지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/25bb611f-af57-46be-b81f-ca51084ad647/image.png" alt=""></p>
<p>이 문자들을 DH{} 내부에 넣어 입력하면 끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - phpreg]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-phpreg</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-phpreg</guid>
            <pubDate>Thu, 14 Nov 2024 01:27:23 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/5bcfa3ce-e735-4be9-b116-837b7e8cbe19/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/1713743c-0c89-47ef-ad83-b3246457f4fc/image.png" alt=""></p>
<p>서버에 접속해보면 문과 2개의 입력 필드가 보인다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c8b40c27-f742-4c1e-8085-51d24efff4e1/image.png" alt=""></p>
<p>소스코드를 보면 nickname과 password가 input1,2라는 이름으로 step2.php에 전송되는 것을 볼 수 있다.</p>
<p>그럼 우선 문제 파일에 있는 step2.php 파일 코드를 확인해보자.</p>
<pre><code class="language-php">&lt;?php
          // POST request
          if ($_SERVER[&quot;REQUEST_METHOD&quot;] == &quot;POST&quot;) {
            $input_name = $_POST[&quot;input1&quot;] ? $_POST[&quot;input1&quot;] : &quot;&quot;;
            $input_pw = $_POST[&quot;input2&quot;] ? $_POST[&quot;input2&quot;] : &quot;&quot;;</code></pre>
<p>input1,2(nickname, password)를 받아서 변수에 저장하고 있다.</p>
<pre><code class="language-php">            // pw filtering
            if (preg_match(&quot;/[a-zA-Z]/&quot;, $input_pw)) {
              echo &quot;alphabet in the pw :(&quot;;
            }
            else{
              $name = preg_replace(&quot;/nyang/i&quot;, &quot;&quot;, $input_name);
              $pw = preg_replace(&quot;/\d*\@\d{2,3}(31)+[^0-8\&quot;]\!/&quot;, &quot;d4y0r50ng&quot;, $input_pw);</code></pre>
<p>패스워드에 알파벳이 포함되면 경고문을 출력, 아닌 경우 정규표현식으로 name 값에서 nyang을 제거하고 있고, 패스워드에서는 특정 패턴을 만족하는 문자열을 d4y0r50ng라는 값으로 변환하고 있다.</p>
<pre><code class="language-php">              if ($name === &quot;dnyang0310&quot; &amp;&amp; $pw === &quot;d4y0r50ng+1+13&quot;) {
                echo &#39;&lt;h4&gt;Step 2 : Almost done...&lt;/h4&gt;&lt;div class=&quot;door_box&quot;&gt;&lt;div class=&quot;door_black&quot;&gt;&lt;/div&gt;&lt;div class=&quot;door&quot;&gt;&lt;div class=&quot;door_cir&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#39;;

                $cmd = $_POST[&quot;cmd&quot;] ? $_POST[&quot;cmd&quot;] : &quot;&quot;;</code></pre>
<p>name이 dnyang0310이고, pw가 d4y0r50ng+1+13이면 Step2로 넘어가며 cmd 변수가 정의된다.</p>
<pre><code class="language-php">                if ($cmd === &quot;&quot;) {
                  echo &#39;
                        &lt;p&gt;&lt;form method=&quot;post&quot; action=&quot;/step2.php&quot;&gt;
                            &lt;input type=&quot;hidden&quot; name=&quot;input1&quot; value=&quot;&#39;.$input_name.&#39;&quot;&gt;
                            &lt;input type=&quot;hidden&quot; name=&quot;input2&quot; value=&quot;&#39;.$input_pw.&#39;&quot;&gt;
                            &lt;input type=&quot;text&quot; placeholder=&quot;Command&quot; name=&quot;cmd&quot;&gt;
                            &lt;input type=&quot;submit&quot; value=&quot;제출&quot;&gt;&lt;br/&gt;&lt;br/&gt;
                        &lt;/form&gt;&lt;/p&gt;
                  &#39;;
                }
                // cmd filtering
                else if (preg_match(&quot;/flag/i&quot;, $cmd)) {
                  echo &quot;&lt;pre&gt;Error!&lt;/pre&gt;&quot;;
                }
                else{
                  echo &quot;&lt;pre&gt;--Output--\n&quot;;
                  system($cmd);
                  echo &quot;&lt;/pre&gt;&quot;;
                }
              }</code></pre>
<p> cmd에 아무런 값도 입력되지 않으면 cmd 폼을 생성하고, cmd에 값이 입력된 경우에는 입력 값에 flag 문자가 들어있으면 Error! 문구를 출력하고, flag 문자열이 없으면 cmd에 입력된 값을 OS에서 실행한 결과를 출력한다.</p>
<p>그럼 우선적으로 풀어야할 것은 아래 정규 표현식을 통한 검증을 우회하는 것.</p>
<pre><code class="language-php">            // pw filtering
            if (preg_match(&quot;/[a-zA-Z]/&quot;, $input_pw)) {
              echo &quot;alphabet in the pw :(&quot;;
            }
            else{
              $name = preg_replace(&quot;/nyang/i&quot;, &quot;&quot;, $input_name);
              $pw = preg_replace(&quot;/\d*\@\d{2,3}(31)+[^0-8\&quot;]\!/&quot;, &quot;d4y0r50ng&quot;, $input_pw);</code></pre>
<p>name 값의 nyang 검증의 경우 preg_replace()는 재귀적으로 검증을 수행하는 것이 아니기 때문에 nynyangang처럼 겹쳐서 사용하면 통과가된다.</p>
<p>pw 값의 정규 표현식을 풀어보면 <strong>[숫자 0개 이상]</strong>@<strong>[숫자 2~3개][31 문자 1개 이상][0부터 8, &quot;이 아닌 문자 1개]</strong>! 이다.</p>
<blockquote>
<p>💡 <strong>정규 표현식 옵션</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">옵션</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">()</td>
<td align="left">특정 문자를 하나의 그룹으로 처리</td>
</tr>
<tr>
<td align="center">^</td>
<td align="left">부정 표현</td>
</tr>
<tr>
<td align="center">*</td>
<td align="left">0개 이상</td>
</tr>
</tbody></table>
<p>검증을 통과하려면 name : dnyang0310에 pw : d4y0r50ng+1+13이어야 하기 때문에 아래와 같이 입력한다.</p>
<ul>
<li><strong>name</strong> : dnynyang0310</li>
<li><strong>pw</strong> : 0@00319!+1+13</li>
</ul>
<p>그럼 아래와 같이 Step2로 넘어가게 된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b496f93e-8202-4092-8180-31a87137521d/image.png" alt=""></p>
<p>flag 값은 ../dream/flag.txt에 존재한다고 했지만 flag 문자열을 입력하면 에러가 발생한다. 이를 우회하기 위해 와일드 카드(*)를 사용해 파일을 읽어온다. 와일드 카드는 모든 것을 의미한다. 예를들어, f*는 f로 시작하는 모든 파일, *.txt는 확장자가 txt인 모든 파일을 의미하게 된다.</p>
<p><code>cat ../dream/*</code>, <code>cat ../dream/f*</code>, <code>cat ../dream/*.txt</code> 등등 여러가지 방법으로 flag.txt 파일을 특정할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/85d7200d-638b-4088-9dcf-75406b300120/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - ex-reg-ex]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-ex-reg-ex</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-ex-reg-ex</guid>
            <pubDate>Wed, 13 Nov 2024 08:49:28 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a82b065d-e743-491a-b990-97f95b7bbc14/image.png" alt=""></p>
<hr>
<h2 id="풀이">풀이</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/f3a5ccf3-19eb-442d-ba0c-4d7af1fd6ac0/image.png" alt=""></p>
<p>GET, POST 방식으로 데이터를 입력 받는데, POST 방식으로 입력된 값이 정규표현식 패턴에 일치하면 플래그 값을 반환해주는 것으로 보인다.</p>
<pre><code class="language-python">re.match(r&#39;dr\w{5,7}e\d+am@[a-z]{3,7}\.\w+&#39;, input_val)</code></pre>
<p>위에서 사용된 옵션들은 다음과 같다.</p>
<blockquote>
<p>💡 <strong>정규 표현식 옵션</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">옵션</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">\w</td>
<td align="left">단일 문자</td>
</tr>
<tr>
<td align="center">{0,1}</td>
<td align="left">앞의 패턴이 최소 0개에서 최대 1개까지 반복</td>
</tr>
<tr>
<td align="center">\d</td>
<td align="left">숫자</td>
</tr>
<tr>
<td align="center">+</td>
<td align="left">앞의 패턴이 1개 이상 반복</td>
</tr>
<tr>
<td align="center">[a-z]</td>
<td align="left">a부터 z까지 지정</td>
</tr>
<tr>
<td align="center">\.</td>
<td align="left">. 을 단순 문자로 표현</td>
</tr>
</tbody></table>
<p>문자열 앞에 붙은 r은 문자열 내부에 존재하는 백 슬래시가 단순 문자로 처리되도록 만드는 옵션으로 파일 경로나 정규표현식 작성 시 주로 사용된다.</p>
<p>이외에는 단순 문자.</p>
<p>이를 토대로 정규표현식을 풀어보면, dr<strong>[문자 5~7개]</strong>e<strong>[숫자 1개 이상]</strong>am@<strong>[a부터 z까지 알파벳 중 3~7개]</strong>.<strong>[문자 1개 이상]</strong>가 된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/ffa1d623-ed3d-4e04-a5b3-68cbb025a7ff/image.png" alt=""></p>
<p>서버에 접속하면 입력 폼이 존재한다. 여기에 위에서 작성했던 dr<strong>aaaaa</strong>e<strong>0</strong>am@<strong>aaa</strong>.<strong>a</strong>을 입력하면 바로 플래그가 나온다. </p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/56c5eee1-e0cf-4bbf-a50b-80eb48e470c2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - pathtraversal]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-pathtraversal</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-pathtraversal</guid>
            <pubDate>Tue, 12 Nov 2024 04:05:31 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/839873b1-5105-4de6-854a-4e33cbc6c320/image.png" alt=""></p>
<hr>
<h2 id="소스코드">소스코드</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/aeeb4c33-bedf-4533-b3cd-5ac5e505296c/image.png" alt=""></p>
<p>중요한 부분만 살펴보면, /get_info 경로에서 GET으로 요청을 받게되면 get_info.html을 반환하고, POST로 요청을 받으면 {API_HOST}/api/user/{userid}에서 정보를 받아와 get_info.html에 추가해 클라이언트에게 반환한다. 여기서 userid는 사용자가 입력하는 값이다. 그럼 userid 대신 ../과 같은 pathtraversal 공격을 사용하면 상위 디렉토리 정보를 받아올 수도 있을 것이다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a101b709-d09d-4351-8964-27f711f4fe17/image.png" alt=""></p>
<p>또한, /api/flag 경로에 접근하면 FLAG를 반환해준다. FLAG는 flag.txt를 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/0e38df74-c8c3-40a4-a7d8-057368755031/image.png" alt=""></p>
<p>즉, userid 대신 path traversal 공격을 사용해 /api/flag 경로에 접근하면 flag 값을 얻을 수 있을 것이다.</p>
<hr>
<h2 id="풀이---python">풀이 - Python</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/885de226-8648-41df-a9d6-01555a97cce3/image.png" alt=""></p>
<p>페이지에 접속하면 Get User Info 링크가 존재한다. 클릭해서 이동.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3186453a-120f-41f1-83f2-b627ff51cbd4/image.png" alt=""></p>
<p>이동하면, userid 입력란에 guest가 적힌 것을 볼 수 있고, View를 누르면 해당 유저의 정보를 받아오게 된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/df950647-b5be-4732-a919-ec05cd451184/image.png" alt=""></p>
<p>pathtraversal을 테스트해보기 위해 ../를 입력해본다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/26428519-5479-432c-a7f5-27976efb691d/image.png" alt=""></p>
<p>View를 눌러 전송해보면 ../ 값이 Undefined로 변경되어 전송되는 것을 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/72753125-1e2b-4679-8ced-95bb62b0e179/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b1333412-b685-4328-93be-edef2f99c720/image.png" alt=""></p>
<p>결과로는 아무것도 받아오지 못한다. 특정 값을 프론트엔드 측에서 JS를 이용해 검증하는 것 같다. 이를 우회하려면 Proxy 혹은 python 등을 활용해 프론트엔드 측을 거치지 않고 바로 요청을 전송하는 방법이 있다. 여기서는 python을 사용해 우회한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3c1cbdbe-b6f4-409b-bdfc-0998f53c4a0c/image.png" alt=""></p>
<pre><code class="language-python">//python http 요청 모듈 requests import
import requests as req

//URL, 파라미터(data) 지정
URL = &quot;http://host3.dreamhack.games:11536/get_info&quot;
data = {&quot;userid&quot; : &quot;../flag&quot;}

res = req.post(URL, data=data)

print(res.text)</code></pre>
<p>이전에 파라미터로 userid만 전송하는 것을 봤기 때문에 userid에 ../flag를 입력해 전송한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/54d01835-d956-44b3-9d43-263709aa39e0/image.png" alt=""></p>
<p>응답을 확인해보면 중간에 플래그 값이 적혀 있는 것을 볼 수 있다.</p>
<hr>
<h2 id="풀이-개발자-도구">풀이-개발자 도구</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c75a1b31-bfef-4043-9c77-97f95b9c49a7/image.png" alt=""></p>
<p>개발자 도구 &gt; setting &gt; 자바스크립트 사용 중지를 체크하고 userid 입력란에 ../flag를 입력하면 바로 플래그 값을 얻을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/36a6608f-b7fc-4cb9-9a06-062b0301f286/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Forensic] VeraCrypt]]></title>
            <link>https://velog.io/@song-_-/Forensic-VeraCrypt</link>
            <guid>https://velog.io/@song-_-/Forensic-VeraCrypt</guid>
            <pubDate>Tue, 12 Nov 2024 02:45:08 GMT</pubDate>
            <description><![CDATA[<h2 id="veracrypt">VeraCrypt</h2>
<ul>
<li>오픈 소스 암호화 프로그램</li>
<li>하나의 디스크에 Standard volume &amp; Hidden volume을 생성하고, 각 volume에 다른 암호를 설정할 수 있다.</li>
<li>key파일 확장자 hc or key</li>
</ul>
<p>3GB 정도의 USB를 가지고 실습. </p>
<h2 id="standard-volume-생성">Standard volume 생성</h2>
<h3 id="1-veracrypt-설치-후-실행">1) VeraCrypt 설치 후 실행</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/ece507b3-c379-437c-9eb9-3ab945da1344/image.png" alt=""></p>
<h3 id="2-volume-만들기">2) volume 만들기<img src="https://velog.velcdn.com/images/song-_-/post/f27b3805-e001-429a-860a-683a4f3f7880/image.png" alt=""></h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/db1bcee2-f04d-4144-8972-57f1b2d35f73/image.png" alt=""></p>
<p>Create Volume 클릭</p>
<h3 id="3-암호화-대상">3) 암호화 대상</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/0a9bba4a-9e27-4aec-a37d-3081ae3956a8/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>암호화된 파일 컨테이너 생성 -&gt; 파일 암호화</li>
<li>비 시스템 파티션/드라이브 암호화 -&gt; HDD, USB 암호화</li>
<li>시스템 파티션 또는 전체 시스템 드라이브 암호화 -&gt; OS 암호화</li>
</ol>
<p>-&gt; 1번 선택</p>
<h3 id="4-암호화-대상">4) 암호화 대상</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d6844360-384a-48e9-a1ac-9b7baf3e41c9/image.png" alt=""></p>
<blockquote>
<ol>
<li>Standard volume</li>
<li>Hidden volume</li>
</ol>
</blockquote>
<p>-&gt; 1번 선택</p>
<h3 id="5-파일-저장-위치">5) 파일 저장 위치</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/74bb28c2-8883-49ea-b14e-ce17829aabe8/image.png" alt=""></p>
<p>-&gt; Select File</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/efc5b690-e2aa-4b3a-a645-03be91e5676a/image.png" alt=""></p>
<p>저장할 폴더에 파일 이름과 파일 형식 .hc로 변경해 저장.</p>
<h3 id="6-암호화-설정">6) 암호화 설정</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a38a2018-a9b5-414a-8320-e74c03058814/image.png" alt=""></p>
<p>암호화 알고리즘 : AES
Hash 알고리즘 : SHA-512</p>
<h3 id="7-volume-크기">7) Volume 크기</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/7552e248-2145-4829-a862-4cd20b01de44/image.png" alt=""></p>
<p>-&gt; 100MB</p>
<h3 id="8-volume-패스워드">8) Volume 패스워드</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/38030877-322f-4146-aa83-954cb88bf409/image.png" alt=""></p>
<blockquote>
<p><strong>옵션</strong></p>
</blockquote>
<ol>
<li>Use Keyfiles : 암호 대신 키 값이 저장된 파일 사용. </li>
<li>Display password : 패스워드 보이게</li>
<li>Use PIM : PIM 사용</li>
</ol>
<p>암호에 추가로 Use Keyfiles 옵션을 추가하면 마운트 시 암호와 Keyfile 둘 다 입력해주어야 마운트할 수 있다.</p>
<p>20자 이하로 설정하면 경고창이 뜨는데 그냥 무시하고 넘어가도 된다.</p>
<h3 id="9-volume-형식">9) Volume 형식</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d4b095b7-6222-4714-80e6-32aac0a0c17f/image.png" alt=""></p>
<p>여기서 마우스를 막 이동시키면 아래 바가 채워지면서 암호화가 높아진다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/22d0b759-9b31-4c66-9943-25247cd37ef3/image.png" alt=""></p>
<h3 id="10-생성-완료">10) 생성 완료</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c58442a3-2440-4c2e-86c3-57a29781f582/image.png" alt=""></p>
<p>이전에 지정한 폴더로 이동해보면 .hc 확장자 파일이 하나 생성되어 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/ebffa818-9a1a-4104-ab74-554202863fea/image.png" alt=""></p>
<h3 id="11-생성된-volume-마운트">11) 생성된 Volume 마운트</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/46188820-3dad-4293-ada3-43cc1095f415/image.png" alt=""></p>
<p>-&gt; Select File 눌러서 .hc 확장자 파일 지정하고, 마운트할 드라이브를 선택</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/8d9efc03-79f3-4831-bdb3-d69955b80021/image.png" alt=""></p>
<p>-&gt; 아래 Mount 버튼 클릭</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/6bf58bb9-5108-4d51-91e9-ff0284bb884a/image.png" alt=""></p>
<p>-&gt; 이전에 설정한 패스워드 입력 후 OK</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/5c8764be-8f03-42de-a637-1fad1ee474ca/image.png" alt=""></p>
<p>내 컴퓨터로 이동해보면 Q 드라이브가 생성된 것을 볼 수 있다.</p>
<h3 id="12-마운트-해제">12) 마운트 해제</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/399a0e87-d74c-4371-b87a-f95bbd81aa56/image.png" alt=""></p>
<p>Dismount All을 누르면 마운트가 해제된다.</p>
<h2 id="hidden-volume-생성">Hidden Volume 생성</h2>
<h3 id="1-volume-형식-지정">1) Volume 형식 지정</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c138aac1-eb03-4768-a479-0a022baf306d/image.png" alt=""></p>
<p>Volume 형식을 Hidden Volume으로 지정.</p>
<h3 id="2-volume-생성-모드-선택">2) Volume 생성 모드 선택</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a089638b-5d0b-4ea4-9842-2908bedc3672/image.png" alt=""></p>
<ol>
<li>Normal : Standard 생성 후 Hidden 생성</li>
<li>Direct : 기존 Volume에 Hidden 생성</li>
</ol>
<h3 id="3-standard-파일-지정">3) Standard 파일 지정</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/da29afe6-4b28-4094-a87d-2148944cb6bf/image.png" alt=""></p>
<p>이전에 생성한 Standard 파일 지정</p>
<h3 id="4-outer-volume-패스워드">4) Outer Volume 패스워드</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4e1bc27f-c427-42ed-bafa-acce10469b74/image.png" alt=""></p>
<p>Outer Volume에서 사용할 패스워드 입력. Standard Volume 생성할 때 입력한 패스워드는 더 이상 사용되지 않고, Outer Volume 패스워드와 Hidden Volume 패스워드 두 개를 사용한다. 이 때, Outer Volume과 hidden Volume 패스워드는 다르게 입력해주어야 한다.</p>
<h3 id="5-hidden-volume-옵션-설정-시작">5) Hidden Volume 옵션 설정 시작</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a1350474-6c65-4e44-8d6c-4310216660fd/image.png" alt=""></p>
<p>-&gt; Next</p>
<h3 id="6-암호화-방식">6) 암호화 방식</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/480b6fc6-9ae8-4a83-9412-0add0b472dc4/image.png" alt=""></p>
<h3 id="7-volume-크기-1">7) Volume 크기</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/393593e1-73a8-4262-b1d5-07182821788a/image.png" alt=""></p>
<p>-&gt; 50MB</p>
<h3 id="8-hidden-volume-패스워드">8) Hidden Volume 패스워드</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/33168ef0-f585-40b5-bbf7-766e50ee56fd/image.png" alt=""></p>
<h3 id="9-hidden-volume-형식">9) Hidden Volume 형식</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a4f7f034-cf7f-4d98-9146-0a52cb4221a6/image.png" alt=""></p>
<h3 id="10-hidden-volume-생성-완료">10) Hidden Volume 생성 완료</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/39a9e781-3f98-47df-ad45-b7eaaf64270b/image.png" alt=""></p>
<p>-&gt; Exit</p>
<h3 id="11-마운트">11) 마운트</h3>
<p>마운트를 할 때 Outer 패스워드를 입력하면 외부 볼륨, Hidden 패스워드를 입력하면 Hidden 볼륨이 마운트된다.</p>
<ul>
<li><p>외부 볼륨 마운트
<img src="https://velog.velcdn.com/images/song-_-/post/340dbd29-18b3-4453-8645-fb684dbccd48/image.png" alt=""></p>
</li>
<li><p>히든 볼륨 마운트
<img src="https://velog.velcdn.com/images/song-_-/post/0437140a-a120-4f9b-99f7-2e390b3d25c3/image.png" alt=""></p>
</li>
</ul>
<h2 id="usb-암호화">USB 암호화</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/90b2ae66-64f9-4830-92f6-bd08713348b5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/ab66c639-4f88-491f-8821-f83aa3975bc1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/445d6b67-38a1-44ea-944b-bcc268516450/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3f020e03-f17b-430f-8000-15c81f2ea1b1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Wargame] 드림핵 - Carve party]]></title>
            <link>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-php7cmp4re-x4np4g2u</link>
            <guid>https://velog.io/@song-_-/Wargame-%EB%93%9C%EB%A6%BC%ED%95%B5-php7cmp4re-x4np4g2u</guid>
            <pubDate>Fri, 08 Nov 2024 08:10:39 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/9c30aa1c-48cc-4ad1-b8bf-6611bc936860/image.png" alt=""></p>
<p>이번 문제는 따로 서버가 없기 때문에 문제 파일을 다운로드 받아 HTML 파일을 실행.</p>
<hr>
<h2 id="풀이---개발자-도구">풀이 - 개발자 도구</h2>
<p><img src="https://velog.velcdn.com/images/song-_-/post/0fd2e6d3-08f2-47a9-8019-35cb03a722d5/image.png" alt=""></p>
<p>웹 사이트에는 호박이 덩그러니 있고, 아래에 10000번을 더 클릭하라고 나와있다.</p>
<p>우회할 방법을 찾기 위해 소스코드를 확인.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4eb60fc9-de19-40cf-b9dc-cf0feb7b56df/image.png" alt=""></p>
<p>소스코드 내에 스크립트가 존재한다. 이를 해석해보면, 호박(jack-target)을 클릭했을 때 counter 값을 1 증가시킨 후, 만약 counter가 10000 이하이고, 100의 배수인 경우 pie 값에 ((pie ^ 0xff) + (i * 10)) &amp; 0xff 연산을 수행하고 있다. 즉, 단순히 코드를 변경하는 게 아니라 진짜로 10000번을 클릭해야한다.</p>
<p>문제 풀이를 위해 console 창에서 아래 반복문을 실행한다.</p>
<pre><code class="language-jquery">i = 0

while(i&lt;10001){
$(&#39;jack-target&#39;).click();
i++
}</code></pre>
<p>$()는 jquery에서 CSS 선택자를 이용해 특정 요소를 지정하는 구문. 이를 사용해 호박을 지정해준다. 그리고 click() 메서드로 클릭. 이를 10001번 반복한다. 왜냐하면, 10000번 클릭 후 한 번 더 클릭해야 플래그 값을 얻을 수 있기 때문.</p>
<p>실행하면 바로 플래그 값을 얻을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/bb9d3425-65d9-4a22-8f4b-2156d19f1be1/image.png" alt=""></p>
<h2 id="풀이---selinux">풀이 - Selinux</h2>
<p>해결 방법은 여러가지가 있겠지만 여기서는 selenium을 사용한다. 우선, cmd에서 <code>python.exe -m pip install --upgrade pip</code> 명령어로 pip를 업그레이드한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a003fd9a-3e8d-417a-9758-5a1ef1847361/image.png" alt=""></p>
<p>그리고 <code>pip install selenium</code> 명령어로 selenium을 설치해준다. 설치가 완료되면 python 코드를 작성한다.</p>
<h3 id="1-모듈-import">1) 모듈 import</h3>
<pre><code class="language-python">from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By</code></pre>
<p>chrome 웹 드라이버 지정을 위한 webdriver, service 모듈을 import. 그리고 요소 지정 및 특정 행동 실행을 위한 ActionChains와 By 모듈을 import.</p>
<h3 id="2-드라이버-및-url-지정">2) 드라이버 및 URL 지정</h3>
<p><a href="https://googlechromelabs.github.io/chrome-for-testing/#stable">크롬 드라이버</a>는 해당 URL에서 받을 수 있다. 이를 현재 작업 중인 python 파일과 동일한 위치에 옮긴다.</p>
<pre><code class="language-python">#드라이버 지정
service = Service(&quot;chromedriver.exe&quot;)
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(service=service, options=options)

#URL 지정
url = &#39;file:///C:/Users/admin/Downloads/jack-o-lantern.html&#39;

#창 크기 설정
driver.maximize_window()

#창 오픈
driver.get(url)</code></pre>
<h3 id="3-action-실행">3) action 실행</h3>
<pre><code class="language-python">#action 객체 생성
action = ActionChains(driver)

#요소 지정
pumkin = driver.find_element(By.ID, &quot;jack-target&quot;)
action.move_to_element(pumkin).perform()</code></pre>
<p>특정 행동 수행을 위해 action 객체를 생성하고, 요소를 지정. 호박을 클릭해야하니 호박의 ID 값을 가져와 find_element()의 인자로 입력한다. 호박의 ID 값은 개발자 도구에서 확인 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a32e45b5-f8b0-46c0-837d-101f559a5ca0/image.png" alt=""></p>
<pre><code class="language-python">#지정 요소 10001번 클릭
i = 0

while (i&lt;10001):
    pumkin.click()
    i += 1</code></pre>
<p>이제 반복문을 만들어  호박을 10001번 클릭한다.</p>
<h3 id="4-실행">4) 실행</h3>
<p>코드를 실행하면 점점 호박에 얼굴이 생겨나고, 10001번 클릭이 완료되면 플래그 값을 얻을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d4bd6f75-357c-4a5c-8826-08accc452052/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Cloud] AWS - CloudFormation]]></title>
            <link>https://velog.io/@song-_-/Cloud-AWS-CloudFormation</link>
            <guid>https://velog.io/@song-_-/Cloud-AWS-CloudFormation</guid>
            <pubDate>Fri, 01 Nov 2024 07:06:20 GMT</pubDate>
            <description><![CDATA[<h2 id="cloudformation">CloudFormation</h2>
<p>CloudFormation : VPC, EC2와 같은 리소스들을 템플릿(코드)으로 구성하고 Stack을 생성해 자동 관리할 수 있다. IaC : Infastructure as Code</p>
<p>CloudFormation 메인 페이지에서 스택 생성 클릭</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4dd9a0bc-db0b-4e01-b414-33c77e7c5cb1/image.png" alt=""></p>
<h3 id="1-사전-조건---템플릿-준비">1) 사전 조건 - 템플릿 준비</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/eaeb157e-6e71-433d-a313-aeeb09d03f9c/image.png" alt=""></p>
<p>기존 템플릿 선택 </p>
<h3 id="2-템플릿-지정">2) 템플릿 지정</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/35a091c7-5b24-4513-89d5-ec43cf73f37d/image.png" alt=""></p>
<p>템플릿 파일 업로드 선택 -&gt; 아래 파일 선택을 클릭해 미리 작성해놓은 yaml 파일 선택 -&gt; 다음</p>
<h3 id="3-스택-이름-제공">3) 스택 이름 제공</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3ec8c779-b4ea-4a0b-8b62-7570f87f4a34/image.png" alt=""></p>
<p>스택 이름 작성</p>
<h3 id="4-파라미터">4) 파라미터</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/f830a6d7-b8c0-4526-aa81-34f7333c39eb/image.png" alt=""></p>
<p>사용할 키 선택 후 다음</p>
<h3 id="5-스택-옵션-구성">5) 스택 옵션 구성</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/fe58f4f5-938d-4010-bf08-f530fa5886fd/image.png" alt=""></p>
<p>설정 없이 다음</p>
<h3 id="6-검토-및-작성">6) 검토 및 작성</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/99b034e0-16ed-46a5-91ea-5fa7199c36fa/image.png" alt=""></p>
<p>설정 값 확인 후 전송</p>
<h2 id="인스턴스">인스턴스</h2>
<h3 id="1-생성-확인">1) 생성 확인</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/605b3eff-8a9b-4107-b8d5-3aec069a1395/image.png" alt=""></p>
<p>EC2 -&gt; 인스턴스로 가보면 웹 서버 인스턴스가 생성된 것을 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/233e0a28-e71d-4b9a-8754-c311b56b3411/image.png" alt=""></p>
<p>아이피를 브라우저에 입력하면 웹 서버 화면이 나온다.</p>
<h3 id="2-삭제">2) 삭제</h3>
<p>삭제 할  때는 스택 관리 페이지에서 스택을 삭제해주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/96b973fb-fd4f-498e-8de8-b4c8400f3231/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Cloud] AWS - Port Forwarding]]></title>
            <link>https://velog.io/@song-_-/Cloud-AWS-Port-Forwarding</link>
            <guid>https://velog.io/@song-_-/Cloud-AWS-Port-Forwarding</guid>
            <pubDate>Fri, 01 Nov 2024 01:15:15 GMT</pubDate>
            <description><![CDATA[<h2 id="port-forwarding">Port Forwarding</h2>
<p>서버에서 HTTP 서버를 실행하고 해당 아이피로 접속해보면  방화벽 때문에 접속이 되지 않는다. 그래서 포트 포워딩을 해주어야 한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/6e0541fc-7c28-40fb-99c3-461eae11175a/image.png" alt=""></p>
<p>인스턴스를 클릭하고 중간으로 내려보면 여러 탭들이 존재한다. 여기서 보안 탭을 클릭.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/75b4bfe0-2997-4aa4-b8f6-0ef734d2a5e7/image.png" alt=""></p>
<p>보안 그룹 클릭</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/481df3f4-94dd-4bcc-8be6-a3020e3d2e24/image.png" alt=""></p>
<p>여기서 인바운드 규칙을 생성할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/06992335-6e17-4714-a6cb-3b46c17366c0/image.png" alt=""></p>
<p>인바운드 규칙 편집 클릭</p>
<p>좌측 하단 규칙 추가 후 HTTP 규칙 추가</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3617a43d-b988-44aa-975f-c23ddd305f55/image.png" alt=""></p>
<p>유형 : HTTP
소스 유형 : Anywhere-IPv4</p>
<p>위처럼 설정 후 우측 하단 규칙 저장 버튼 클릭</p>
<p>다시 웹 사이트에 접속해보면 기존에 설정한 내용이 출력된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/39ba9ae1-3860-424a-a16e-6dc8a83b9a2e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Cloud] Kubernetes - 기본 사용법]]></title>
            <link>https://velog.io/@song-_-/Cloud-Kubernetes-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@song-_-/Cloud-Kubernetes-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Thu, 31 Oct 2024 00:09:49 GMT</pubDate>
            <description><![CDATA[<h2 id="kube-ctx-kube-ns-kube-ps1">kube-ctx, kube-ns, kube-ps1</h2>
<p><strong>kube-ctx (context)</strong> : 여러 클러스터 중 원하는 클러스터 선택
<strong>kube-ns (namespace)</strong> : 단일 클러스터 내의 자원별 격리할 때 구분하는 용도.
<strong>kube-ps1</strong> : 프롬프트</p>
<h2 id="kube-ctx">kube-ctx</h2>
<h3 id="1-설치">1) 설치</h3>
<p><code>k krew install ctx</code></p>
<h3 id="2-클러스터-확인">2) 클러스터 확인</h3>
<p><code>k ctx</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/78eb6e88-741e-4c77-acaa-7e19852bd8da/image.png" alt=""></p>
<h3 id="3-클러스터-변경">3) 클러스터 변경</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/74b5b267-966b-4da9-8d17-be2af621f998/image.png" alt=""></p>
<hr>
<h2 id="kube-ns">kube-ns</h2>
<h3 id="1-설치-1">1) 설치</h3>
<p><code>k krew install ns</code></p>
<h3 id="2-네임-스페이스-확인">2) 네임 스페이스 확인</h3>
<p><code>k ns</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4ee612c3-69c5-43cf-ad71-fc48a30118b0/image.png" alt=""></p>
<h3 id="3-네임-스페이스-변경">3) 네임 스페이스 변경</h3>
<p><code>k ns [namespace]</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/dade60f8-eab1-4ce0-ac32-9a8deacc6a45/image.png" alt=""></p>
<h3 id="4-구성-요소-확인">4) 구성 요소 확인</h3>
<p><img src="https://velog.velcdn.com/images/song-_-/post/952e1370-9fe4-4f72-bf72-32f6eada4dcd/image.png" alt=""></p>
<hr>
<h2 id="kube-ps1">kube-ps1</h2>
<h3 id="1-설치-2">1) 설치</h3>
<p><code>git clone https://github.com/jonmosco/kube-ps1.git</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d739db82-f2de-4405-9784-a04acb622ffa/image.png" alt=""></p>
<p>여기서 kube-ps1.sh 파일에 실행 권한을 부여해준다.</p>
<p><code>chmod +x kube-ps1.sh</code></p>
<h3 id="2-환경-변수-등록">2) 환경 변수 등록</h3>
<p>~/.bashrc 파일 맨 아래 구문 작성</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/faf632bc-75a4-45b5-904f-c80cb9054754/image.png" alt=""></p>
<p>적용을 위해 <code>source ~/.bashrc</code> 실행</p>
<p>실행하면 아래와 같이 쉘이 변경된다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/44293165-4363-45c6-8eb6-4b403ddae6d1/image.png" alt=""></p>
<hr>
<h2 id="nginx">nginx</h2>
<h3 id="1-설치-3">1) 설치</h3>
<p><code>k run nginx --image=nginx</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/1474d1b4-4fb9-475a-9152-3c85301dbdd6/image.png" alt=""></p>
<p><code>kgp -o wide</code>로 pod 목록 확인</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/1c97bed1-b6da-4070-9148-217b7f63b81a/image.png" alt=""></p>
<h3 id="2-삭제">2) 삭제</h3>
<p><code>k delete pod nginx</code></p>
<h3 id="3-여러-개-생성">3) 여러 개 생성</h3>
<p><code>k scale deployment httpd --replicas 10</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Cloud] AWS - EC2 인스턴스 생성]]></title>
            <link>https://velog.io/@song-_-/Cloud-AWS</link>
            <guid>https://velog.io/@song-_-/Cloud-AWS</guid>
            <pubDate>Thu, 24 Oct 2024 07:02:01 GMT</pubDate>
            <description><![CDATA[<p>우선 AWS 회원가입 후 로그인</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/c6eab1cc-539c-4c26-b989-b79f0de519a7/image.png" alt=""></p>
<p>왼쪽 목록 창 열고 모든 서비스로 이동.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/e5e144d1-ec8e-46bc-a882-94dceee0f600/image.png" alt=""></p>
<p>컴퓨팅 밑에 EC2 선택</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/bfc4c218-37fd-4e30-abfb-bc8cd268da55/image.png" alt=""></p>
<p>중간에 인스턴스 시작</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/5df87b22-dbfe-463b-8b6a-dd032ff94abf/image.png" alt=""></p>
<p>인스턴스 이름 작성</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4d078299-594b-4e0e-977e-5507193036e1/image.png" alt=""></p>
<p>아래 OS 선택</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/a3180982-e99b-4ff7-a191-7c404cba3f59/image.png" alt=""></p>
<p>선택 후 아래 AMI 목록을 보면 오른쪽에 &quot;프리 티어 사용 가능&quot;이라는 문자가 적혀있는 것들이 있다. 이것들은 무료로 사용 가능.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/169694ec-d388-48c2-8d53-a3e4e3decf62/image.png" alt="">
<img src="https://velog.velcdn.com/images/song-_-/post/ec4563a8-1aaf-4d13-98e9-32ee536b3bba/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/e0ba6d27-6e6a-4574-8629-9e12ee9e6bd2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/8d4b3385-9ca2-4352-b186-940a201e9991/image.png" alt="">
<img src="https://velog.velcdn.com/images/song-_-/post/e98baf34-0514-4217-834a-52c0b4361830/image.png" alt="">
<img src="https://velog.velcdn.com/images/song-_-/post/f6bb8365-6b1e-44fc-ac39-92b7e046bf3d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3d04aaa4-2264-4653-af36-3d03b513490b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/bc7e48d5-46eb-4253-a9c8-c676fc8e42dc/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/fb05ff69-2e16-42f1-b687-145e266551bf/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/1ae0641f-1362-4f94-9b3a-5f383e6c02b1/image.png" alt=""></p>
<p>ID : ec2-user</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/d615107d-beda-491c-ac35-e2926bafd69c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Cloud] Kubernetes - 설치 및 설정]]></title>
            <link>https://velog.io/@song-_-/Cloud-Kubernetes-</link>
            <guid>https://velog.io/@song-_-/Cloud-Kubernetes-</guid>
            <pubDate>Thu, 24 Oct 2024 07:01:17 GMT</pubDate>
            <description><![CDATA[<h2 id="설치">설치</h2>
<h3 id="1-git-설치">1) git 설치</h3>
<p><code>apt install -y git</code></p>
<h3 id="2-clone">2) clone</h3>
<p><code>git clone -b v2.16.0 https://github.com/kubernetes-sigs/kubespray.git</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/52df6934-7d9f-49b5-91e6-06f479bbd7e6/image.png" alt=""></p>
<p>해당 디렉토리로 이동해 <code>apt update -y</code></p>
<h3 id="3-필수-패키지-설치">3) 필수 패키지 설치</h3>
<p>kubernetes는 파이썬으로 동작한다. 그래서 pip를 설치해주어야 한다.</p>
<p><code>apt install -y python3-pip</code></p>
<p>kubernetes 디렉토리 안에 requirements.txt에 k8s 실행을 위해 설치해야할 모듈 정보가 적혀있다. </p>
<p><code>cat requirements.txt</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/418e6605-6e54-4164-8014-0e342cfff837/image.png" alt=""></p>
<p>위 정보를 수정해준다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/bb7d4562-ce00-4dc5-a497-6d86e851e872/image.png" alt=""></p>
<p>해당 파일을 pip3 명령어의 -r 옵션 인자로 입력한다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/07a7ea78-b680-48a5-8337-089e06c04022/image.png" alt=""></p>
<p>위 문구가 출력될 경우 --break-system-packages 옵션 추가해서 다시 입력</p>
<h3 id="4-inventory">4) Inventory</h3>
<p>인벤토리 sample을 mycluster라는 이름으로 복사해준다.</p>
<p><code>cp -rpf inventory/sample/ inventory/mycluster</code></p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/29edd005-d4f5-4acb-ad20-c7ba9d8ed301/image.png" alt=""></p>
<h3 id="5-노드-등록-마스터--워커">5) 노드 등록 (마스터 &amp; 워커)</h3>
<p>inventory/mycluster 디렉토리에 있는 inventory.ini 파일에 노드들을 등록해준다.</p>
<ul>
<li><p>[all] : 전체 노드 등록
<img src="https://velog.velcdn.com/images/song-_-/post/f58f874a-a48b-4e59-93d9-992d78ca1d21/image.png" alt=""></p>
</li>
<li><p>[kube_control_plane] : 마스터 노드 등록
<img src="https://velog.velcdn.com/images/song-_-/post/83f51b4b-2a67-4d75-bcbb-7aac13af06b7/image.png" alt=""></p>
</li>
<li><p>[etcd] : 마스터 노드 등록
<img src="https://velog.velcdn.com/images/song-_-/post/e922fde9-f4d1-4318-8891-f550c4cd5cd0/image.png" alt=""></p>
</li>
<li><p>[kube_node] : 워커 노드 등록
<img src="https://velog.velcdn.com/images/song-_-/post/0893ddc2-3eb9-4e4c-8e12-1ff22f7f5b5f/image.png" alt=""></p>
</li>
</ul>
<h3 id="6-파일-설정">6) 파일 설정</h3>
<p>inventory/mycluster/group_vars/k8s_cluster 밑에 k8s-cluster.yml 파일 구문 수정.</p>
<ul>
<li><p>129라인 구문 수정
<img src="https://velog.velcdn.com/images/song-_-/post/5e2cf50e-b205-42b3-9d54-a6cdb5f6cece/image.png" alt=""></p>
</li>
<li><p>229라인 구문 확인
<img src="https://velog.velcdn.com/images/song-_-/post/53ed8f8f-360f-4bfe-b8bf-4452bc8f4f18/image.png" alt=""></p>
</li>
<li><p>240라인 구문 수정
<img src="https://velog.velcdn.com/images/song-_-/post/b036290c-112b-4343-bfb5-75380ec43a0e/image.png" alt=""></p>
</li>
</ul>
<h3 id="7-kubernetes-설치">7) Kubernetes 설치</h3>
<p><code>ansible-playbook -i inventory/mycluster/inventory.ini --become --become-user=root -v cluster.yml</code></p>
<p><code>snap install kubectl --classic</code> </p>
<p><code>kubectl get node -o wide</code> 이 명령어를 입력했을 때 각 노드들 정보가 출력되면 성공적으로 설치된 것이다.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/4ec7166e-008a-4381-a46e-582cfdb253fa/image.png" alt=""></p>
<h3 id="8-bashrc-설정">8) bashrc 설정</h3>
<p>~/.bashrc 파일에 아래 구문 작성</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/5f70b635-7b9d-4d3c-9a5d-61b1eae3e904/image.png" alt=""></p>
<p>위 구문 아래에 추가로 alias 작성</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/3b404040-6b7e-4bda-bcc0-872d04c8ea30/image.png" alt=""></p>
<p>작성 후 <code>source ~/.bashrc</code> 실행 한 다음 노드 정보 확인할 수 있는 <code>kgn</code> alias 실행</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/caa754b0-0f07-4569-b662-8f8aede7333c/image.png" alt=""></p>
<hr>
<h2 id="krew-설치">Krew 설치</h2>
<h3 id="1-설치">1) 설치</h3>
<pre><code>(
  set -x; cd &quot;$(mktemp -d)&quot; &amp;&amp;
  OS=&quot;$(uname | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)&quot; &amp;&amp;
  ARCH=&quot;$(uname -m | sed -e &#39;s/x86_64/amd64/&#39; -e &#39;s/\(arm\)\(64\)\?.*/\1\2/&#39; -e &#39;s/aarch64$/arm64/&#39;)&quot; &amp;&amp;
  KREW=&quot;krew-${OS}_${ARCH}&quot; &amp;&amp;
  curl -fsSLO &quot;https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz&quot; &amp;&amp;
  tar zxvf &quot;${KREW}.tar.gz&quot; &amp;&amp;
  ./&quot;${KREW}&quot; install krew
)</code></pre><p><img src="https://velog.velcdn.com/images/song-_-/post/4b5371a4-ceb3-4443-848a-a58254f7c3e7/image.png" alt=""></p>
<p><strong>네트워크 안될 경우</strong></p>
<p>/etc/resolv.conf 삭제 후 /run/systemd/resolve/resolv.conf 파일 ln -s 링크로 다시 심볼릭 링크 생성. 생성 후 파일 안에 원하는 DNS 서버 주소 입력.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/2c7cd060-c903-40d2-a5ed-72f2c09a61e9/image.png" alt=""></p>
<h3 id="2-파일-설정">2) 파일 설정</h3>
<p>~/.bashrc 파일 맨 아래 구문 추가</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/b889220a-1068-4d36-8a59-60bf4d55ca61/image.png" alt=""></p>
<p>추가 후 <code>source ~/.bashrc</code> </p>
<h3 id="3-krew-실행">3) krew 실행</h3>
<p><code>k krew</code> 실행 시 krew 설명이 출력되면 설치 성공.</p>
<p><img src="https://velog.velcdn.com/images/song-_-/post/87a8642e-32ad-4818-8c0e-0d2a28572f60/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>