WEB渗透测试中SQL注入那点事
发布日期:2024-05-19 浏览次数: 专利申请、商标注册、软件著作权、资质办理快速响应热线:4006-054-001 微信:15998557370
WEB集群智慧云安服渗透测试中SQL注入那点事 概述原理注入条件SQL注入一般步骤 1.注入点的种类解析 1.1 按注入点参数的类型分类 1.2 按照数据请求方式来分类 2.联合查询注入(union) 3.盲注 3.1 报错盲注 3.2 布尔盲注(基于逻辑判断) 3.3 延时盲注sleep(基于时间) 4.注入进阶 4.1 加解密注入 4.2 二次注入/二阶注入 4.3 DNSlog带外注入 4.4 堆叠注入 5.WAF绕过 5.1 WAF原理 5.2 正则表达式(regular expression) 5.3 WAF绕过方法总结 5.3 绕过思路分享 6.小结 概述 在学习SQL注入之前,我们应先了解什么是SQL? SQL一般是指结构化查询语言,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。那么问题来了,什么是SQL注入呢? 原理 SQL注入就是当开发人员对用户输入数据的合法性没有判断或过滤不严时,攻击者通过拼接恶意SQL语句诱使解释器在未经适当授权的情况下执行意外命令或访问数据。 简而言之:SQL注入的原理就是攻击者通过拼接恶意SQL语句,将其带入数据库进行查询,从而得到数据库一些敏感信息。 注入条件 SQL注入产生条件有三:(1)变量可控(2)变量未存在过滤(3)我们构造的SQL语句可带入数据库中查询。 当我们了解SQL注入产生的条件时,还有一个非常重要的点需要特别注意,就是应该了解那个参数存在注入点,如果注入点搞错了,你怎么进行构造语句也不起任何作用。例如,如果参数x存在注入点,下面哪个可以注入成功呢? (1)?x=1 & x=1 and 1=1 (2)?x=1 &y=1 and 1=1 通过例子我们可以发现例(1)可以注入成功,例(2)不可以,这是为什么?因为是参数X存在注入点,这时我们的注入语句就应该拼接到x后面,而不是像例(2)那样把语句拼接到Y后面,否则就像我前面说的,搞错了注入点,你怎么进行构造SQL语句网页也不起任何作用。 SQL注入一般步骤 1.注入点判断 2.注入点类型判断(有无回显) 3.信息猜解(库名-表名-列名-具体数据) 判断一个链接是否存在注入漏洞,可以通过对其传入的参数(但不仅仅只限于参数,还有cookie注入,HTTP头注入等) 进行构造,然后对服务器返回的内容进行判断来查看是否存在注入点。 注入点又分为有回显和无回显,有回显就是当我们输入恶意SQL语句时,页面会给我们一个反馈的信息,例如我们语句输入错误,后台就会把错误信息返回显示在网页上,而无回显就恰恰相反,当我们无论输入的SQL是正确或者错误,页面都不会发生改变。 下面我们就先介绍一下有回显的注入点判断: 1.注入点的种类解析 1.1 按注入点参数的类型分类 (1)数字型注入 当输入的参数x为整型的时候,通常sql语句是这样的 select * from users where id =x ,例如id=1这种类型,向数据库传入的是数字,参数不需要被引号括起来。 数字型注入判断方法一般较为简单,当我们在注入点参数后构造语句 and 1=1 页面显示正常 and 1=2页面显示错误的时候,那么这个页面就有可能存在数字型注入点。 and是与的逻辑,即两个条件为真时,页面才会返回正常,所以 当输入and 1=1时,后台会执行sql语句是 select * from users where id =x and 1=1;没有语法显示错误且逻辑判断为真,返回正常 当输入and 1=2时,后台会执行sql语句是 select * from users where id =1 and 1=2;没有语法错误且逻辑判断为假,返回错误 (2)字符型注入 当输入的参数x为整型的时候,通常sql语句是这样的 select * from users where id =‘x ',例如name=admin这种类型,像数据库传入的是字符串,参数需要被引号括起来。 字符型注入判断跟数字型注入逻辑差不多,只不过是在语句上需要添加一些符号,如单引号,双引号,括号等 当输入'and' 1'='1 时,后台会执行sql语句是 select * from users where id =’x' and '1‘=‘1’;没有语法显示错误且逻辑判断为真,返回正常 当输入‘and ’1’=‘2时,后台会执行sql语句是 select * from users where id =’1‘ and ’1‘=‘2’;没有语法错误且逻辑判断为假,返回错误 而字符型常见干扰符号有:双引号”,单引号',括号),综括号}等,具体是什么符号干扰实际案例中还需各位进行尝试。 1.2 按照数据请求方式来分类 (1)GET注入 HTTP请求方式为get,注入点一般在get传入的参数部分,例如?id=1,id便是一个注入点。 (2)POST注入 HTTP请求方式为post,注入点一般为提交的HTML表单, 即post传入的数据内容。 (3)Request注入 get,post,reques注入的判断方法其实就是通过在请求方法中提交不同SQL判断语句,看页面是否与原来一样,一样则不存在注入点,不一样则存在注入点,但是有一点值得注意,GET提交的数据会优先输出, Request请求方法可以包含get,post任意语句。 (4)HTTP头注入 HTTP的请求头存在注入点,例如XFF头,cookie,Host这些都是常见的注入点。 注入点判断方法:通过修改http数据包数据(构造恶意SQL语句)进行提交,页面是否显示我们提交的数据,显示则存在,反之不存在。 (5)Cookie注入 cookie注入其实跟上面3个差不多,通过在cookie中输入恶意SQL语句带入数据库查询,即可实现cookie注入。 2.联合查询注入(union) 联合查询注入一般配合 order by 函数进行信息猜解,当我们发现网站的注入点时且网站有错误回显的时候,那我们就可以使用 union 进行注入。其大致步骤为: 1.注入点判断(前面已经介绍过) 2.order by 列名猜解(ORDER BY 语句用于根据指定的列对结果集进行排序,当排序的那列数字超过了原有的列数就会报错,借助这个函数原理我们就可猜出数据库有多少列名) order by x //x为界面正确和错误的临界值,如 当我们输入SQL语句' order by 3 页面显示正常,order by 4 页面显示错误,那么x就为3,即数据库有3列。 下面通过SQLilbs靶场示例我们可以更清楚了解这一原理,前期我们判断出了注入点为字符型注入,那么我们就可以order by 列名查询,如我们通过 ' order by 3 --+ //--+是起到过滤后面内容的作用,有些数据库也可用#进行过滤掉后面的内容。 当我们输入SQL语句' order by 3 --+,发现页面显示正常 当我们输入’order by 4 --+,你会发现页面显示了错误的信息 那么我们就可以明白了,该数据库有3列数据。当我们得到这个信息后就可以下一步操作了。 3.union 查询 当我们用order by 函数猜解出数据库列名后,我们就可以使用 union函数进行注入了,SQL语法为 union select 1,2,3,4,....n --+ //因为我们通过order by 猜解出有X列,那我们就可以通过select 查询X列,通过页面报错回显位,再进行payload构造。我们还是接着以上靶场为例,因为我们知道了该数据库有3列数据,那我们就可以构造SQL语句 ‘union select 1,2,3--+ 通过上图我可以看到,页面显示了两个数字2,3这两个数字就是注入点的回显位置,我们通过在回显位置构造payload,得出想要信息。 4.报错显示位信息查询 union select 1,payload,3,...n --+ 通过构造payload得到数据库显示位,那么就可以获取我们想要的信息了,上面我们得到了显示位为2,3那我们只要在select 后面的2,3位置构造payload即可,例如我们想要获取数据库版本信息和数据库名那我们可以通过SQL语句 'union select 1,version(),database()--+ 进行注入查询 通过语句注入你就得到了数据库版本为5.1.73,数据库名为security,如果你还想获取其他信息,那么只需要修改显示位的payload即可。 但需要注意的是使用union进行联合查询时想要查询的数据回显,则需要第1个查询结果为空。即select 1 union select 2,1查询的结果为空时,数据库才会去查询2想要的信息。 这边整理了一些常见的数据信息收集如: 数据库版本:version() 数据库名字:database() 数据库用户:user() 操作系统:@@version_compile_os information_schema.schemata //所有数据库库名 information_schema.tables //数据库下面的所有表名 information_schema.columns //数据库某数据表下面的列名 schema_name //数据库名 table_name //表名 column_name //列名 以上都是一些常见的数据库信息收集,如果感兴趣网上还有许多方法,可以自己查找学习。 以上介绍的都是一些通过拼接SQL语句后,页面返回一些错误的信息,也就是回显,让我们发现注入漏洞,但随着安全防护的不断提高,许多网站都是没有回显的,就是说你输入的SQL语句带入数据库查询后,无论是正确还是错误的,它都不把信息回显到页面上,页面跟原来的一样没有改变。那么这种无回显的我们又该如何操作呢? 不要慌,无回显我们也是可以试一试,下面我们就来介绍如何通过无回显SQL注入,也就是俗称的盲注。 3.盲注 3.1 报错盲注 报错型注入:通过特殊函数错误使用并使其输出错误结果来获取信息。 常见3种报错盲注函数: floor,updatexml,extractvalue等 下面我们就先来介绍updatexml,extractvalue这两个函数 在mysql高版本(大于5.1版本)中添加了对XML文档进行查询和修改的函数:updatexml(),extractvalue()当这两个函数在执行时,如果出现xml文档路径错误就会产生报错 3.1.1 updatexml updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。 语法:updatexml(XML_document,XPath_string,new_value) updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)以上这些都是一些函数的具体介绍,那我们实际中怎么构造呢? 我们可以通过 :id=x' or updatexml(1,concat(0x7e,(payload)),0) # //or是或的意思一个成立就行,当然你也可以使用and没有什么影响,comcat是连接函数,将里面的字符串连接起来成为一个字符串。payload就是我们想要得到的信息,如果想得到用户名,那么payload就为user(); #前面讲过是过滤后面语句的。 那么这个函数如何报错注入呢,这个函数里面的关键就是0x7e,0x7e在ASCII码中 是:~;而通过updatexml我们可以知道当xpath_string格式出现错误,mysql则会爆出xpath语法错误,而0x7e并不属于xpath的语法格式,所以我们才可以通过这一特征得到报错想要的信息。 3.1.2 extractvalue 此函数从目标XML中返回包含所查询值的字符串 语法:extractvalue(XML_document,xpath_string) SQL语句:x' or extractvalue(1,concat(0x7e,payload))# extractvalue函数的使用跟上updatexml一样都是当xpath_string格式出现错误,mysql则会爆出xpath语法错误 而0x7e就是~不属于xpath语法格式,因此报出xpath语法错误。同时 ‘~‘可以换成’#’、’