
2.3.3 存储型XSS
存储型XSS与反射型XSS核心原理一致,都是将JavaScript通过程序输出到HTML页面中并交由浏览器引擎解析。相比于反射型XSS,存储型XSS危害更大。反射型XSS需构造恶意URL来诱导受害者点击,而存储型XSS由于有效载荷直接被写入了服务器中,且不需要将有效载荷输入到URL中,往往可以伪装成正常页面,迷惑性更强。因此存储型XSS漏洞对于普通用户而言很难及时被发现。
若过滤不严,存储型XSS极易造成网络蠕虫,导致大量Cookie被窃取。当然存储型XSS也可用作权限维持来窃取网站后台的登录信息,存储型XSS攻击流程如图2-53所示。

图2-53 存储型XSS攻击流程
存储型XSS可以笼统地看作程序先从数据库中读取数据,并将其直接渲染为HTML,此时浏览器引擎便会解析数据中存在的恶意JavaScript脚本。网站程序中常见的攻击点一般有:文章编辑、用户留言、个性签名等。
接下来,我们依旧使用一个开源代码XSS Demo进行审计演示。首先通过其正常的页面功能发现存在路由/show会打印出用户的留言,根据web.xml可以找到其对应的类,如图2-54所示。

图2-54 存在路由/show会打印出用户的留言
根据xml中的调用可以跟踪到调用类,在类中可以发现,程序首先对“MessageInfo ServiceImpl”类进行了实例化操作,随后通过setAttribute方法对msg的值进行存储,并通过“getRequestDispatcher”将其重定向至“message.jsp”文件进行输出,如图2-55所示。

图2-55 通过setAttribute方法对msg的值进行存储
追踪msg的值,其来源于“msginfo.MessageInfoShowService()”,跟进该方法可以发现程序最终调用了MessageInfoShowDao方法,如图2-56所示。

图2-56 调用MessageInfoShowDao方法
跟进MessageInfoShowDao方法,可发现其对数据库进行了连接操作,并从message数据表中查询出全部数据,赋值给对应的name、mail、message并返回给servlet层,如图2-57所示。

图2-57 MessageInfoShowDao对数据库进行了连接操作
回到message.jsp,可以看到message.jsp文件从list中取出之前存入的name、mail及messgae,并渲染HTML输出至浏览器,如图2-58所示。
到此漏洞的整个执行流程我们已分析完成,接下来便是找到对应的入口进行触发,而触发该漏洞一个最大的问题是:数据来源于数据库,我们需要对其进行控制。也就是说,想要触发该XSS漏洞,首先得将包含XSS有效载荷的数据插入数据库中。通过搜索对应的关键字可以在MessageInfoStoreDao中找到数据对应的入库操作,如图2-59所示。

图2-58 message.jsp文件从list中取出数据

图2-59 在MessageInfoStoreDao中找到数据对应的入库操作
那么接下来的问题便回到了MessageInfoStoreDao在哪里被调用,通过调用栈可以发现MessageInfoStoreService方法中调用了MessageInfoStoreDao,如图2-60所示。

图2-60 MessageInfoStoreService方法的主要代码
通过调用栈继续跟进MessageInfoStoreService,可以发现在StoreXSS中对其进行了调用,并且MessageInfoStoreService中的三个参数全部直接来源于GET方法,如图2-61所示。

图2-61 跟进MessageInfoStoreService发现在StoreXSS中对其进行了调用
因为程序没有对输入进行任何校验,所以只需找到添加数据的路由后插入对应的有效载荷,如图2-62所示。

图2-62 插入对应的有效载荷
如图2-63所示,返回留言界面查看效果,即可触发XSS弹窗。

图2-63 触发XSS弹窗