본문 바로가기

드림핵

[드림핵 워게임] simple-sqli

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

위의 문제를 다음과 같은 과정으로 풀어보았다.

 

 

1. 총 2개의 엔드포인트를 볼 수 있다.

 

(1) 인덱스 페이지 ( / )

@app.route('/')
def index():
    return render_template('index.html')

index.html을 렌더링 하고 있다. index 페이지에 접속해보면 메뉴바에 Home, About, Contact, Login 메뉴가 있는 것을 볼 수 있는데, 이 중에서 주목할 만한 페이지는 Login 페이지이다.

 

(2) login 페이지 ( /login )

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userid = request.form.get('userid')
        userpassword = request.form.get('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}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

GET, POST 메소드가 있는데, GET으로 요청한 경우 로그인폼이 있는 페이지를 렌더링하고, 폼의 userid, password에 값을 입력하여 로그인 버튼을 클릭하면 POST 방식으로 요청하게 된다. 이때 query_db() 함수에서 전달받은 값, userid, userpassword를 담아 select 쿼리문을 동적으로 생성하여 실행하는 것을 확인할 수 있다. 이렇게 동적으로 생성한 쿼리를 Raw Query라고 하는데, Raw Query는 sql injection 공격에 대해 취약하다.

 

 

 

2. 취약점이 있는 코드 확인하기

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
    db.row_factory = sqlite3.Row
    return db

def query_db(query, one=True):
    cur = get_db().execute(query)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

위의 두 함수가 Raw Query를 그대로 실행하고 있으므로 sql injection 공격이 가능하다.

 

 

 

3. login 페이지에 익스플로잇 코드를 입력하여 로그인하면 flag를 얻을 수 있다.

/login 에서 query_db()함수에 'select * from users where userid="{userid}" and userpassword="{userpassword}"' 를 전달하여 해당 쿼리문을 실행하고 있다. 이때 {userid}에 적당한 익스플로잇 코드를 입력하여 sql injection 공격을 할 수 있다.

admin"--

위의 코드를 userid에 전달하면 -- 뒤로는 주석으로 처리되어 password에 어떤 값을 넣는지에 상관없이 userid가 admin인 행을 DB에서 조회해올 수 있다. 즉 DBMS에서 이 쿼리를 다음과 같이 처리하는 것이다.

select * from users where userid="admin"--"and userpassword="아무거나" <--주석 처리됨

 

'드림핵' 카테고리의 다른 글

[드림핵 워게임] command injection-1  (1) 2022.10.08
[드림핵 워게임] Mango  (0) 2022.10.01
[드림핵 워게임] csrf-2  (1) 2022.09.24
[드림핵 워게임] csrf-1  (1) 2022.09.23
[드림핵 워게임] xss-2  (1) 2022.09.21