SWLUG/웹 해킹

[Dreamhack/드림핵] baby-linux

gapsoo 2023. 11. 16. 20:37

 

https://dreamhack.io/wargame/challenges/837

 

baby-linux

Description 리눅스 명령어를 실행하는 웹 서비스가 작동하고 있습니다. 해당 웹 서비스의 코드가 첨부파일로 주어집니다. flag.txt 파일을 찾아 출력하여 플래그를 획득하세요! 플래그 형식은 DH{...}

dreamhack.io

 


[1] 문제 분석

 

# 웹 페이지 분석

 

 

 

문제의 이름은 'Baby linux' 이고,

이름처럼 리눅스 명령어 'echo$( )' 괄호 안에 무언가를 입력하고 제출할 수 있는 구조로 되어 있다.

 

 

 

<html>
<head>
  <link rel="stylesheet" href="/static/css/bootstrap.min.css">
  <link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
  <link rel="stylesheet" href="/static/css/non-responsive.css">
</head>

<body class="container">
  <form method="POST">
    <div class="row">
      <div class="col-md-6 form-group">
        <h1>Baby Linux</h1><br/>
        <div class="input_box">
          <p class="input_txt">echo $(<input type="text" name="user_input" class="input_in_txt" required>)</p>
        </div>
      </div>
    </div>
  
    <button type="submit" class="btn btn-default">Submit</button>
  </form><br/><br/>
  <h2>Result</h2>
  <pre>
</pre>


  <script src="/static/js/jquery.min.js"></script>
  <script src="/static/js/bootstrap.min.js"></script> 
</body>
</html>

 

 

문제 화면의 소스 코드이다.

POST 방식으로 폼이 구성되어 있고, echo $() 안에 입력한 값은 "user_input" 이라는 파라미터로 저장되어 제출되는 것 같다.

 

더 이상 알아낼 수 있는 것이 없어서 다운로드한 문제 파일을 살펴보았다.

 

 

# 다운로드한 문제 파일 분석

  

⚙️ app.py

#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template

APP = Flask(__name__)

@APP.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        user_input = request.form.get('user_input')
        cmd = f'echo $({user_input})'
        if 'flag' in cmd:
            return render_template('index.html', result='No!')

        try:
            output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
            return render_template('index.html', result=output.decode('utf-8'))
        except subprocess.TimeoutExpired:
            return render_template('index.html', result='Timeout')
        except subprocess.CalledProcessError:
            return render_template('index.html', result='Error')

    return render_template('index.html')

if __name__ == '__main__':
    APP.run(host='0.0.0.0', port=8000)

 

 

내가 해석한 바로는

 

웹에서 받아온 'user_input'의 내용을 cmd에 넣는 것 같았다.

그리고 cmd에 'flag'라는 문자열이 있다면 'No!'라는 결과를 반환하는 것 같았다.

 

그러니까 조건은  'flag'라는 문자열이 cmd 창에 들어가면 안 되는 것이다.

 

 

 

이 부분의 형식을 참고해서, 폼을 제출하는 칸에 ")'&&f'echo $(ls"를 입력해보았다.

입력한 값을 통해 cmd = f'echo $()'&&f'echo $(ls)' 가 전달되는 것이다.

('ls'는 현재 내가 있는 디렉터리 안에 존재하는 모든 디렉터리와 파일들의 목록을 출력하는 명령어이다.)

 

 

현재 내가 있는 디렉터리 안의 파일과 디렉터리 목록을 출력하는 것을 성공했다!

 

'hint.txt' 파일이 의심스러우니 'cat' 명령어를 통해 그 내용을 보도록 하겠다.

.

.

.

)'&&f'echo $(cat hint.txt  을 입력해서

 cmd = f'echo $()'&&f'echo $(cat hint.txt)' 이 전달되도록 했다.

 

 

그랬더니 ./dream/hack/hello 안에 Flag가 있다는 내용의 문구가 출력되었다.

.

.

.

 

./dream/hack/hello 안에 어떤 파일이나 디렉토리가 있는지 확인하고 싶었다.

 

)'&&f'echo $(ls ./dream/hack/hello 을 입력해서

cmd = f'echo $()'&&f'echo $(ls ./dream/hack/hello)' 이 전달되도록 했다.

 

 

그랬더니 ./dream/hack/hello 안에 내가 찾던 flag.txt가 있다는 문구가 출력되었다.

.

.

.

 

이제 flag.txt의 내용을 열어봐야 하는데, 여기서 'flag'라는 문자열이 cmd에 있으면 안 된다는 것이 문제였다.

 

그래서 )'&&f'echo $(cat ./dream/hack/hello/*.txt 을 사용하여 '.txt'로 끝나는 모든 파일의 내용을 출력하는 명령어를 사용하였다.

 

 

 

문제 풀이 완료~~