본문 바로가기
정보보안/Web Hacking

드림핵(DreamHack) - 커맨드 인젝션 -1, Command Injection-1(풀이)

by 우동이 2021. 7. 21.
300x250

해당 문제는 드림핵의 커맨드 인젝션-1번 문제입니다. command injection-1

dreamhack-command injection1

 

Command injection 말 그대로 명령어 삽입 공격인 것 같은데 이 문제에서 해당 기법을 처음 접해봤습니다.

SQL Injection 처럼 명령 구문을 삽입하는 공격이리라,, 하고 풀이해봤습니다.

 

/index

 

사이트는 /index, /ping 두 개의 URL이 존재합니다.

문제를 풀기 전 함께 제공된 app.py를 살펴보겠습니다.

 

 

#!/usr/bin/env python3
# app.py
import subprocess

from flask import Flask, request, render_template, redirect

from flag import FLAG

APP = Flask(__name__)


@APP.route('/')
def index():
    return render_template('index.html')


@APP.route('/ping', methods=['GET', 'POST'])
def ping():
    if request.method == 'POST':
        host = request.form.get('host')
        cmd = f'ping -c 3 "{host}"'
        try:
            output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
            return render_template('ping_result.html', data=output.decode('utf-8'))
        except subprocess.TimeoutExpired:
            return render_template('ping_result.html', data='Timeout !')
        except subprocess.CalledProcessError:
            return render_template('ping_result.html', data=f'an error occurred while executing the command. -> {cmd}')

    return render_template('ping.html')


if __name__ == '__main__':
    APP.run(host='0.0.0.0', port=8000)
cmd = f'ping -c 3 "{host}"'

 

서버는 flask로 짜였고 index페이지와 /ping 두 URL 중

/ping의 ping() 메서드에 cmd = f'ping -c 3 "{host}"' 항목이 눈에 띕니다.

{host} 부분에 command injection 취약점이 발생할 명령을 삽입해야 하는 듯합니다.

 

/ping - ping 테스트를 위한 호스트 입력 칸
8.8.8.8(구글DNS)

 

8.8.8.8로 ping 테스트를 수행합니다.

 

/ping - ping()

 

실제 ping 명령과 동일한 기능을 수행하고 이 결과를 출력하는 것을 알 수 있습니다.

ping -c 3 {host}
[입력값];ls

command injection을 발생시키는 방법은 주로 "메타 문자"를 통해 발생합니다.

Command Injection에 쓰이는 메타문자 모음

 

위 서버 코드를 살펴보면 ping 기능을 입력받는 부분이 존재하고

{host}라는 입력값을 받는 걸 알 수 있는데 메타 문자로 변조된 공격코드를 {host} 부분에 삽입하면

command injection의 취약점이 발생한다는 걸 알 수 있습니다.

 

 

저는 수많은 메타 문자 중 세미콜론(;)을 통한 변조 코드를 작성하여 삽입하겠습니다.

 

 

ls; cat test1.txt -> 명령어 구분자를 통한 명령어 동시 수행

ls;cat test1.txt

 

위 세미콜론(;)을 통해 앞의 명령어의 에러 유무와 관계없이 뒷 명령어를 실행하는 즉

구분 자이지만 무조건 실행된다는 것을 알 수 있습니다.

 

8.8.8.8;ls 어 안되네?
8.8.8.8" 이것도 안되네..
8.8.8.8";"ls

 

구분자를 통해 간단히 취약점이 발생할 거라 생각했지만 안되니 당황해서

다양한 변조 코드를 짜서 삽입해보았으나 전부 안됐습니다.

입력값에 대한 검증이 따로 있는지 살펴보지는 않고 바로 해서 그런가 싶어서

동봉된 다른 코드들을 또 뒤져봤습니다.

 

/*ping.html*/
{% extends "base.html" %}
{% block title %}ping{% endblock %}

{% block head %}
  {{ super() }}
{% endblock %}

{% block content %}
<h1>Let's ping your host</h1><br/>
<form method="POST">
  <div class="row">
    <div class="col-md-6 form-group">
      <label for="Host">Host</label>
      <input type="text" class="form-control" id="Host" placeholder="8.8.8.8" name="host" pattern="[A-Za-z0-9.]{5,20}" required>
    </div>
  </div>

  <button type="submit" class="btn btn-default">Ping!</button>
