기본적으로 소스코드를 제공해준다.


  1. """
  2.     Web App with file based ACL.
  3. """
  4.  
  5. import os
  6. import struct
  7.  
  8. from flask import Flask, request, render_template, abort, flash, redirect, url_for
  9.  
  10. """
  11.     Flask Config
  12. """
  13. app = Flask(__name__)
  14. app = Flask(__name__)
  15. app.config['DEBUG'] = False
  16. app.secret_key = ""
  17.  
  18. FLAG = '??'
  19.  
  20. class ACL(object):
  21.     """
  22.     Intent:
  23.         ACL for the Application
  24.  
  25.     Responsibilities:
  26.         - Add New Records to ACL
  27.         - Verify existing records in ACL
  28.  
  29.     Data Structures
  30.         - record
  31.           {
  32.               'username': <str>username[100],
  33.               'password': <str>password[100],
  34.               'admin': <str:`true/false`>admin
  35.           }
  36.     """
  37.  
  38.     DEFAULT_ACL_FILE = 'acl.data'
  39.  
  40.     def __init__(self, *args, **kwargs):
  41.         """
  42.         ACL(, [file_name, ])
  43.         :param str file_name kwarg
  44.         """
  45.         self.acl_file = kwargs.get('acl_file', self.DEFAULT_ACL_FILE)
  46.         self.acl_lines = self._read_acl_file()
  47.  
  48.     """
  49.         Writing Methods
  50.     """
  51.     @staticmethod
  52.     def _pack_data(data_dict):
  53.         """
  54.             Pack data with data_structure.
  55.         """
  56.         return '{}:{}:{}'.format(
  57.                                     data_dict['username'],
  58.                                     data_dict['password'],
  59.                                     data_dict['admin']
  60.                                 )
  61.  
  62.     @staticmethod
  63.     def _append_data(filename, data):
  64.         """
  65.             write `data` to filename as binary data.
  66.         """
  67.         with open(filename, 'a') as f:
  68.             f.write(data)
  69.             f.write('\n') # New Line Delimiter
  70.  
  71.     def _append_record(self, data_dict, *args, **kwargs):
  72.         """
  73.             Pack data and append to file.
  74.         """
  75.         bin_data = self._pack_data(data_dict)
  76.  
  77.         self._append_data(self.acl_file, bin_data)
  78.  
  79.     def add_record(self, username, password, admin, *args, **kwargs):
  80.         """
  81.             Add record to ACL.
  82.             - Client Facing
  83.         """
  84.         record = {
  85.             'username': username,
  86.             'password': password,
  87.             'admin': admin
  88.         }
  89.  
  90.         self._append_record(data_dict=record)
  91.  
  92.         return record
  93.  
  94.     def _read_acl_file(self):
  95.         """
  96.             Read all the lines in `self.acl_file`
  97.         """
  98.         if not os.path.exists(self.acl_file):
  99.             return None
  100.  
  101.         with open(self.acl_file, 'r') as f:
  102.             lines = f.readlines()
  103.  
  104.         return lines
  105.  
  106.  
  107.     def _unpack_data(self, buffer):
  108.         """
  109.             Unpack the buffer and extract contents.
  110.         """
  111.         unpacked_data = buffer.strip()
  112.         unpacked_data = unpacked_data.split(':')
  113.  
  114.         record = {
  115.             'username': unpacked_data[0],
  116.             'password': unpacked_data[1],
  117.             'admin': unpacked_data[2],
  118.         }
  119.         return record
  120.  
  121.  
  122.     def verify(self, username, password):
  123.         """
  124.             Verify if username and password exist in ACL.
  125.             - Client Facing
  126.         """
  127.         for line in self.acl_lines:
  128.             try:
  129.                 data = self._unpack_data(line)
  130.             except:
  131.                 continue
  132.  
  133.             if username == data['username'] and password == data['password']:
  134.                 return True, data
  135.  
  136.         return False
  137.  
  138.  
  139. acl = ACL()
  140.  
  141. @app.route('/', methods=['GET', 'POST'])
  142. def index():
  143.     if request.method == 'GET':
  144.         return render_template('index.html', admin=False, flag=FLAG)
  145.     elif request.method == 'POST':
  146.         try:
  147.             username = request.form.get('username')
  148.             password = request.form.get('password')
  149.             is_user, record = acl.verify(username, password)
  150.             print(is_user)
  151.             if is_user:
  152.                 admin = True if record['admin'] == 'true' else False
  153.             else:
  154.                 raise Exception()
  155.             return render_template('index.html', admin=admin, flag=FLAG, record=record)
  156.         except:
  157.             return redirect(url_for('index'))
  158.  
  159. @app.route('/register', methods=['GET', 'POST'])
  160. def register():
  161.     if request.method == 'GET':
  162.         return render_template('register.html')
  163.     elif request.method == 'POST':
  164.         username = request.form.get('username')
  165.         password = request.form.get('password')
  166.         acl.add_record(username, password, 'false')
  167.  
  168.         return redirect(url_for('index'))
  169.  
  170. if __name__ == '__main__':
  171.     app.run(port=5000, debug=True)



_unpack_data 함수 내에서 데이터를 언패킹하는 과정에서 취약점이 터진다. 간단히 : 문자를 기분으로 split하기 때문에 회원가입 시 패스워드를 youngin:true 형태로 가입해 주면 된다.


그러면 기본적으로 youngin:youngin:false와 같은 구조가 youngin:youngin:true:false가 된다.


위와 같은 형태로 가입 후 id:youngin,pw:youngin 으로 로그인 해주면 되는데 이때 회원가입시 요청한 데이터가 들어가 있는 self.acl_lines 요 값이 로컬에서 테스트해보니 항상 일정하지가 않아서 내가 삽입한 데이터가 존재하지 않는 경우가 있었다.. 그래서 위와 같은 로그인을 여러번 반복해서 해주니 플래그가 나왔다.



Flag = evlz{T#3_W34K_$N4K3}ctf










'CTF > Writeup' 카테고리의 다른 글

Trust CTF 2019 Web Writeup  (0) 2019.02.16
Evlz CTF 2019 FindMe  (0) 2019.02.06
NCSC CTF 2019 Web Wrietup  (0) 2019.02.04
Codegate CTF 2019 Preliminary Rich Project  (0) 2019.01.27
INSOMNIHACK CTF TEASER 2019 Phuck2 :(  (0) 2019.01.22
블로그 이미지

JeonYoungSin

메모 기록용 공간

,