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 分析。