</form>
{% endblock %}

templates/ping.html 파일입니다.

코드를 살펴보시면 

pattern="[A-Za-z0-9.]{5,20}"

pattern에서 정규표현식을 통해 입력값 host에 대한 검증이 이루어지고 있었습니다.

그런데 사실 저는 이게 온전히 검증 코드인지 아닌지 살펴볼 코드에 대한 적절한 지식이 없는지라.. 확답은 할 수가 없습니다만

정규표현식이 괜히 사용되어 있지는 않을 것 같고 검증이건 아니건 제가 넣은 입력값에 대한 무언가의 조치가 취해져 있다고

생각할 뿐입니다.

그럼 일단 정규표현식에 대해 살짝 알아는 봐야겠습니다 궁금하니까요,,

 

 

RegExr: Learn, Build, & Test RegEx

RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).

regexr.com

[A-za-z0-9.]{5,20}
정규표현식 조건

위에 있던 정규표현식 값을 그대로 넣어 확인해봤습니다.

뜻을 대강 해석해보자면

알파벳 대문자, 소문자 전부 허용,

숫자는 0-9까지 그리고 점 문자 허용,

마지막의 글자 수의 길이 5-20까지 허용

대략 이렇습니다.

그렇다면 결론은 이겁니다. 위 정규표현식 조건에 해당하지 않는 세미콜론(:)과 같은

메타 문자는 사용이 안된다는 뜻이며 즉 필터링이 된다는 의미이죠

 

그러니 검증이 되는지 안되는지 확실히 몰랐지만 정규표현식 조건에 메타 문자가 들어있지 않다는 것만으로

원리에 대해 자세히 알고 있는 것은 아니지만 검증이 수행되고 있다는 점을 확인했습니다.

 

 

Kali Linux - FireFox - proxy

HTTP Request에서 입력값에 대한 검증 우회의 방법에는 여러 가지가 있습니다만

저는 버프 스위트 프로그램을 사용하는 걸 선호합니다.

웹 프락시를 설정해준 후 버프 스위트의 인터셉트를 통해 request를 잡아줍니다.

 

Burpsuite - intercept
Burpsuite - intercept

 

intercept를 통해 전송되고 있는 request를 가로챘습니다.

정상 전송되는 Host값을 변조(공격코드 삽입)하여 서버에 전달하겠습니다.

 

Burpsuite - HTTP Request 값 변조
command injection 코드 삽입

아까 맨 처음에 떠올렸던 메타 문자인 세미콜론을 삽입한 인젝션 코드를 작성해줍니다.

 

/ping - ls 명령어 실행됨

 

/ping에서 ls 명령어가 정상적으로 수행되었음을 알 수 있습니다.

그렇게 서버에 존재하는 파일의 리스트가 출력되었고

우리가 찾아야 할 flag.py파일이 존재한다는 걸 알게 되었고

해당 플래그 파일을 cat/more을 통해 읽어 들이면 끝입니다.

 

";"cat 안됨..

8.8.8.8";"cat flag.py

 

간단한 문제라 생각해서 바로 해봤으나 안되더라고요

아무래도 cat과 flag.py 사이의 공백 또한 정규표현식을 통한 필터링에 걸리나 싶어서

이 공백또한 메타 문자를 이용해 처리를 해줘야 하나 싶어서 "로 감싸 봤습니다.

 

 

8.8.8.8";"cat " "flag.py

8.8.8.8";"cat" "flag.py

 

이것저것 해보다가 때려 맞춘 거긴 합니다만

아직도 왜 저 공백까지 메타 문자로 처리를 해주어야 하는지에 대한 이해가 잘 되지는 않고 있습니다.

아까 살펴본 정규표현식 조건상에서는. 만 허용되는 것 같은데 어째서 "로 감싸는 건 가능한 걸까.... 싶은 그런

 

flag가 출력되었습니다.

하지만 때려 맞춘 보람은 있었나 봅니다.

cat 명령어는 온전히 제 기능을 수행해 flag값을 출력해냈습니다.

웹 해킹이 해킹 분야 중 가장 쉽게 접하는 분야라지만 그럼에도 쉽지는 않은듯합니다.

특히 이해가 되지 않는 부분에  대한 설명이나 답을 찾아내는 것 또한 어렵더라고요,,

 

아무튼 공부 열심히 합시다!

 

 

300x250

댓글