CTF
[hkcert] Mystiz's Mini CTF (2) Write Up
Wermut
2025. 2. 27. 01:14
mass assignment 취약점
본 문제는 mass assignment 취약점이 존재하는 문제인데, 이 취약점은 공격자가 서버에서 할당한
클라이언트의 변수를 충분히 검증하지 못해 내부의 속성으로 변환하는 취약점으로,
// models.user.py
def marshal(self):
return {
'id': self.id,
'username': self.username,
'is_admin': self.is_admin,
'score': self.score
}
문제를 보면 is_admin 이란 변수로 사용자가 admin 권한을 갖고 있는지 검증하고 있다.
이때 버프스위트를 사용해 회원가입 시에 is_admin 속성을 추가해 1로 설정해 주면 서버는 이를 그대로 적용해
공격자가 admin 권한을 탈취하는 것이 가능하다.
// views/_init_.py
from flask import Blueprint, request, jsonify
from flask.views import MethodView
import collections
from app.views import pages
from app.views.api import users
from app.views.api import challenges
from app.views.api.admin import challenges as admin_challenges
from app.models.user import User
from app.models.challenge import Challenge
from app.models.attempt import Attempt
class GroupAPI(MethodView):
init_every_request = False
def __init__(self, model):
self.model = model
self.name_singular = self.model.__tablename__
self.name_plural = f'{self.model.__tablename__}s'
def get(self):
# the users are only able to list the entries related to them
items = self.model.query_view.all()
group = request.args.get('group')
if group is not None and not group.startswith('_') and group in dir(self.model):
grouped_items = collections.defaultdict(list)
for item in items:
id = str(item.__getattribute__(group))
grouped_items[id].append(item.marshal())
return jsonify({self.name_plural: grouped_items}), 200
return jsonify({self.name_plural: [item.marshal() for item in items]}), 200
def register_api(app, model, name):
group = GroupAPI.as_view(f'{name}_group', model)
app.add_url_rule(f'/api/{name}/', view_func=group)
def init_app(app):
# Views
app.register_blueprint(pages.route, url_prefix='/')
# API
app.register_blueprint(users.route, url_prefix='/api/users')
app.register_blueprint(challenges.route, url_prefix='/api/challenges')
app.register_blueprint(admin_challenges.route, url_prefix='/api/admin/challenges')
register_api(app, User, 'users')
register_api(app, Challenge, 'challenges')
register_api(app, Attempt, 'attempts')
admin 계정을 탈취한 직후 코드에 명시되어 있는 경로를 확인했을 때, 위 /views/_init_. py 파일에서
/api/admin/challenges로 접근하여 flag를 확인할 수 있다.