pikachu之XSS
XSS(跨站脚本)概述
Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型:
1.反射性XSS;
2.存储型XSS;
3.DOM型XSS;
XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。
XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
输出转义:根据输出点的位置对输出到前端的内容进行适当转义;
pikachu之XSS
反射型xss(get)
问我喜欢的NBA球星,那必然牢大,然后直接出来页面。
尝试随便输入123,我们发现输入的内容全都会出现在页面上。
想直接构造<script>alert(1)</script>,但是发现一个问题,这个框框太小了不够用...于是我们打开控制台,找到框框的位置,将框框的20改为100,如下:
这次就能输入了,弹框成功。
或者可以在url的参数进行操作,令参数=<script>alert(1)</script>,弹框即可
反射性xss(post)
点击提示直接登录,再次填入kobe。
这道题跟上题一样,填入paylaod直接弹框,不再多说。
存储型xss
依旧输入<script>alert(1)</script>
反复刷新页面,依然弹窗,说明存储型xss是永久型的。
DOM型xss
这道题我们随便输入一个,发现下面生成了超链接,但是是一个空超链接,无论我们输入什么都是这几个字。
接下来输入百度网址,点击超链接发现可以跳转百度。
那么猜测结构可能是<a href="我们的输入">what do you see?</a>
这样的话输入" >45查看有没有闭合成这样:
<a src="" >45">what do you see?</a>假如成功闭合,那么超链接的文本应该变成
45">what do you see?
可惜没有。
尝试将双引号换成单引号,成功。
输入' οnclick=alert(1)>45
按理来说结构变成这样,应该点击一下就会弹框。
<a src='' onlick=alert(1)>45'>what do you see?</a>
成功。
DOM型xss-x
这里随便输入,然后点击请说出你的伤心往事,然后下面又出现了一个超链接。
点击超链接,然后又出现了一个超链接,并且url参数位置出现了一个#符号。
试着将输入改为http://www.baidu.com,然后点击请输入你的伤心往事,发现url参数增加了我们输入的链接。
点击下面超链接,然后点击出现的另外一个就让往事都随风,都随风吧超链接,成功跳转百度。
构造paylaod
' οnclick=alert(1)>
最终点击就让往事都随风,都随风吧成功弹窗。
源代码如下,这里其实就是我们输入' οnclick=alert(1)>内容会出现在url参数位置,即text=' οnclick=alert(1)>#然后点击请说出你的伤心往事,然后就会执行domxss()函数,这个函数中的
var str =window.location.search
就是首先将url的参数从?到最后(或者#,但是不返回#)赋给str,也就是str=?text=' οnclick=alert(1)>,
然后这里var txss = decodeURIComponent(str.split("text=")[1]);,就是将str的内容按照text=进行分隔,然后存入数组。
如:[ "?", "' οnclick=alert(1)>" ],然后提取[1]位置也就是' οnclick=alert(1)>,并且赋值给txss,使用decodeURIComponent()对经过URL编码的字符串进行解码。
然后将txss的所有+号换成空格,随后赋值给xss。
然后是最关键的
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>"; |
它会将"<a href='"+xss+"'>就让往事都随风,都随风吧</a>";赋值给我们的名为dom属性的内容,而xss就是' οnclick=alert(1)>,所以就是将
"<a href='' οnclick=alert(1)>'>就让往事都随风,都随风吧</a>";赋值给dom,而dom就是一个显示内容的地方,也就是显示出来'>就让往事都随风,都随风吧这个链接,点击就会弹窗。
window.location.search
:这是浏览器提供的一个属性,它返回当前页面URL中从问号?
开始到末尾(或到#
锚点,不返回最后的#)的部分,也就是查询字符串(Query String)。示例:如果当前页面的URL是
https://example.com/vulnerable-page?text=<script>alert('xss')</script>&other=123
,那么window.location.search
的值就是"?text=<script>alert('xss')</script>&other=123"
。
document.getElementById("dom").innerHTML
document
:代表整个HTML网页文档。.getElementById("dom")
:获取元素。这是一个方法,用于在document
中查找一个id
属性为"dom"
的HTML元素。.innerHTML
:获取或设置元素的HTML内容。这个属性代表该元素内部的所有HTML代码。
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
在页面上找到一个ID为
dom
的元素,然后把它里面的所有内容替换成一个新的超链接。这个新链接的地址(href
)来自于变量xss
的值,链接显示的文本是“就让往事都随风,都随风吧”。
xss之盲打
这道题两个框都输入弹框js脚本,发现页面底下就出现了谢谢参与。。。没什么返回
点击提示,进入后台界面,然后登录管理员账号,登录后台的时候弹框了。这种就是xss盲打,攻击者无法看到攻击是否成功,当管理员访问后台的时候就会执行输入的攻击脚本。
xss之过滤
思路一
首先输入<script>alert(1)</script>,发现返回>。
任意输入几个字符,发现会原样返回,那么肯定我们输入的payload某被过滤了。
输入<sad>试一下,发现被过滤。
输入<b>abc</b>,发现<b>起作用了,abc进行了加粗,那么到这里其实可以猜测出系统可能使用了白名单,经过测试,<s>,<img src="">,<a href=""></a>也可以存活。
既然<img src="">可以存活,那么我们可以构造一个payload试一试
payload:<img src="1" οnerrοr="alert(1)"> ##因为图片的地址不正确导致报错从而导致onerror事件触发,其中onerror其实也可以替代成onclick事件,通过点击图片触发弹框事件。
其实<a>超链接标签也存活,那么也可以想到一个思路,构造payload
payload:<a href="#" οnclick=alert(1)>链接</a>
其中#是一个占位符,它的作用有:
1.让这个 <a>
标签保持一个合法链接的样式和行为(鼠标变成小手,有链接颜色),但阻止它进行真正的页面跳转。
2.当用户点击这个链接时,浏览器会将页面滚动到顶部(因为 #
代表页面顶部锚点)
可以使用<s>标签,payload:
<s οnclick=alert(1)>123 ##点击划线123即可触发。
思路二
我们输入"<>'on/`() script img href src查看一下回显,发现回显这样。
然后一个一个的进行测试,输入",测试,输入<>,测试...最终发现,如果单个输入的话那么全部都可以输出,这里就要大胆猜测一下了,为什么全部输入的时候script后面的保存完好呢?当然肯定不是单独过滤了script,因为直接输入script的话可以输出。反正肯定跟script有关。
尝试输入"script,'script,<script,>script,()script,/script...
接下来发现,除了<script以外,所有的组合全部都没有被过滤。
尝试输入:<55bf58script,在<和script之间混合数据,最后发现无论混合多少数据或者不加入数据,都会被过滤,那么大胆猜测过滤了<.*script。
可以考虑大小写绕过
payload:
<sCript>alert(1)</sCript>
<sCript>prompt(/xss/)</sCript> <sCript>prompt(`xss`)</sCript> <sCript>prompt('xss')</sCript>
<sCript>confirm(1)</sCript>
这里既然不能使用script,就开始考虑别的如<s>,<img>标签,这里不在赘述。
xss之htmlspecialchars
思路一
输入<script>alert(1)</script>,发现竟然把我记录了!当看到这种超链接那么背后肯定是有<a>标签的。
查看页面源代码,发现<>都被编码了,因此这关想闭合标签是不行了。但是发现单引号没有被html编码,所有可以考虑闭合单引号。
payload:
#' οnclick='confirm(/xss/)'或者#' οnclick='confirm(/xss/)闭合单引号。
思路二
可以之间修改前端代码尝试,然后点击超链接发现弹框。
htmlspecialchars()的作用就是把预定义的字符转换为了HTML实体。预定义的字符如下:
& 成为 &
" 成为 "
' 成为 '或'
< 成为 <
> 成为 >
htmlspecialchars()函数默认是不对单引号进行转义的,要想连单引号一起转义,需要给函数传入参数ENT_QUOTES,所以一般情况下如果遇到htmlspecialchars()函数的话,考虑一下单引号的闭合从而进行攻击。
ENT_COMPAT:默认编码,但是编码双引号不编码单引号
ENT_QUOTES:编码双引号和单引号
ENT_NOQUOTES:不编码任何引号
xss之href输出
思路一
首先输入百度网址,看一下怎么个事,然后点击下面超链接跳转到了百度页面,这道题一想就可以知道在<a>标签上面做手脚。
检查代码,然后在这里发现了我们输入的网址。
更改为这样
<a href="#" οnclick="confirm(`xss`)">...
点击超链接发现弹框。
思路二
同样也可以在输入框构造,但是经过我的测试<,>,',"都被htmlspecialchars()函数编码了,那么想要通过闭合的方法好像行不通了。
这里可以利用JavaScript协议。
payload:
javascript:alert(document.cookie)
javascript:prompt(document.cookie)
javascript:confirm(document.cookie)
输入后点击超链接发现提取了我的cookie。
解析:
javascript: 这是一个伪协议,表示接下来的内容是 JavaScript 代码,可以在当前页面的上下文中执行。
document.cookie: 这是一个 JavaScript 表达式,用于获取当前页面的 Cookie 值。Cookie 是一种用于在客户端和服务器之间存储数据的机制,它可以用于标识和跟踪用户会话状态。xss之js输出
xss之js输出
输入<script>alert(1)</script>,页面没变化,但是查看页面源代码我们发现了下面的一段javascript的if语句,其中ms的内容就是我们输入的内容。
这里尝试闭合,构造:';alert(1);//
完整闭合如下
通过//将';进行注释
如果不注释';的话,那么语句是$ms='';alert(1);';,在红色部分语句可能会发生错误。
$ms='';alert(1);//';
因为alert(1)本身就在javascript脚本中,所以会直接执行。