14

我得到了我的 javaEE 应用程序的 veracode 报告。它在任何日志记录中都有缺陷(使用 log4j),所以我将StringEscapeUtils.escapeJava(log)它们添加到所有日志中,但 veracode 一直将它们报告为安全漏洞。

这是一个正确的解决方案吗?我还可以做些什么?

这是报告信息:标题:日志的输出中和不当

描述:函数调用可能导致日志伪造攻击。将未经处理的用户提供的数据写入日志文件允许攻击者伪造日志条目或将恶意内容注入日志文件。损坏的日志文件可用于掩盖攻击者的踪迹或作为攻击日志查看或处理实用程序的传递机制。例如,如果 Web 管理员使用基于浏览器的实用程序来查看日志,则可能会发生跨站点脚本攻击。

建议:尽可能避免将用户输入直接嵌入到日志文件中。使用安全的日志记录机制(例如 OWASP ESAPI 记录器)清理用户提供的用于构建日志条目的数据,该机制将自动删除意外的回车和换行,并且可以配置为对非字母数字数据使用 HTML 实体编码。仅在绝对必要时编写自定义黑名单代码。始终验证用户提供的输入以确保其符合预期格式,并尽可能使用集中的数据验证例程。

他们建议使用 ESAPI,但这是一个非常大的项目,所以我需要最简单的解决方案,这就是我尝试使用 String.escape 'StringEscapeUtils.escapeJava(log)' 的原因

谢谢先进!

4

5 回答 5

10

我是 Veracode 应用安全咨询小组的负责人,可以详细回答您的问题。对话的最佳地点是通过 Support@veracode.com,因为讨论可能涉及您的发现的具体细节,我们可能希望避免公开这些细节。

简短的回答是 StringEscapeUtils.escapeJava() 可以有效地消除典型的 CRLF 风险,但它不是我们的系统自动识别的机制之一,因为在某些情况下它可能不够用。

Veracode 系统具有适当标记这些发现的机制,因此它们不会引起混淆。

请联系 Veracode 支持 (support@veracode.com),我们将能够详细讨论。

最好的问候,吉姆。

于 2013-04-26T13:45:21.867 回答
6

这份报告中有两个问题混为一谈。

首先,存在日志注入 - 使用换行符溢出到单独的日志行中。StringEscapeUtils.escapeJava生成具有行分隔符和非 ASCII 字符转义的输出,原则上确保此问题得到修复。但是,Veracode 并不知道这一点——作为一个自动扫描器,它对这种方法的作用还不够了解,因此无法确定,因此它必须报告那里可能仍然存在漏洞。自然,Veracode 无法知道第三方库代码中的每一个转义函数。

当您在日志行中使用自己的分隔符时,也可能发生日志注入,例如Bad thing happened with parameters {0} and {1}. 在这种情况下,如果攻击者" and "在其中一个参数中包含字符串,您将无法准确地重新创建哪个数据在哪个参数中。这里的答案是用不出现在转义函数输出中的分隔符包围参数 - 例如,在每个值周围加上双引号,并用于escapeJava转义值中的任何双引号字符。

当使用某些工具查看日志时,第二次攻击发生在您的应用程序之外。如果该工具存在注入漏洞,则日志数据中的元字符可能会变为活动状态。经典示例是在 Web 界面中查看日志,将它们直接复制到页面中而不转义,从而导致 HTML 注入,从而导致日志查看应用程序中的跨站点脚本。

如果您可以确定您只查看不会出现此类愚蠢错误的工具中的日志,则无需担心。

否则,请尝试从您认为可能受到影响的语言中转义任何元字符。通常<用于&HTML。如果您不想对所有非 HTML 日志数据进行 HTML 转义,另一种方法是将这些字符替换为转义\u003E的等价物,例如escapeJava.

同样,Veracode 将无法自动确定您所做的事情在那里一定是安全的,因此一旦您对它感到满意,您就必须将这些报告标记为忽略/处理。

于 2013-04-26T13:57:24.643 回答
4

我遇到了同样的问题,我通常忽略这个缺陷,原因很简单:记录器只是给了我一个日志事件。它不应该关心格式(暴露敏感数据是另一个问题)。

