MENU

SQL注入

什么是SQL注入

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体的我们举个例子来说。

$id = $_GET['id'];
$sql = "select * from sqli where id = {$id}";
echo $sql.'<br/>';
$rs = mysqli_fetch_array(mysqli_query($conn, $sql));
echo $rs['username'];

这是我们的后台语句 为了能清楚的呈现注入语句 我这里输出了执行的sql语句
sqli_test1
我们可以看到id是可以控制的 那么我们现在构造一个恶意内容
sqli_test2
在这里 我输入了and 1=2 union select 1,2,3,4
我们可以看到 and 1=2 会使前面的sql语句失效 然后 union 执行接下来的语句
本来应该输出 admin 在输入构造的语句后就变成了 2
在这里我们不只可以构造 select 1,2,3,4 如果是一些恶意语句就会使数据库中的信息暴露

SQL注入的具体流程

在这里我就用上面给出的代码来进行演示
首先我们先来看下数据库
sqli_liucheng
上面的代码 需要利用 union 来进行注入 而 union 需要前后两个语句的字段数相同

得到字段数

所以 首先我们需要知道字段数
这里会用到 order by

ORDER BY 语句用于根据指定的列对结果集进行排序
ORDER BY 语句默认按照升序对记录进行排序

order by 后可以跟数字 代表第几个字段 当字段不存在时会报错 我们可以利用这一点来得知字段数
sqli_orderby1
sqli_orderby2
我们可以看到4的时候 可以正确显示admin 而5的时候不行了 所以存在4个字段

得到具体的注入点

看一下源代码 我们可以知道 最后只会输出 键名为 username 的键值
那么我们需要将得到的结果放在和 username 同样的字段下
具体的利用就是我刚才演示的样子
and 1=2 无效之前的sql语句 再利用 union select 1,2,3,4 获得 username 字段所在的位置
这里我们可以看到输出了 2 也就是代表 username 字段在第二个位置
我们看数据库 也确实如此

获取数据库名

sql语句中 有一个函数 database() 可以显示当前的数据库名
那么怎么利用呢
sqli_database
思路和获取具体的注入点一样 只不过是把 2 换成了 database()
结果我们也可以看到 sqli

获取表名

获取表名这里 我们需要用到sql数据库中一个特殊的东西 information_schema
information_schema这张数据表保存了MySQL服务器所有数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。再简单点,这台MySQL服务器上,到底有哪些数据库、各个数据库有哪些表,每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema表里面。
下面对一些重要的数据字典表做一些说明:

SCHEMATA表:提供了关于数据库的信息。
TABLES表:给出了关于数据库中的表的信息。
COLUMNS表:给出了表中的列信息。
STATISTICS表:给出了关于表索引的信息。
USER_PRIVILEGES表:给出了关于全程权限的信息。该信息源自mysql.user授权表。
SCHEMA_PRIVILEGES表:给出了关于方案(数据库)权限的信息。该信息来自mysql.db授权表。
TABLE_PRIVILEGES表:给出了关于表权限的信息。该信息源自mysql.tables_priv授权表。
COLUMN_PRIVILEGES表:给出了关于列权限的信息。该信息源自mysql.columns_priv授权表。
CHARACTER_SETS表:提供了关于可用字符集的信息。
COLLATIONS表:提供了关于各字符集的对照信息。
COLLATION_CHARACTER_SET_APPLICABILITY表:指明了可用于校对的字符集。
TABLE_CONSTRAINTS表:描述了存在约束的表。
KEY_COLUMN_USAGE表:描述了具有约束的键列。
ROUTINES表:提供了关于存储子程序(存储程序和函数)的信息。此时,ROUTINES表不包含自定义函数(UDF)。
VIEWS表:给出了关于数据库中的视图的信息。
TRIGGERS表:提供了关于触发程序的信息。

在sql注入中 我们会经常用到 TABLES 表和 COLUMNS
sqli_tables
这里还利用了子查询 这个以后再说
group_concat() 函数 可以将所有的结果合并成一个 我们可以从下面的获取字段名中看到效果
然后我们就得到了表名

获取字段名

同样利用 COLUMNS 表 通过group_concat() 函数将所有结果合并
sqli_columns

获取具体数据

都知道表名 字段名了 就可以简单粗暴了
sqli_rs
至此注入完成

后记

这次只是我自己对于sql注入的简单的解说 当然sql注入不只这些
如果可以的话 我以后还会继续总结
在实战中我们面对的 就不再是这么简单的后台了
所以我之后也会发表 我自己对与sql注入技巧的总结
总之 在安全这条路上继续坚持下去吧

Tags: CTF, WEB, SQLI
Archives QR Code
QR Code for this page
Tipping QR Code