Java 后门-unicode编码
Java代码默认可以直接全是unicode编码: 假设有如下未编码Java代码:
public class Test { public static void main(String[] args) { System.out.println(1); } }
编码后的Java代码:
\u0070\u0075\u0062\u006c\u0069\u0063 \u0063\u006c\u0061\u0073\u0073 \u0054\u0065\u0073\u0074 \u007b \u0070\u0075\u0062\u006c\u0069\u0063 \u0073\u0074\u0061\u0074\u0069\u0063 \u0076\u006f\u0069\u0064 \u006d\u0061\u0069\u006e\u0028 \u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d \u0061\u0072\u0067\u0073\u0029 \u007b \u0053\u0079\u0073\u0074\u0065\u006d.out.println\u0028\u0031\u0029\u003b \u007d \u007d
这段代码输出的结果是1,为了以示区别代码中间故意写了十进制的.out.println。 既然知道即便是使用unicode编码等效于普通的十进制代码,那么首先想到的肯定是可以用来隐藏webshell或者绕过WAF或补丁继续攻击Struts。 某些Struts2关键字绕过:
Jsp里面一样可以使用unicode编码去替代关键字:
既然知道有这样的恶意攻击的可能性,那么应该怎样去修复此类问题呢?当然是先把unicode转码了。
/** * unicode 转换成 utf-8 * * @param str * @return */ public static String unicodeToUtf8(String str) { if(str==null||str.length()<1){ return str; } char aChar; int len = str.length(); StringBuffer outBuffer = new StringBuffer(len); for (int x = 0; x < len;) { aChar = str.charAt(x++); if (aChar == '\\') { aChar = str.charAt(x++); if (aChar == 'u') { int value = 0; for (int i = 0; i < 4; i++) { aChar = str.charAt(x++); switch (aChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = (value << 4) + aChar - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': value = (value << 4) + 10 + aChar - 'a'; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': value = (value << 4) + 10 + aChar - 'A'; break; default: throw new IllegalArgumentException( "Malformed \\uxxxx encoding."); } } outBuffer.append((char) value); } else { if (aChar == 't') aChar = '\t'; else if (aChar == 'r') aChar = '\r'; else if (aChar == 'n') aChar = '\n'; else if (aChar == 'f') aChar = '\f'; outBuffer.append(aChar); } } else outBuffer.append(aChar); } return outBuffer.toString(); }
Apache-commons-lang同样也提供了对应的转换:
import org.apache.commons.lang.StringEscapeUtils; public class Test { public static void main(String[] args) { String a="\\u0048\\u0065\\u006C\\u006C\\u006F"; String b = StringEscapeUtils.unescapeJava(a); System.out.println(b); } }