Fastjson just fixed a bug which might cause service down a few days ago. This bug is caused by some mishandling of special character \x which is an escaped character to indicate hexdecimal number. The impact of this bug would be big if the attacker constructs a malicious data which would cause the service down.
The code which causes the issue is in com.alibaba.fastjson.parser.JSONLexerBase#scanString
, when a JSON string is passed in, fastjson would parse the string character by character, when it finds the \x, it would try to process the following two characters automatically and treat them as hexdecimal character.
case 'x':
char x1 = ch = next();
char x2 = ch = next();
int x_val = digits[x1] * 16 + digits[x2];
char x_char = (char) x_val;
putChar(x_char);
break;
However, it might encounter problem if the \x is the last character in the string, since fastjson doesn't do any boundary check and it will always try to read the next two characters and would eventually read EOF(\u001A). Thereafter it continues to read and try to find EOF, but since EOF has been processed already, it will again try to find EOF but never finds it anymore until out of memory occurs.
if (ch == EOI) {
if (!isEOF()) {
putChar((char) EOI);
continue;
}
throw new JSONException("unclosed string : " + ch);
}
The fix made is basically adding some extra check after reading \x.
case 'x':
char x1 = next();
char x2 = next();
boolean hex1 = (x1 >= '0' && x1 <= '9')
|| (x1 >= 'a' && x1 <= 'f')
|| (x1 >= 'A' && x1 <= 'F');
boolean hex2 = (x2 >= '0' && x2 <= '9')
|| (x2 >= 'a' && x2 <= 'f')
|| (x2 >= 'A' && x2 <= 'F');
if (!hex1 || !hex2) {
throw new JSONException("invalid escape character \\x" + x1 + x2);
}
char x_char = (char) (digits[x1] * 16 + digits[x2]);
putChar(x_char);
break;
All versions below 1.2.60 are affected, please upgrade to the latest version if you are still using one of the impacted versions.