这里的解决方案是在将日志事件写入日志文件的附加程序中添加适当的过滤/后处理。在此步骤中,您可以删除特殊字符(\0\r-回车、\b-退格、\x1b-转义和\x7f-删除)并替换\n为,\n...以使无法在日志中注入虚假日志行。

当你这样做时,你可以放心地忽略所有这些缺陷。

此外,如果系统管理员使用错误的工具查看日志文件(任何执行转义序列\r和退格的文件),他应该被解雇。

于 2015-06-01T10:23:02.320 回答
1

使用 StringEscapeUtils.escapeHtml(log) 来避免 HTML 注入并可能解决您的问题。

于 2014-07-16T21:08:27.263 回答
1

正如我所观察到的(并从 Veracode 的消息中理解),应该执行以下操作:

  • 要删除的换行符,以便不能伪造日志(通过生成可以模仿日志条目的输入)
  • 要转义/编码某些字符以减轻对日志查看工具的攻击

这可以通过使用encodeForHtml()ESAPI 库中的编码方法来实现。但是,该库需要一些额外的配置(ESAPI.properties),如果您只想转义记录的值,这是多余的。为了克服这个问题,我提取(并稍微修改)了转义代码。这是代码:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HtmlEncoder {

  private static final char REPLACEMENT_CHAR = '\ufffd';
  private static final String REPLACEMENT_HEX = "fffd";
  private static Map<Character,String> characterToEntityMap; // statically initialized
  /**
   * Initialize an array to mark which characters are to be encoded. Store the hex
   * string for that character to save time later. If the character shouldn't be
   * encoded, then store null.
   */
  private static final String[] encodedCharsCache = new String[256];

  public String encodeForHTML(String input) {
    return encode(input);
  }

  // note: bases encodeForHTML() from ESAPI. Unfortunately ESAPI requires configuration in properties which
  // is a pain if you just need to encode
  private String encode(String input) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < input.length(); i++) {
      char c = input.charAt(i);
      sb.append(encodeCharacter(c));
    }
    return sb.toString();
  }

  private static String toHex(char c) {
    return Integer.toHexString(c);
  }

  private static String getHexForNonAlphanumeric(char c)  {
      // note: we cache only up to 256 characters (ASCII)
    return c < 0xFF ? encodedCharsCache[c] : toHex(c);
  }

  private String encodeCharacter( Character c ) {

    // check for immune characters
    if ( c == ',' || c == '.' || c == '-' || c == '_' || c == ' ') {
      return ""+c;
    }

    // check for alphanumeric characters
    String hex = getHexForNonAlphanumeric(c);
    if ( hex == null ) { // means we should not encode the character
      return ""+c;
    }

    // check for illegal characters
    if ( ( c <= 0x1f && c != '\t' && c != '\n' && c != '\r' ) || ( c >= 0x7f && c <= 0x9f ) )
    {
      hex = REPLACEMENT_HEX; // Let's entity encode this instead of returning it
      c = REPLACEMENT_CHAR;
    }

    // check if there's a defined entity
    String entityName = (String) characterToEntityMap.get(c);
    if (entityName != null) {
      return "&" + entityName + ";";
    }

    // return hex representation of entity
    return "&#x" + hex + ";";
  }

  static {
    for ( char c = 0; c < 0xFF; c++ ) {
      if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A ) {
        encodedCharsCache[c] = null;
      } else {
        encodedCharsCache[c] = toHex(c).intern();
      }
    }

    Map<Character, String> map = new HashMap<Character,String>(252);

    map.put((char)34,  "quot"); /* quotation mark */
    map.put((char)38,  "amp");   /* ampersand */
    map.put((char)60,  "lt");  /* less-than sign */
    map.put((char)62,  "gt");  /* greater-than sign */
    map.put((char)160, "nbsp"); /* no-break space */
    map.put((char)161, "iexcl");  /* inverted exclamation mark */
    map.put((char)162, "cent"); /* cent sign */
    map.put((char)163, "pound");  /* pound sign */
    map.put((char)164, "curren"); /* currency sign */
    map.put((char)165, "yen");   /* yen sign */
    map.put((char)166, "brvbar"); /* broken bar */
    map.put((char)167, "sect"); /* section sign */
    map.put((char)168, "uml");   /* diaeresis */
    map.put((char)169, "copy"); /* copyright sign */
    map.put((char)170, "ordf"); /* feminine ordinal indicator */
    map.put((char)171, "laquo");  /* left-pointing double angle quotation mark */
    map.put((char)172, "not");   /* not sign */
    map.put((char)173, "shy");   /* soft hyphen */
    map.put((char)174, "reg");   /* registered sign */
    map.put((char)175, "macr"); /* macron */
    map.put((char)176, "deg");   /* degree sign */
    map.put((char)177, "plusmn"); /* plus-minus sign */
    map.put((char)178, "sup2"); /* superscript two */
    map.put((char)179, "sup3"); /* superscript three */
    map.put((char)180, "acute");  /* acute accent */
    map.put((char)181, "micro");  /* micro sign */
    map.put((char)182, "para"); /* pilcrow sign */
    map.put((char)183, "middot"); /* middle dot */
    map.put((char)184, "cedil");  /* cedilla */
    map.put((char)185, "sup1"); /* superscript one */
    map.put((char)186, "ordm"); /* masculine ordinal indicator */
    map.put((char)187, "raquo");  /* right-pointing double angle quotation mark */
    map.put((char)188, "frac14"); /* vulgar fraction one quarter */
    map.put((char)189, "frac12"); /* vulgar fraction one half */
    map.put((char)190, "frac34"); /* vulgar fraction three quarters */
    map.put((char)191, "iquest"); /* inverted question mark */
    map.put((char)192, "Agrave"); /* Latin capital letter a with grave */
    map.put((char)193, "Aacute"); /* Latin capital letter a with acute */
    map.put((char)194, "Acirc");  /* Latin capital letter a with circumflex */
    map.put((char)195, "Atilde"); /* Latin capital letter a with tilde */
    map.put((char)196, "Auml"); /* Latin capital letter a with diaeresis */
    map.put((char)197, "Aring");  /* Latin capital letter a with ring above */
    map.put((char)198, "AElig");  /* Latin capital letter ae */
    map.put((char)199, "Ccedil"); /* Latin capital letter c with cedilla */
    map.put((char)200, "Egrave"); /* Latin capital letter e with grave */
    map.put((char)201, "Eacute"); /* Latin capital letter e with acute */
    map.put((char)202, "Ecirc");  /* Latin capital letter e with circumflex */
    map.put((char)203, "Euml"); /* Latin capital letter e with diaeresis */
    map.put((char)204, "Igrave"); /* Latin capital letter i with grave */
    map.put((char)205, "Iacute"); /* Latin capital letter i with acute */
    map.put((char)206, "Icirc");  /* Latin capital letter i with circumflex */
    map.put((char)207, "Iuml"); /* Latin capital letter i with diaeresis */
    map.put((char)208, "ETH");   /* Latin capital letter eth */
    map.put((char)209, "Ntilde"); /* Latin capital letter n with tilde */
    map.put((char)210, "Ograve"); /* Latin capital letter o with grave */
    map.put((char)211, "Oacute"); /* Latin capital letter o with acute */
    map.put((char)212, "Ocirc");  /* Latin capital letter o with circumflex */
    map.put((char)213, "Otilde"); /* Latin capital letter o with tilde */
    map.put((char)214, "Ouml"); /* Latin capital letter o with diaeresis */
    map.put((char)215, "times");  /* multiplication sign */
    map.put((char)216, "Oslash"); /* Latin capital letter o with stroke */
    map.put((char)217, "Ugrave"); /* Latin capital letter u with grave */
    map.put((char)218, "Uacute"); /* Latin capital letter u with acute */
    map.put((char)219, "Ucirc");  /* Latin capital letter u with circumflex */
    map.put((char)220, "Uuml"); /* Latin capital letter u with diaeresis */
    map.put((char)221, "Yacute"); /* Latin capital letter y with acute */
    map.put((char)222, "THORN");  /* Latin capital letter thorn */
    map.put((char)223, "szlig");  /* Latin small letter sharp sXCOMMAX German Eszett */
    map.put((char)224, "agrave"); /* Latin small letter a with grave */
    map.put((char)225, "aacute"); /* Latin small letter a with acute */
    map.put((char)226, "acirc");  /* Latin small letter a with circumflex */
    map.put((char)227, "atilde"); /* Latin small letter a with tilde */
    map.put((char)228, "auml"); /* Latin small letter a with diaeresis */
    map.put((char)229, "aring");  /* Latin small letter a with ring above */
    map.put((char)230, "aelig");  /* Latin lowercase ligature ae */
    map.put((char)231, "ccedil"); /* Latin small letter c with cedilla */
    map.put((char)232, "egrave"); /* Latin small letter e with grave */
    map.put((char)233, "eacute"); /* Latin small letter e with acute */
    map.put((char)234, "ecirc");  /* Latin small letter e with circumflex */
    map.put((char)235, "euml"); /* Latin small letter e with diaeresis */
    map.put((char)236, "igrave"); /* Latin small letter i with grave */
    map.put((char)237, "iacute"); /* Latin small letter i with acute */
    map.put((char)238, "icirc");  /* Latin small letter i with circumflex */
    map.put((char)239, "iuml"); /* Latin small letter i with diaeresis */
    map.put((char)240, "eth");   /* Latin small letter eth */
    map.put((char)241, "ntilde"); /* Latin small letter n with tilde */
    map.put((char)242, "ograve"); /* Latin small letter o with grave */
    map.put((char)243, "oacute"); /* Latin small letter o with acute */
    map.put((char)244, "ocirc");  /* Latin small letter o with circumflex */
    map.put((char)245, "otilde"); /* Latin small letter o with tilde */
    map.put((char)246, "ouml"); /* Latin small letter o with diaeresis */
    map.put((char)247, "divide"); /* division sign */
    map.put((char)248, "oslash"); /* Latin small letter o with stroke */
    map.put((char)249, "ugrave"); /* Latin small letter u with grave */
    map.put((char)250, "uacute"); /* Latin small letter u with acute */
    map.put((char)251, "ucirc");  /* Latin small letter u with circumflex */
    map.put((char)252, "uuml"); /* Latin small letter u with diaeresis */
    map.put((char)253, "yacute"); /* Latin small letter y with acute */
    map.put((char)254, "thorn");  /* Latin small letter thorn */
    map.put((char)255, "yuml"); /* Latin small letter y with diaeresis */
    map.put((char)338, "OElig");  /* Latin capital ligature oe */
    map.put((char)339, "oelig");  /* Latin small ligature oe */
    map.put((char)352, "Scaron"); /* Latin capital letter s with caron */
    map.put((char)353, "scaron"); /* Latin small letter s with caron */
    map.put((char)376, "Yuml"); /* Latin capital letter y with diaeresis */
    map.put((char)402, "fnof"); /* Latin small letter f with hook */
    map.put((char)710, "circ"); /* modifier letter circumflex accent */
    map.put((char)732, "tilde");  /* small tilde */
    map.put((char)913, "Alpha");  /* Greek capital letter alpha */
    map.put((char)914, "Beta"); /* Greek capital letter beta */
    map.put((char)915, "Gamma");  /* Greek capital letter gamma */
    map.put((char)916, "Delta");  /* Greek capital letter delta */
    map.put((char)917, "Epsilon");  /* Greek capital letter epsilon */
    map.put((char)918, "Zeta"); /* Greek capital letter zeta */
    map.put((char)919, "Eta");   /* Greek capital letter eta */
    map.put((char)920, "Theta");  /* Greek capital letter theta */
    map.put((char)921, "Iota"); /* Greek capital letter iota */
    map.put((char)922, "Kappa");  /* Greek capital letter kappa */
    map.put((char)923, "Lambda"); /* Greek capital letter lambda */
    map.put((char)924, "Mu");  /* Greek capital letter mu */
    map.put((char)925, "Nu");  /* Greek capital letter nu */
    map.put((char)926, "Xi");  /* Greek capital letter xi */
    map.put((char)927, "Omicron");  /* Greek capital letter omicron */
    map.put((char)928, "Pi");  /* Greek capital letter pi */
    map.put((char)929, "Rho");   /* Greek capital letter rho */
    map.put((char)931, "Sigma");  /* Greek capital letter sigma */
    map.put((char)932, "Tau");   /* Greek capital letter tau */
    map.put((char)933, "Upsilon");  /* Greek capital letter upsilon */
    map.put((char)934, "Phi");   /* Greek capital letter phi */
    map.put((char)935, "Chi");   /* Greek capital letter chi */
    map.put((char)936, "Psi");   /* Greek capital letter psi */
    map.put((char)937, "Omega");  /* Greek capital letter omega */
    map.put((char)945, "alpha");  /* Greek small letter alpha */
    map.put((char)946, "beta"); /* Greek small letter beta */
    map.put((char)947, "gamma");  /* Greek small letter gamma */
    map.put((char)948, "delta");  /* Greek small letter delta */
    map.put((char)949, "epsilon");  /* Greek small letter epsilon */
    map.put((char)950, "zeta"); /* Greek small letter zeta */
    map.put((char)951, "eta");   /* Greek small letter eta */
    map.put((char)952, "theta");  /* Greek small letter theta */
    map.put((char)953, "iota"); /* Greek small letter iota */
    map.put((char)954, "kappa");  /* Greek small letter kappa */
    map.put((char)955, "lambda"); /* Greek small letter lambda */
    map.put((char)956, "mu");  /* Greek small letter mu */
    map.put((char)957, "nu");  /* Greek small letter nu */
    map.put((char)958, "xi");  /* Greek small letter xi */
    map.put((char)959, "omicron");  /* Greek small letter omicron */
    map.put((char)960, "pi");  /* Greek small letter pi */
    map.put((char)961, "rho");   /* Greek small letter rho */
    map.put((char)962, "sigmaf"); /* Greek small letter final sigma */
    map.put((char)963, "sigma");  /* Greek small letter sigma */
    map.put((char)964, "tau");   /* Greek small letter tau */
    map.put((char)965, "upsilon");  /* Greek small letter upsilon */
    map.put((char)966, "phi");   /* Greek small letter phi */
    map.put((char)967, "chi");   /* Greek small letter chi */
    map.put((char)968, "psi");   /* Greek small letter psi */
    map.put((char)969, "omega");  /* Greek small letter omega */
    map.put((char)977, "thetasym"); /* Greek theta symbol */
    map.put((char)978, "upsih");  /* Greek upsilon with hook symbol */
    map.put((char)982, "piv");   /* Greek pi symbol */
    map.put((char)8194,  "ensp"); /* en space */
    map.put((char)8195,  "emsp"); /* em space */
    map.put((char)8201,  "thinsp"); /* thin space */
    map.put((char)8204,  "zwnj"); /* zero width non-joiner */
    map.put((char)8205,  "zwj");   /* zero width joiner */
    map.put((char)8206,  "lrm");   /* left-to-right mark */
    map.put((char)8207,  "rlm");   /* right-to-left mark */
    map.put((char)8211,  "ndash");  /* en dash */
    map.put((char)8212,  "mdash");  /* em dash */
    map.put((char)8216,  "lsquo");  /* left single quotation mark */
    map.put((char)8217,  "rsquo");  /* right single quotation mark */
    map.put((char)8218,  "sbquo");  /* single low-9 quotation mark */
    map.put((char)8220,  "ldquo");  /* left double quotation mark */
    map.put((char)8221,  "rdquo");  /* right double quotation mark */
    map.put((char)8222,  "bdquo");  /* double low-9 quotation mark */
    map.put((char)8224,  "dagger"); /* dagger */
    map.put((char)8225,  "Dagger"); /* double dagger */
    map.put((char)8226,  "bull"); /* bullet */
    map.put((char)8230,  "hellip"); /* horizontal ellipsis */
    map.put((char)8240,  "permil"); /* per mille sign */
    map.put((char)8242,  "prime");  /* prime */
    map.put((char)8243,  "Prime");  /* double prime */
    map.put((char)8249,  "lsaquo"); /* single left-pointing angle quotation mark */
    map.put((char)8250,  "rsaquo"); /* single right-pointing angle quotation mark */
    map.put((char)8254,  "oline");  /* overline */
    map.put((char)8260,  "frasl");  /* fraction slash */
    map.put((char)8364,  "euro"); /* euro sign */
    map.put((char)8465,  "image");  /* black-letter capital i */
    map.put((char)8472,  "weierp"); /* script capital pXCOMMAX Weierstrass p */
    map.put((char)8476,  "real"); /* black-letter capital r */
    map.put((char)8482,  "trade");  /* trademark sign */
    map.put((char)8501,  "alefsym");  /* alef symbol */
    map.put((char)8592,  "larr"); /* leftwards arrow */
    map.put((char)8593,  "uarr"); /* upwards arrow */
    map.put((char)8594,  "rarr"); /* rightwards arrow */
    map.put((char)8595,  "darr"); /* downwards arrow */
    map.put((char)8596,  "harr"); /* left right arrow */
    map.put((char)8629,  "crarr");  /* downwards arrow with corner leftwards */
    map.put((char)8656,  "lArr"); /* leftwards double arrow */
    map.put((char)8657,  "uArr"); /* upwards double arrow */
    map.put((char)8658,  "rArr"); /* rightwards double arrow */
    map.put((char)8659,  "dArr"); /* downwards double arrow */
    map.put((char)8660,  "hArr"); /* left right double arrow */
    map.put((char)8704,  "forall"); /* for all */
    map.put((char)8706,  "part"); /* partial differential */
    map.put((char)8707,  "exist");  /* there exists */
    map.put((char)8709,  "empty");  /* empty set */
    map.put((char)8711,  "nabla");  /* nabla */
    map.put((char)8712,  "isin"); /* element of */
    map.put((char)8713,  "notin");  /* not an element of */
    map.put((char)8715,  "ni");  /* contains as member */
    map.put((char)8719,  "prod"); /* n-ary product */
    map.put((char)8721,  "sum");   /* n-ary summation */
    map.put((char)8722,  "minus");  /* minus sign */
    map.put((char)8727,  "lowast"); /* asterisk operator */
    map.put((char)8730,  "radic");  /* square root */
    map.put((char)8733,  "prop"); /* proportional to */
    map.put((char)8734,  "infin");  /* infinity */
    map.put((char)8736,  "ang");   /* angle */
    map.put((char)8743,  "and");   /* logical and */
    map.put((char)8744,  "or");  /* logical or */
    map.put((char)8745,  "cap");   /* intersection */
    map.put((char)8746,  "cup");   /* union */
    map.put((char)8747,  "int");   /* integral */
    map.put((char)8756,  "there4"); /* therefore */
    map.put((char)8764,  "sim");   /* tilde operator */
    map.put((char)8773,  "cong"); /* congruent to */
    map.put((char)8776,  "asymp");  /* almost equal to */
    map.put((char)8800,  "ne");  /* not equal to */
    map.put((char)8801,  "equiv");  /* identical toXCOMMAX equivalent to */
    map.put((char)8804,  "le");  /* less-than or equal to */
    map.put((char)8805,  "ge");  /* greater-than or equal to */
    map.put((char)8834,  "sub");   /* subset of */
    map.put((char)8835,  "sup");   /* superset of */
    map.put((char)8836,  "nsub"); /* not a subset of */
    map.put((char)8838,  "sube"); /* subset of or equal to */
    map.put((char)8839,  "supe"); /* superset of or equal to */
    map.put((char)8853,  "oplus");  /* circled plus */
    map.put((char)8855,  "otimes"); /* circled times */
    map.put((char)8869,  "perp"); /* up tack */
    map.put((char)8901,  "sdot"); /* dot operator */
    map.put((char)8968,  "lceil");  /* left ceiling */
    map.put((char)8969,  "rceil");  /* right ceiling */
    map.put((char)8970,  "lfloor"); /* left floor */
    map.put((char)8971,  "rfloor"); /* right floor */
    map.put((char)9001,  "lang"); /* left-pointing angle bracket */
    map.put((char)9002,  "rang"); /* right-pointing angle bracket */
    map.put((char)9674,  "loz");   /* lozenge */
    map.put((char)9824,  "spades"); /* black spade suit */
    map.put((char)9827,  "clubs");  /* black club suit */
    map.put((char)9829,  "hearts"); /* black heart suit */
    map.put((char)9830,  "diams");  /* black diamond suit */

    characterToEntityMap =  Collections.unmodifiableMap(map);

  }
}

现在有了该功能,您可以通过以下方式记录您的条目:

// below can be static (to be shared), or the method HtmlEncoder#encodeForHtml can be made static for easier usage.. but just to illustrate
private HtmlEncoder htmlEncoder = new HtmlEncoder(); 

logger.info("I wanted to log param: [{}]", htmlEncoder.encodeForHTML(someVariable));
于 2018-04-12T20:03:04.847 回答