如何使用 Spring Boot 验证和清理 HTTP Get?
How to validate and sanitize HTTP Get with Spring Boot?
我不断收到来自 Checkmarx 代码扫描器的烦人错误,
Method getTotalValue at line 220 of src\java\com\example\PeopleController.java
gets user input for the personName element. This element’s value then flows through
the code without being properly sanitized or validated and is eventually
displayed to the user. This may enable a Cross-Site-Scripting attack.
这是我的代码。我想我做了所有必要的验证。还有什么???
@Slf4j
@Configuration
@RestController
@Validated
public class PeopleController {
@Autowired
private PeopleRepository peopleRepository;
@RequestMapping(value = "/api/getTotalValue/{personName}", method = RequestMethod.GET)
@ResponseBody
public Integer getTotalValue(@Size(max = 20, min = 1, message = "person is not found")
@PathVariable(value="personName", required=true) String personName) {
PersonObject po = peopleRepository.findByPersonName(
Jsoup.clean(personName, Whitelist.basic()));
try {
return po.getTotalValue();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@ExceptionHandler
public String constraintViolationHandler(ConstraintViolationException ex) {
return ex.getConstraintViolations().iterator().next()
.getMessage();
}
}
一定是缺少一些验证。如何使用 Spring Boot
正确验证 HTTP GET
您需要小心使用这些扫描工具,因为有时这些工具会报告误报,有时不需要更改代码。我不是 checkmarx 专家,但请确保此工具真正理解您正在使用的 bean 验证注释以及调用 Jsoup.clean(personName, Whitelist.basic())
。
I think I did ALL the validation necessary. What else???
首先,您需要了解控制器的应用程序级别输入卫生和业务级别输入验证之间的区别。你在这里做的是第二部分,第一部分可能在你的设置中丢失,这是专门从安全角度完成的,通常是为整个应用程序设置的。
您正在使用 @Size
注释来限制输入的大小,但这并不能保证不会出现错误的字符串 - 可能导致 XSS 攻击的字符串。然后,您正在使用调用 Jsoup.clean(personName, Whitelist.basic()))
来清理这个经过大小验证的输入。由于我不确定该调用的作用,因此您需要确保新值是 XSS - 安全的。您立即将该值传递给数据库调用,然后将 Integer
返回给 caller/client,因此我对此处发生 XSS 攻击的任何可能性都非常悲观,但工具是这么说的。
There must be some missing validation. How to validate HTTP GET
properly with Spring Boot
正如我之前解释的那样,输入验证是一个通常用于业务逻辑级别输入验证的术语,而输入清理/清理与安全性有关。在 Spring 引导环境中,这通常是通过使用 Spring 安全 APIs & 启用 XSS 过滤器或通过编写自己的 XSS 过滤器和插件来完成的它在你的应用程序中。过滤器首先出现,然后是您的控制器,因此您的控制器将始终具有经过清理的值,并且您将对该经过清理的值应用业务验证。
这是一个宽泛的答案,对于您可能会做的代码等 google。还建议阅读有关 XSS 攻击的更多信息。只需了解有多种方法可以实现同一目标。
How to create filter in Spring RESTful for Prevent XSS?
Cross Site Scripting (XSS) Attack Tutorial with Examples, Types & Prevention
在最后 link 中提到,
The first step in the prevention of this attack is Input validation.
Everything, that is entered by the user should be precisely validated,
because the user’s input may find its way to the output.
& 你没有在你的代码中做,所以我猜没有 XSS。
编辑:
XSS 安全有两个方面 - 首先不允许对服务器端代码进行恶意输入,这可以通过 XSS 过滤器来完成,有时,允许恶意输入没有害处(假设你正在保存恶意输入数据库或返回 API 响应)。
第二个方面是向 HTML 客户指示可能的 XSS 攻击(如果我们确定 API 客户将成为 HTML / UI)然后我们需要添加 X-XSS-Protection
header & 这将通过以下代码完成。这将使浏览器能够打开其 XSS 保护功能(如果存在)。
@Override
受保护的无效配置(HttpSecurity http)抛出异常{
http.headers().xssProtection()....
}
What is the http-header “X-XSS-Protection”?
Is Xss protection in Spring security enabled by default?
对于第一个方面,即编写过滤器 - 请参阅该答案中的 my this answer 和 link。
我想,我在上面写错了 Spring 安全提供输入卫生过滤器,我想,它没有。将验证并让您知道。我已经在回答这个问题时提到的行上写了我的自定义过滤器 - Prevent XSS in Spring MVC controller
您还必须了解 Spring Boot 也习惯于编写传统的 MVC 应用程序,其中服务器端也呈现 HTML 以呈现。在 JSON 响应 ( REST APIs ) 的情况下,UI 客户端可以控制要转义的内容和不转义的内容,因为 JSON 输出并不总是馈送到 HTML 客户端又名浏览器。
我有一个很棒的(恕我直言)解决方案,它使用 Jsoup 和 Apache Commons。我希望它能帮助其他人
添加这个 class
import org.apache.commons.lang.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class SecurityEscape {
public static String cleanIt(String arg0) {
return Jsoup.clean(
StringEscapeUtils.escapeHtml(StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeSql(arg0)))
, Whitelist.basic());
}
}
现在您可以像这样在您的控制器中清除来自 GET
或 POST
的所有传入字符串
@PostMapping("/api/blah") or GET whatever . .. . . .
public ResponseEntity<?> testIt(String whatever) {
String whatever = SecurityEscape.cleanIt(whatever);
... ..
在这个 CHECKMARX 说这是一个安全代码之后
特别感谢@Sabir Khan 的指导
Checkmarx v8.8.0 也对我有用
offendingValue = StringEscapeUtils.escapeHtml(offendingValue);
顺便说一句,我尝试了以下解决方案:https://github.com/mehditahmasebi/spring/blob/master/spring-xss-filter/src/main/java/com/spring/boot/web/WebConfig.java 我们成功了
这对我有用 ----
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.util.StringUtils;
public class SecurityUtil {
private SecurityUtil() {
throw new IllegalStateException("Utility class");
}
/**
* Remove escape characters like Html/Js scripts from input if present
* @param str Input string
* @return sanitize string
*/
public static String cleanIt(String str) {
return Jsoup.clean(
StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript (StringUtils.replace(str, "'", "''")))
, Whitelist.basic());
}
}
org.apache.commons.lang3.StringEscapeUtils
已弃用 org.apache.commons.text.StringEscapeUtils
(documentation)
不要忘记将其导入您的依赖项 ()。
用法相同,eg:
import org.apache.commons.text.StringEscapeUtils;
...
String escapedHtml = StringEscapeUtils.escapeHtml4("Hello world!");
我不断收到来自 Checkmarx 代码扫描器的烦人错误,
Method getTotalValue at line 220 of src\java\com\example\PeopleController.java
gets user input for the personName element. This element’s value then flows through
the code without being properly sanitized or validated and is eventually
displayed to the user. This may enable a Cross-Site-Scripting attack.
这是我的代码。我想我做了所有必要的验证。还有什么???
@Slf4j
@Configuration
@RestController
@Validated
public class PeopleController {
@Autowired
private PeopleRepository peopleRepository;
@RequestMapping(value = "/api/getTotalValue/{personName}", method = RequestMethod.GET)
@ResponseBody
public Integer getTotalValue(@Size(max = 20, min = 1, message = "person is not found")
@PathVariable(value="personName", required=true) String personName) {
PersonObject po = peopleRepository.findByPersonName(
Jsoup.clean(personName, Whitelist.basic()));
try {
return po.getTotalValue();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@ExceptionHandler
public String constraintViolationHandler(ConstraintViolationException ex) {
return ex.getConstraintViolations().iterator().next()
.getMessage();
}
}
一定是缺少一些验证。如何使用 Spring Boot
正确验证 HTTP GET您需要小心使用这些扫描工具,因为有时这些工具会报告误报,有时不需要更改代码。我不是 checkmarx 专家,但请确保此工具真正理解您正在使用的 bean 验证注释以及调用 Jsoup.clean(personName, Whitelist.basic())
。
I think I did ALL the validation necessary. What else???
首先,您需要了解控制器的应用程序级别输入卫生和业务级别输入验证之间的区别。你在这里做的是第二部分,第一部分可能在你的设置中丢失,这是专门从安全角度完成的,通常是为整个应用程序设置的。
您正在使用 @Size
注释来限制输入的大小,但这并不能保证不会出现错误的字符串 - 可能导致 XSS 攻击的字符串。然后,您正在使用调用 Jsoup.clean(personName, Whitelist.basic()))
来清理这个经过大小验证的输入。由于我不确定该调用的作用,因此您需要确保新值是 XSS - 安全的。您立即将该值传递给数据库调用,然后将 Integer
返回给 caller/client,因此我对此处发生 XSS 攻击的任何可能性都非常悲观,但工具是这么说的。
There must be some missing validation. How to validate HTTP GET properly with Spring Boot
正如我之前解释的那样,输入验证是一个通常用于业务逻辑级别输入验证的术语,而输入清理/清理与安全性有关。在 Spring 引导环境中,这通常是通过使用 Spring 安全 APIs & 启用 XSS 过滤器或通过编写自己的 XSS 过滤器和插件来完成的它在你的应用程序中。过滤器首先出现,然后是您的控制器,因此您的控制器将始终具有经过清理的值,并且您将对该经过清理的值应用业务验证。
这是一个宽泛的答案,对于您可能会做的代码等 google。还建议阅读有关 XSS 攻击的更多信息。只需了解有多种方法可以实现同一目标。
How to create filter in Spring RESTful for Prevent XSS?
Cross Site Scripting (XSS) Attack Tutorial with Examples, Types & Prevention
在最后 link 中提到,
The first step in the prevention of this attack is Input validation. Everything, that is entered by the user should be precisely validated, because the user’s input may find its way to the output.
& 你没有在你的代码中做,所以我猜没有 XSS。
编辑:
XSS 安全有两个方面 - 首先不允许对服务器端代码进行恶意输入,这可以通过 XSS 过滤器来完成,有时,允许恶意输入没有害处(假设你正在保存恶意输入数据库或返回 API 响应)。
第二个方面是向 HTML 客户指示可能的 XSS 攻击(如果我们确定 API 客户将成为 HTML / UI)然后我们需要添加 X-XSS-Protection
header & 这将通过以下代码完成。这将使浏览器能够打开其 XSS 保护功能(如果存在)。
@Override 受保护的无效配置(HttpSecurity http)抛出异常{
http.headers().xssProtection()....
}
What is the http-header “X-XSS-Protection”?
Is Xss protection in Spring security enabled by default?
对于第一个方面,即编写过滤器 - 请参阅该答案中的 my this answer 和 link。
我想,我在上面写错了 Spring 安全提供输入卫生过滤器,我想,它没有。将验证并让您知道。我已经在回答这个问题时提到的行上写了我的自定义过滤器 - Prevent XSS in Spring MVC controller
您还必须了解 Spring Boot 也习惯于编写传统的 MVC 应用程序,其中服务器端也呈现 HTML 以呈现。在 JSON 响应 ( REST APIs ) 的情况下,UI 客户端可以控制要转义的内容和不转义的内容,因为 JSON 输出并不总是馈送到 HTML 客户端又名浏览器。
我有一个很棒的(恕我直言)解决方案,它使用 Jsoup 和 Apache Commons。我希望它能帮助其他人
添加这个 class
import org.apache.commons.lang.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class SecurityEscape {
public static String cleanIt(String arg0) {
return Jsoup.clean(
StringEscapeUtils.escapeHtml(StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeSql(arg0)))
, Whitelist.basic());
}
}
现在您可以像这样在您的控制器中清除来自 GET
或 POST
的所有传入字符串
@PostMapping("/api/blah") or GET whatever . .. . . .
public ResponseEntity<?> testIt(String whatever) {
String whatever = SecurityEscape.cleanIt(whatever);
... ..
在这个 CHECKMARX 说这是一个安全代码之后
特别感谢@Sabir Khan 的指导
Checkmarx v8.8.0 也对我有用
offendingValue = StringEscapeUtils.escapeHtml(offendingValue);
顺便说一句,我尝试了以下解决方案:https://github.com/mehditahmasebi/spring/blob/master/spring-xss-filter/src/main/java/com/spring/boot/web/WebConfig.java 我们成功了
这对我有用 ----
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.util.StringUtils;
public class SecurityUtil {
private SecurityUtil() {
throw new IllegalStateException("Utility class");
}
/**
* Remove escape characters like Html/Js scripts from input if present
* @param str Input string
* @return sanitize string
*/
public static String cleanIt(String str) {
return Jsoup.clean(
StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript (StringUtils.replace(str, "'", "''")))
, Whitelist.basic());
}
}
org.apache.commons.lang3.StringEscapeUtils
已弃用 org.apache.commons.text.StringEscapeUtils
(documentation)
不要忘记将其导入您的依赖项 (
用法相同,eg:
import org.apache.commons.text.StringEscapeUtils;
...
String escapedHtml = StringEscapeUtils.escapeHtml4("Hello world!");