SV.SCRIPT

脚本执行

用已污染数据加载和执行来自不受信任控制域的功能时,将报告此错误。

从 2023.2 版本开始,此检查器将支持 Jakarta EE。

漏洞与风险

包含第三方功能(如 Web 小组件、库或其他功能来源)时,软件必须有效地信任该功能。如果没有充分的保护机制,功能可能是恶意性质(来自不受信任的来源,具有欺骗性质,或在从受信任来源传输过程中被修改)。功能还可能包含其自身的弱点,或将访问权限授予应保留为基础系统隐私的附加功能和状态信息,例如系统状态信息、敏感的应用程序数据或 Web 应用程序的 DOM。

攻击者可通过导致程序下载攻击者已放入不受信任控制域(例如恶意 Web 站点)的代码,将恶意功能插入程序。

缓解与预防

使用以下策略帮助减轻或防止这些问题:
  • 使用的库或框架经过审核,不允许出现这种弱点或提供可轻松容易避免此弱点的结构。
  • 当可接受对象(例如文件名或 URL)的集受限或已知时,创建从固定输入值(例如数字 ID)的集到实际文件名或 URL 的映射,并拒绝所有其他输入。
  • 假定所有输入都是恶意的。使用“接受已知正确”输入验证策略,即,使用严格符合规范的可接受输入的白名单。拒绝任何不严格符合规范的输入,或将其转换为严格符合规范。在执行输入验证时,考虑到所有可能相关的属性,包括长度、输入类型、可接受值的完整范围、缺少或多余的输入、语法、相关字段的一致性,以及业务规则遵从性。
  • 尽可能不要将库文件、包含文件和实用工具文件存储在 web 文档根目录中。
  • 了解不受信任的输入进入您软件的所有可能区域:参数或自变量、cookie、读取自网络的任何内容、环境变量、反向 DNS 查找、查询结果、请求标头、URL 组件、电子邮件、文件、文件名、数据库以及向应用程序提供数据的任何外部系统。请记住,可通过 API 调用间接获取此类输入。造成许多文件包含问题的原因是程序员假定某些输入不能修改,尤其是对 cookie 和 URL 组件来说。

漏洞代码示例

在此示例中,用 renderMenu 渲染页面的菜单。菜单渲染通过 javascript 脚本完成,其位置作为请求中的参数传递。调用对象 menuRenderer 的方法渲染来执行实际渲染。

攻击者可在请求中修改参数 renderer,使它指向在自己控制的服务器,从而加载恶意脚本而不是预期的库。以上代码将在恶意代码中执行渲染方法,从而使攻击者可访问应用程序的上下文。

复制
   public class MenuRenderer {
  
       public static void renderMenu(HttpServletRequest request) throws Exception {
           ScriptEngineManager manager = new ScriptEngineManager();
           ScriptEngine engine = manager.getEngineByName("JavaScript");
  
           //parameter "renderer" contains url of javascript rendering library
           URL url = new URL(request.getParameter("renderer"));
           engine.eval((String) url.getContent());
  
          Invocable inv = (Invocable) engine;
  
          // get script object on which we want to call the method
          Object menu = engine.get("menuRenderer");
  
          // invoke the method named "render" on the script object "obj"
          inv.invokeMethod(menu, "render", request.getParameter("menu"));
      }
  }

修正代码示例 1

在此修正代码示例中,输入进行了消毒。

复制
   public class MenuRenderer {
   
       public static void renderMenu(HttpServletRequest request) throws Exception {
           ScriptEngineManager manager = new ScriptEngineManager();
           ScriptEngine engine = manager.getEngineByName("JavaScript");
   
           //parameter "renderer" contains url of javascript rendering library
           String cleanRenderer = sanitize(request.getParameter("renderer"));
           URL url = new URL(cleanRenderer);
          engine.eval((String) url.getContent());
  
          Invocable inv = (Invocable) engine;
  
          // get script object on which we want to call the method
          Object menu = engine.get("menuRenderer");
  
          // invoke the method named "render" on the script object "menu"
          inv.invokeMethod(menu, "render", request.getParameter("menu"));
      }
  }

漏洞代码示例 2

在此示例中,doGet 相信“调度程序”参数未被篡改并包含在响应中。攻击者可通过修改参数“调度程序”,使服务器加载与预期不同的文件,从而导致信息泄漏或权限提升(管理员 servlet)。

复制
   void doGet(HttpServletRequest request, HttpServletResponse response) {
     final String dispatcher = request.getParameter("dispatcher");
     request.getRequestDispatcher(<source>).include(request, response);
   }

修正代码示例 2

在此修正代码示例中,输入进行了消毒。

复制
   void doGet(HttpServletRequest request, HttpServletResponse response) {
       final String dispatcher = request.getParameter("dispatcher");
       if(isValid(dispatcher)){
           request.getRequestDispatcher(<source>).include(request, response);
       }
   }

扩展

使用 @Check 指定执行安全检查或消毒输入的方法,通过 Klocwork 知识库扩展此检查器。有关详情,请参阅调整 Java 分析。