
signup 페이지에서 회원가입을 할 수 있다. 이름, 나이, 학교 이름, 학교번호를 넣을 수 있다.
@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == 'POST':
name = request.form['name']
age = request.form['age']
school_type = request.form['school_type']
number = request.form['number']
if not is_alpha(name):
return redirect(url_for('login'))
if not is_alpha(age):
return redirect(url_for('login'))
if not is_alpha(school_type):
return redirect(url_for('login'))
if not is_alpha(number):
return redirect(url_for('login'))
cykor_mem = CYKOR()
input_list = {}
input_list[school_type] = number
input_list["name"] = name
input_list['age'] = age
input_list["making"] = {'name' : 'saneo'}
#input_list={'KOREA':123123,'name':jin,'age':19,'making':{'name':'saneo'}}
list2mem(input_list, cykor_mem)
user = User(name=name, age=age, school_type=school_type, number=number, output_str=str(vars(cykor_mem)))
db.session.add(user)
db.session.commit()
return redirect(url_for('login'))
return render_template('signup.html')
위는 회원가입 페이지에서 post 요청을 다루는 코드이다. input_list를 만드는데, {school_type: 학교 번호, name: 이름, age: 나이, making: {name: saneo}}로 list를 만든다.

burp suite으로 확인해보았다. name, age, school_type, number를 데이터로 보내고 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flag</title>
</head>
<body>
cykor{fake}
</body>
</html>
error.html이다. 딱 봐돠 error.html을 발생시키면 flag를 얻을 수 있을 것 같다.

아까 회원가입한 정보로 로그인해보았다. 위와 같이 이름, 나이, 학교이름, 학교번호를 보여주고, 추가된 리스트까지 보여주고 있다.
이 문제를 해결하기 위해서는 에러를 발생시켜야 한다.
@app.errorhandler(AttributeError)
def handle_attribute_error(e):
return render_template('error.html'), 500
위의 코드는 AttributeError가 발생했을 때 실행하는 코드이다. 따라서 우리는 AttributeError를 발생시켜야 한다.
def list2mem(src, dst):
for k, v in src.items():
print(k,v, vars(dst))
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
list2mem(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
list2mem(v, getattr(dst, k))
else:
setattr(dst, k, v)
위의 list2mem 함수에서 취약점을 확인할 수 있었다. 이 함수는 내가 입력한 것을 바탕으로 리스트를 만들어서 이를 메모리에 추가해주는 함수인 것 같다.
위의 블로그를 참고하여 hasattr, getattr 함수 등에 대해 공부하였다. hasattr 함수는 객체에 해당 키가 존재하는지, 그리고 getattr 함수는 객체에서 해당 키에 해당하는 value를 가져오는 함수이다.
위의 if hasattr(dst, ‘__getitem__’)을 통과하면 dst.get()함수를 실행시킨다. 그런데 dst에는 get 함수가 존재하지 않는다!! 따라서 여기서 AttributeError가 발생하고 , 그러면 flag를 확인할 수 있다.
그러면 어떻게 hasattr(dst, ‘__getitem__’)를 통과할 수 있을까? 이것을 통과하기 위해서는 dst에서 key값으로 ‘__getitem__’을 가지고 있어야 하는데 우리가 입력할 수 있는 이름, 나이, 학교번호는 모두 key가 아닌 value로 들어간다.
그런데 한 가지 다른 것이 있다. 바로 school_type이다! 실제 회원가입 페이지에서는 KOREA와 y만 고를 수 있게 되어있지만, 이것이 결국 list의 key로 들어가기에 burp suite를 사용하면 내가 원하는 값으로 바꿔서 넣을 수 있다.

따라서 위와 같이 school_type을 ‘__getitem__’으로 바꿔주었다. 이렇게 되면 list에 ‘__getitem__’:123이라는 key, value 쌍이 하나 생기고, if문을 통과하고 dst에 없는 get 함수를 실행시키려 해서 AttributeError를 발생시킬 수 있다. 보면 Response에서 error.html이 로딩되어 flag를 보이고 있는 것을 확인할 수 있다!
🚩 cykor{d0_y0u_kn0w_cla5s_p011ution??}