하하핫 가보자구
Error based sql injection이란 에러를 발생시켜서 데이터베이스 및 운영 체제의 정보를 획득하는 공격 기법으로, 데이터베이스가 반환하는 에러 메시지를 이용해 공격자가 데이터베이스 구조, 쿼리 결과 등을 알아내는 방법으로 에러 메시지를 자세히 반환하는 경우에 효과적이다.
소스코드나 보러가자..
CREATE DATABASE IF NOT EXISTS `users`;
GRANT ALL PRIVILEGES ON users.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';
USE `users`;
CREATE TABLE user(
idx int auto_increment primary key,
uid varchar(128) not null,
upw varchar(128) not null
);
INSERT INTO user(uid, upw) values('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
FLUSH PRIVILEGES;
이 SQL 스크립트는 사용자 관리 관련 데이터베이스와 테이블을 생성하고, 데이터베이스 사용자에게 권한을 부여하며, 몇 가지 예제 데이터를 삽입하는 과정입니다. 이를 분석해 보면 다음과 같습니다:
1. **데이터베이스 생성**:
```sql
CREATE DATABASE IF NOT EXISTS `users`;
```
- `users`라는 이름의 데이터베이스를 생성합니다. 데이터베이스가 이미 존재하는 경우에는 새로 생성하지 않습니다.
2. **사용자 권한 부여**:
```sql
GRANT ALL PRIVILEGES ON users.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';
```
- `'dbuser'`라는 이름의 사용자에게 `users` 데이터베이스에 대해 모든 권한을 부여합니다.
- 이 사용자는 `localhost`에서만 접속할 수 있고, 비밀번호는 `'dbpass'`로 설정됩니다.
3. **데이터베이스 선택**:
```sql
USE `users`;
```
- 이후에 실행될 모든 SQL 명령이 `users` 데이터베이스에서 실행되도록 설정합니다.
4. **테이블 생성**:
```sql
CREATE TABLE user(
idx int auto_increment primary key,
uid varchar(128) not null,
upw varchar(128) not null
);
```
- `user`라는 테이블을 생성합니다.
- 테이블에는 세 개의 컬럼이 있습니다:
- `idx`: 자동 증가하는 정수형(primary key)로 설정된 인덱스입니다.
- `uid`: 사용자 ID를 저장하는 128자 길이의 문자열입니다. `not null`로 설정되어 빈 값은 허용되지 않습니다.
- `upw`: 사용자 비밀번호를 저장하는 128자 길이의 문자열입니다. `not null`로 설정되어 빈 값은 허용되지 않습니다.
5. **데이터 삽입**:
```sql
INSERT INTO user(uid, upw) values('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
```
- `user` 테이블에 세 개의 사용자 계정을 삽입합니다:
- **admin** 사용자: 비밀번호는 `DH{**FLAG**}`로 설정되었습니다. 여기서 `DH{**FLAG**}`는 일반적인 문자열처럼 보이지만, 실제로는 시스템에서 **플래그(FLAG)**로 사용될 수 있는 값입니다.
- **guest** 사용자: 비밀번호는 `'guest'`입니다.
- **test** 사용자: 비밀번호는 `'test'`입니다.
6. **권한 초기화**:
```sql
FLUSH PRIVILEGES;
```
- 이 명령은 데이터베이스에 변경된 권한 정보를 즉시 적용하도록 합니다.
### 요약:
- 이 스크립트는 `users`라는 데이터베이스와 `user` 테이블을 생성한 후, 세 가지 사용자(관리자, 게스트, 테스트)를 삽입하는 과정입니다.
- 각 사용자의 ID와 비밀번호는 텍스트로 저장되며, 특히 **admin** 계정의 비밀번호는 시스템에서 **FLAG**로 사용될 가능성이 높습니다.
import os
from flask import Flask, request
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = os.environ.get('MYSQL_HOST', 'localhost')
app.config['MYSQL_USER'] = os.environ.get('MYSQL_USER', 'user')
app.config['MYSQL_PASSWORD'] = os.environ.get('MYSQL_PASSWORD', 'pass')
app.config['MYSQL_DB'] = os.environ.get('MYSQL_DB', 'users')
mysql = MySQL(app)
template ='''
<pre style="font-size:200%">SELECT * FROM user WHERE uid='{uid}';</pre><hr/>
<form>
<input tyupe='text' name='uid' placeholder='uid'>
<input type='submit' value='submit'>
</form>
'''
@app.route('/', methods=['POST', 'GET'])
def index():
uid = request.args.get('uid')
if uid:
try:
cur = mysql.connection.cursor()
cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
return template.format(uid=uid)
except Exception as e:
return str(e)
else:
return template
if __name__ == '__main__':
app.run(host='0.0.0.0')
이 Flask 애플리케이션과 이전에 제공한 SQL 스크립트를 비교하면서, 여기에 존재하는 **취약점**을 살펴보고 이를 어떻게 공격할 수 있는지 분석해보겠습니다.
### 주요 취약점: **SQL 인젝션(SQL Injection)**
이 애플리케이션에서 가장 큰 문제는 **SQL 인젝션**에 취약하다는 점입니다. 이 문제는 다음 부분에서 발생합니다:
```python
cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
```
여기서 사용자가 입력한 `uid` 값이 `cur.execute`에 **직접 삽입**됩니다. 만약 입력된 값이 SQL 문을 조작할 수 있도록 설계되면, 공격자가 의도하지 않은 방식으로 데이터를 읽거나 조작할 수 있습니다. 이 문제는 **SQL 인젝션**이라 불리며, 공격자는 임의의 SQL 명령어를 실행할 수 있게 됩니다.
#### 예시 취약점 분석
만약 `uid`로 아래와 같은 입력이 들어가면:
```
' OR '1'='1
```
그럼 `cur.execute` 구문은 다음과 같은 SQL문으로 변환됩니다:
```sql
SELECT * FROM user WHERE uid='' OR '1'='1';
```
이 구문은 항상 `True`이므로, 데이터베이스에 저장된 **모든 사용자 정보**가 반환됩니다. 특히, `admin` 계정의 플래그를 포함한 비밀번호가 노출될 수 있습니다.
### 공격 방법
1. **SQL 인젝션 공격 명령어**:
SQL 인젝션을 수행하기 위해, 아래와 같은 `uid` 값을 입력할 수 있습니다:
```
' OR '1'='1' --
```
이 입력은 다음과 같은 SQL문으로 변환됩니다:
```sql
SELECT * FROM user WHERE uid='' OR '1'='1' --';
```
여기서 `--`는 SQL에서 주석을 의미하므로, 뒤에 오는 코드는 무시됩니다. 이 명령어는 데이터베이스에서 모든 행을 반환하며, 이는 `admin` 계정도 포함됩니다.
2. **FLAG 찾는 방법**:
SQL 인젝션으로 `admin` 계정에 접근할 수 있으므로, 그 계정의 `upw` 필드에 저장된 플래그를 가져올 수 있습니다. 예를 들어:
- 공격자가 웹 브라우저에서 해당 웹 애플리케이션을 열고, `uid` 필드에 아래와 같은 값을 입력합니다:
```
' OR '1'='1' --
```
- 이 공격을 통해 `user` 테이블에 있는 모든 사용자의 데이터를 볼 수 있습니다. `admin` 계정의 `upw` 필드에 `DH{**FLAG**}`와 같은 플래그가 저장되어 있으므로, 이 정보를 확인할 수 있습니다.
### 요약
- 이 Flask 애플리케이션은 SQL 인젝션 공격에 취약합니다.
- 공격자는 `uid`에 `' OR '1'='1' --`와 같은 값을 입력하여 모든 사용자의 데이터를 얻을 수 있습니다.
- 이를 통해 `admin` 계정의 플래그를 찾을 수 있습니다.
**취약점을 공격하는 과정**:
1. `uid` 필드에 `' OR '1'='1' --`와 같은 값을 입력.
2. 반환된 데이터에서 `admin` 계정의 `upw` 값을 찾아서 **FLAG**를 확인.
이러한 SQL 인젝션을 방지하려면, **SQL 쿼리**를 작성할 때 **파라미터화된 쿼리**(Prepared Statements)를 사용해야 합니다.
완벽한 풀이글 블로그 글을 찾았다..
Mysql에서는 대표적으로 extractvalue()함수를 이용한다.
이 함수는 extractvalue(xml_frag, xpath_expr)형태로 이용되며 여기서 ‘xml_frag’는 xml 데이터 조각을 뜻하고, ‘xpath_expr’은 추출한 값을 지정하는 xpath 표현식을 뜻한다.
(xml은 eXtensible Markup Language의 줄임말로 데이터를 구조화하고 저장하는 데에 사용되는 마크업 언어이고, xpath는 xml 문서에서 특성 요소나 속성을 찾기 위한 경로 언어를 뜻한다.)
Error based sql 인젝션에서 xml 데이터의 자리에는 주로 1,2,3 과 같은 단순한 값으로 이용이 된다.
예로 ‘1’은 xml 데이터를 나타내지 않으므로 유효한 xml 데이터는 아니지만,
함수 자체가 인수인 ‘1’을 xml 데이터로 처리하려고 시도하기 때문에 에러가 발생하게 된다.
따라서 이 부분은 함수가 유효하지 않은 xml 데이터로 사용이 되어 에러를 발생시키는 역할을 한다.
xpath 자리에는 잘못된 xpath 표현식을 제공하면 오류가 발생하고,
이 오류 메시지를 통해 데이터베이스의 정보(테이블 이름, 칼럼 이름 등)를 유출할 수 있다.
출처 ㅣ https://velog.io/@son030331/%EC%9B%8C%EA%B2%8C%EC%9E%84-%EB%93%9C%EB%A6%BC%ED%95%B5-error-based-sql-injectionchallenges-412
concat 함수는 SQL의 함수로, 문자열을 합치는 데 사용이 되고 데이터베이스의 정보를 추출하기 위해서 사용된다. 에러 메시지를 통해서 데이터를 유출시키는 방법 중 하나로
extractvalue 함수와 함께 사용하여서 데이터베이스의 정보를 유출할 수 있다.
만약 select concat(‘Hello’, ‘ ‘, ‘World!’)라고 하면 이 쿼리는 “Hello World!”라는 문자열을 반환하게 된다.
컴퓨터의 ASCII 코드에서 백슬래시 문자는 숫자 92에 해당하고 0x는 숫자가 16진수로 표현되었음을 뜻하고,
5c는 16진수로 92를 나타낸다.따라서 0x5c는 16진수로 백슬래시 문자를 나타내는 것이다.
SQL 쿼리에서는 16진수 값을 문자열로 변환하여 사용할 수 있다.
(이 외에도 콜론을 나타내는 0x3a, 수직 탭을 나타내는 0x0b 등 많은 문자들이 더 있다.
따라서,SELECT concat(0x5c, ‘example’); 이라고 하면 \example 이라는 결과값을 반환하게 된다.
SELECT concat(0x5c, (SELECT database())); 라고 하면 database_name이 된다.
종합하면 SELECT extractvalue(1, concat(0x5c, (SELECT database())));
와 같은 형식의 쿼리를 이용하여 데이터베이스의 정보를 유출시킬 수 있다.
출처 ㅣ https://velog.io/@son030331/%EC%9B%8C%EA%B2%8C%EC%9E%84-%EB%93%9C%EB%A6%BC%ED%95%B5-error-based-sql-injectionchallenges-412
설명이 너무 아름다워서 줏어왔다...얼마나 완벽한 설명인가..!
injection 하러가자
DH{c3968c78840750168774ad951fc98bf788563c4d}
slqd 공부하면서 extractvalue() 함수는 한번도 본적없는데 slqp공부에서 나오나보다..신기하군!
https://hyotwo.tistory.com/103
에 파일에서 찾아도 없다.. 후후..해킹세계에서만 아는 명령어인가보다(!)
재밌군..
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[58] IT 비전공자 [dreamhack]command-injection-chatgpt문제 풀기 (3) | 2024.11.06 |
---|---|
[57] IT 비전공자 [dreamhack]oneshot문제 풀기 (2) | 2024.11.05 |
[55] IT 비전공자 [dreamhack]rev-basic-8문제 풀기 (4) | 2024.11.03 |
[54] IT 비전공자 [dreamhack]basic_exploitation_003문제 풀기 (0) | 2024.11.02 |
[53] IT 비전공자 [dreamhack]out_of_bound문제 풀기 (5) | 2024.11.01 |