从“Bug”到Struts2漏洞:小白必知的网络安全揭秘
“Bug” 一词的前世今生
在网络安全和软件开发的领域中,我们常常会听到 “bug” 这个词,它代表着程序或系统中存在的漏洞。但你知道吗,“bug” 最初的含义与昆虫有关。
1947 年 9 月 9 日,美国海军的工程师们在调试 Mark II 计算机时,发现机器出现故障。经过仔细检查,原来是一只飞蛾飞进了计算机的继电器中,导致电路短路。工程师们将这只飞蛾从机器中取出,并诙谐地把它贴在了工作日志上,还标注了 “第一个实际的 bug”。从那以后,“bug” 就逐渐被用来指代计算机系统或程序中的错误、缺陷和漏洞。
随着时间的推移,“bug” 的含义不断扩展,不仅包括硬件故障,更多地是指软件程序中的问题。如今,无论是手机应用、电脑软件,还是各种网络服务,都可能存在 bug。而发现和修复这些 bug,就成为了程序员和网络安全人员的重要工作。
什么是 Struts2 框架
了解了 “bug” 的含义后,我们再来认识一下 Struts2 框架。Struts2 是一个基于 MVC(Model-View-Controller,模型 – 视图 – 控制器)设计模式的开源 Web 应用框架,主要用于开发 Java EE(Java Enterprise Edition)的 Web 应用程序 。它就像是一个搭建 Web 应用的脚手架,为开发者提供了一系列的工具和规范,使得开发过程更加高效和规范。
在 MVC 模式中,Struts2 扮演着控制器(Controller)的角色,负责接收用户的请求,调用模型(Model)进行业务处理,并根据处理结果选择合适的视图(View)呈现给用户。比如,当你在浏览器中访问一个网站,输入用户名和密码进行登录时,Struts2 就会接收这个登录请求,调用相关的业务逻辑来验证用户名和密码是否正确,然后根据验证结果返回相应的页面,告诉你登录成功还是失败。
Struts2 的工作原理可以简单描述为:当 Web 容器接收到一个 HTTP 请求时,首先会经过一系列的过滤器,其中包括 Struts2 的核心过滤器 FilterDispatcher。FilterDispatcher 会根据请求的 URL,查找对应的 Action(业务逻辑处理类),并创建一个 ActionInvocation 对象来调用 Action。在调用 Action 之前,会先执行一系列的拦截器(Interceptor),这些拦截器可以完成诸如参数验证、日志记录、权限检查等功能。Action 执行完毕后,会返回一个结果字符串,ActionInvocation 会根据这个结果字符串找到对应的结果视图(Result),并将结果呈现给用户 。
举个例子,假设我们有一个简单的用户管理系统,其中有一个用户登录的功能。当用户在登录页面输入用户名和密码并点击登录按钮后,浏览器会将这个请求发送到服务器。Struts2 的 FilterDispatcher 接收到请求后,会根据配置文件找到对应的 UserLoginAction。然后,可能会先执行一些拦截器,比如验证用户输入的用户名和密码是否为空。如果验证通过,就会调用 UserLoginAction 的 execute 方法,在这个方法中会进行数据库查询,验证用户名和密码是否匹配。如果匹配,返回 “success” 结果字符串;如果不匹配,返回 “error” 结果字符串。最后,根据返回的结果字符串,找到对应的 JSP 页面,比如 “success.jsp” 或 “error.jsp”,并将页面返回给用户。
Struts2 漏洞大盘点
(一)S2-001 漏洞
S2-001 漏洞是 Struts2 框架中一个较为经典的漏洞,其原理与 Struts 2 框架中的 altSyntax 标签处理功能密切相关。当 altSyntax 功能开启时,它支持对标签中的 OGNL(Object-Graph Navigation Language,对象图导航语言)表达式进行解析并执行。
具体来说,Struts 2 允许用户提交包含 OGNL 表达式字符串的表单数据。若表单验证失败,服务器会将用户之前提交的 OGNL 表达式(如:%{1+1})进行解析执行,然后将结果重新填充到对应的表单数据中 。例如,在一个简单的登录页面中,当用户输入的用户名或密码不符合要求,提交表单后验证失败,此时如果用户名或密码字段中包含恶意的 OGNL 表达式,服务器就会执行该表达式。假设用户在用户名输入框中输入 %{#a=(new java.lang.ProcessBuilder (new java.lang.String []{“whoami”})).redirectErrorStream (true).start (),#b=#a.getInputStream (),#c=new java.io.InputStreamReader (#b),#d=new java.io.BufferedReader (#c),#e=new char [50000],#d.read (#e),#f=#context.get (“com.opensymphony.xwork2.dispatcher.HttpServletResponse”),#f.getWriter ().println (new java.lang.String (#e)),#f.getWriter ().flush (),#f.getWriter ().close ()},如果服务器存在 S2-001 漏洞,就会执行这个表达式,获取当前系统的用户名并返回给用户。
该漏洞主要影响 Struts 2.0.0 – Struts 2.0.8 版本。利用 S2-001 漏洞进行攻击的方式主要是构造恶意的 OGNL 表达式,实现命令执行。除了前面提到的获取用户名的例子,攻击者还可以通过构造类似的表达式来执行任意系统命令,如查看系统文件(%{#a=(new java.lang.ProcessBuilder (new java.lang.String []{“cat”,“/etc/passwd”})).redirectErrorStream (true).start (),#b=#a.getInputStream (),#c=new java.io.InputStreamReader (#b),#d=new java.io.BufferedReader (#c),#e=new char [50000],#d.read (#e),#f=#context.get (“com.opensymphony.xwork2.dispatcher.HttpServletResponse”),#f.getWriter ().println (new java.lang.String (#e)),#f.getWriter ().flush (),#f.getWriter ().close ()})、反弹 Shell 等,从而获取服务器的控制权。
(二)S2-066 漏洞
-
漏洞详情:S2-066 是一个存在于文件上传功能中的路径穿越漏洞,其编号为 CVE-2023-50164。主要影响版本为 Apache Struts 2.0.0 – 2.5.32 以及 6.0.0 – 6.3.0。攻击者可以通过操纵表单字段名称的大小写,将文件上传到预期上传目录之外的位置。在一些需要用户上传文件的 Web 应用中,正常情况下用户上传的文件会被保存到指定的目录,如 /upload/ 目录。但由于 S2-066 漏洞的存在,攻击者可以通过特殊的构造,将文件上传到 Web 根目录或其他敏感目录,从而实现恶意文件的上传和执行。
-
漏洞位置:该漏洞出现在 org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest 类中,尤其是在 parseRequest 方法处理上传文件时,对 filename 参数未充分过滤路径穿越符号。Struts2 原本会对上传文件名进行过滤,以防止路径穿越攻击。但攻击者可以借助使用 filename=…/…/webapps/ROOT/shell.jsp 等方式,从而绕过校验并将文件写入 Web 根目录。当用户上传文件时,JakartaMultiPartRequest 类的 parseRequest 方法会处理上传的文件信息,包括文件名。由于对 filename 参数的过滤不足,攻击者可以在文件名中添加路径穿越符号(如…/),使文件上传到非预期的目录。
-
漏洞利用:在 Struts2 的文件上传处理过程中,框架通常只保留上传文件的基本名称(basename)以防止路径穿越。但是,由于处理过程中的一个逻辑缺陷,攻击者可以通过以下方式绕过这个保护:使用首字母大写的表单字段名(例如,使用 “Upload” 而不是 “upload”),提供一个包含目标路径穿越文件名的单独表单字段,这使得未经处理的文件名可以覆盖基本名称保护,最终导致成功的路径穿越。
假设存在一个文件上传页面,其表单代码如下:
正常情况下,用户上传的文件会被保存到服务器的指定目录,文件名也会被处理为基本名称。但利用 S2-066 漏洞,攻击者可以构造如下的数据包:
POST /upload.action HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryabcdefg
------WebKitFormBoundaryabcdefg
Content-Disposition: form-data; name="Upload"; filename="shell.jsp"
Content-Type: application/octet-stream
------WebKitFormBoundaryabcdefg
Content-Disposition: form-data; name="uploadFileName"
../../webapps/ROOT/shell.jsp
------WebKitFormBoundaryabcdefg--
在这个数据包中,使用了首字母大写的 “Upload” 作为表单字段名,同时提供了一个 “uploadFileName” 字段,其值为 “…/…/webapps/ROOT/shell.jsp”,这是一个包含路径穿越的文件名。通过这种方式,攻击者可以将名为 shell.jsp 的恶意文件上传到 Web 根目录(/webapps/ROOT/),然后通过访问等方式,执行恶意代码,获取服务器的相关信息或执行任意命令。
Struts2 漏洞的危害与影响
Struts2 漏洞一旦被利用,其危害是多方面的,可能会给企业、组织和个人带来严重的损失。下面我们结合实际案例,来看看 Struts2 漏洞的具体危害与影响。
2017 年,美国消费者信用报告机构 Equifax 遭受了一次严重的数据泄露事件,而罪魁祸首就是 Struts2 漏洞 。Equifax 是一家在信用信息领域具有重要地位的公司,拥有大量消费者的敏感信息,包括姓名、地址、社会安全号码、出生日期和信用卡号码等。黑客利用 Struts2 框架中的远程代码执行漏洞(CVE-2017-5638),入侵了 Equifax 的系统。由于该漏洞允许攻击者在受影响的服务器上执行任意命令,黑客得以绕过安全措施,获取了约 1.43 亿美国人的详细个人信息,此外还有未知数量的英国和加拿大居民的个人数据也被泄露 。
这次数据泄露事件造成了极其恶劣的影响。对于 Equifax 公司本身,其股价在华尔街大幅下跌,近 14% 的市值蒸发,公司声誉受到极大损害。两个美国国会委员会针对此次事件举行听证会,纽约、伊利诺伊州、马赛诸塞州、康涅提格洲和宾夕法尼亚州的州检察长也在本州内展开调查,Equifax 面临着巨大的法律风险和经济赔偿压力。对于受影响的消费者来说,他们的个人信息被泄露,面临着身份被盗用、信用卡欺诈等风险,给个人生活和财产安全带来了严重威胁 。
除了数据泄露,Struts2 漏洞还可能导致服务器被控制和网站瘫痪。当攻击者利用漏洞获取服务器的控制权后,他们可以对服务器进行任意操作,如篡改网站内容、植入恶意软件、发起 DDoS 攻击等。2014 年,国外安全研究人员发现 Apache Struts2 在处理 CVE-2014-0094 的漏洞补丁中存在缺陷,可被轻易绕过,导致任意命令执行。黑客利用这个漏洞,对大量使用 Struts2 框架的网站进行攻击,许多网站的服务器被控制,数据被窃取,甚至出现网站瘫痪的情况,严重影响了网站的正常运营和用户体验 。
从这些案例可以看出,Struts2 漏洞的危害不容小觑。无论是大型企业还是小型网站,只要使用了存在漏洞的 Struts2 版本,都可能成为攻击者的目标。因此,及时发现和修复 Struts2 漏洞,对于保障网络安全至关重要。
如何防范 Struts2 漏洞
(一)及时更新与打补丁
及时关注 Apache 官方发布的安全公告,是防范 Struts2 漏洞的关键第一步。官方会在发现漏洞后迅速发布安全更新,这些更新包含了针对已知漏洞的修复代码。因此,一旦有新的安全版本发布,如 Struts 2.5.33 和 6.3.0.2 或更高版本,应尽快将项目中的 Struts2 框架升级到这些安全版本 。
在升级过程中,需要注意一些事项。首先,要对升级过程进行充分的测试。因为升级可能会对现有的业务逻辑产生影响,比如某些自定义的插件或扩展可能与新版本不兼容。所以,在正式升级到生产环境之前,应在测试环境中进行全面的功能测试、性能测试和安全测试,确保升级后的系统能够正常运行。其次,要备份好原有的项目代码和数据。这样在升级过程中出现问题时,可以迅速回滚到之前的状态,避免造成业务中断。
(二)安全配置与代码审查
除了及时更新框架版本,进行安全配置和代码审查也是防范 Struts2 漏洞的重要措施。在安全配置方面,要限制文件上传目录,只允许文件上传到指定的、安全的目录中,避免攻击者通过文件上传漏洞将恶意文件上传到服务器的敏感区域。同时,要对用户输入进行严格的过滤,特别是对于可能包含特殊字符的输入,如文件名、参数等,要过滤掉可能用于路径穿越或命令执行的特殊字符,如…/、;、| 等 。
开展代码审查工作也非常必要。在代码审查过程中,要重点检查 OGNL 表达式的使用。OGNL 表达式在 Struts2 中被广泛使用,但如果使用不当,就容易引发安全问题。要确保 OGNL 表达式的输入是经过严格验证和过滤的,避免用户能够注入恶意的 OGNL 表达式。例如,在使用 OGNL 表达式获取用户输入的值时,要对输入进行合法性检查,确保输入符合预期的格式和范围。可以使用正则表达式等工具对输入进行验证,只有验证通过的输入才能被用于 OGNL 表达式中。
(三)网络安全监测
使用入侵检测系统(IDS)、入侵防御系统(IPS)等网络安全设备,对网络流量进行实时监测,也是防范 Struts2 漏洞的有效手段。这些设备可以实时分析网络流量,识别出异常的请求模式。比如,当检测到请求中包含可疑的 OGNL 表达式或路径穿越字符串时,IDS/IPS 会及时发出警报,并可以根据预设的策略对攻击进行阻断 。
以入侵检测系统(IDS)为例,它会在网络中部署传感器,这些传感器会捕获网络流量,并将流量数据发送到 IDS 的分析引擎。分析引擎会根据预设的规则库,对流量数据进行分析。如果发现某个请求的参数中包含类似于 %{#a=(new java.lang.ProcessBuilder (new java.lang.String []{“whoami”})).redirectErrorStream (true).start (),#b=#a.getInputStream (),#c=new java.io.InputStreamReader (#b),#d=new java.io.BufferedReader (#c),#e=new char [50000],#d.read (#e),#f=#context.get (“com.opensymphony.xwork2.dispatcher.HttpServletResponse”),#f.getWriter ().println (new java.lang.String (#e)),#f.getWriter ().flush (),#f.getWriter ().close ()} 这样的恶意 OGNL 表达式,IDS 就会判定这是一次针对 Struts2 漏洞的攻击,并发出警报。入侵防御系统(IPS)则更加主动,它不仅能够检测到攻击,还可以直接在网络层面阻断攻击流量,防止攻击到达目标服务器。
防范 Struts2 漏洞需要从多个方面入手,及时更新与打补丁、安全配置与代码审查、网络安全监测等措施相互配合,才能有效地降低 Struts2 漏洞带来的安全风险。作为开发者和安全人员,我们要时刻保持警惕,不断学习和掌握新的安全知识和技能,为网络安全保驾护航。
总结
网络安全是一场没有硝烟的持久战,Struts2 漏洞只是其中的一个缩影。在未来的网络世界中,新的技术不断涌现,新的安全挑战也将接踵而至。作为网络世界的参与者,无论是开发者、安全人员还是普通用户,我们都应当持续学习网络安全知识,不断提高自己的安全意识和防范能力。只有这样,我们才能在享受网络带来的便利时,有效地保护自己和他人的信息安全,共同营造一个安全、稳定、可信的网络环境。让我们携手共进,为网络安全贡献自己的力量,让网络世界更加美好。
文章来源于互联网:从“Bug”到Struts2漏洞:小白必知的网络安全揭秘
相关推荐: Perl, C ++,C 开发茉莉花/玫瑰花培植APP
为了开发茉莉花和玫瑰花培植APP,结合Perl、C++和C的技术优势,建议采用分层架构设计,充分发挥各语言特性: ### 系统架构设计 “`mermaid graph TD A[用户界面层] –> B[业务逻辑层] B –> …
5bei.cn大模型教程网










