Wordpress Comment feature at the beginning and end of Xss
Recently, Wordpress's program commented on the feature of Xss on Weibo, and the repair process is also a wave of twists and turns. Next, let me tell you one by one.
WordPress
This problem is caused by special character truncation. mysql official website describes "The character set named utf8 uses a maximum of three bytes per character and contains only BMP characters". When mysql uses utf8 encoding, the maximum size of a single character is 3 bytes. When the utf8 character exceeds 3 bytes, the truncation effect is generated because the database does not recognize the character. For example, use special characters:
#! SqlUPDATE 'wp _ comments' SET 'comment _ content' = 'stefanie [special character] 555555 'where' wp _ comments'. 'comment _ id' = 12;
The insert result in the database is stefanie. The special characters and the following content are not inserted into the database.
The number of bytes used by the UTF-8 encoding varies with character areas.
Mysql UTF-8 encoding cannot recognize four bytes of characters and can be used within the specified range, as shown in figure
When mysql is encoded as a utf-8mb4 or latin1, such characters can be identified. In addition, when mysql enables strict mode, it will be more strict processing, this issue does not occur if data is blocked before it is effectively stored.
With regard to vulnerability exploitation, Wordpress only allows the tags in the white list and their corresponding attributes in the comments, and ensures the integrity of tags, such as the closure of angle brackets. The Poc is as follows:
#! Html <abbr title = "123 onmouseover = alert (1) Special Character">
It can be seen that onmouseover appears as the title attribute value in double quotation marks. During database insertion, special characters are truncated, And the quotation marks on the right are not inserted. During output, the quotation marks on the left are escaped, so that onmouseover can be successfully parsed.
When mysql type = TEXT, the maximum length of TEXT is 64 KB. When the database is inserted, the part larger than 64 KB is discarded, which also causes a truncation, the type of the field for storing comments in wordpress is TEXT.
Similar to the previous vulnerability, this vulnerability only has different truncation methods. The poc is as follows:
#! Html <abbr title = "123 onmouseover = alert (1) Add useless characters to 64KB">
The Truncation effect is as follows:
This poc is only used by IE, while the Klikki Oy team has provided POC, chrome, IE, and firefox compatible with multiple browsers.
Stefaniea title = 'x onmouseover = alert (unescape (/hello % 20 world/. source ))
Style = position: absolute; left: 0; top: 0; width: 5000px; height: 5000px can be truncated with special characters or lengths here '> a>
4.2.1 version is mainly for the length truncation repair, added the length limit of each type of fields in the database in the wp-shortdes \ wp-db.php get_col_length function, and compared with the length of the incoming data.
protected function process_field_lengths( $data, $table ) {foreach ( $data as $field => $value ) { if ( '%d' === $value['format'] || '%f' === $value['format'] ) { // We can skip this field if we know it isn't a string. // This checks %d/%f versus ! %s because it's sprintf() could take more. $value['length'] = false; } else { $value['length'] = $this->get_col_length( $table, $field ); if ( is_wp_error( $value['length'] ) ) { return false; } } if ( false !== $value['length'] && mb_strlen( $value['value'] ) > $value['length'] ) { return false; } $data[ $field ] = $value; } return $data;}$ Value ['length'] comes from get_col_length. the maximum length of the text type is 65535 bytes. The mb_strlen ($ value ['value']) function counts the number of characters, the measurement units of the two values are different. One is the number of bytes and the other is the number of characters.
In the function "mb_strlen", the number of multi-byte characters is 1. In different encodings, the size of a character can be multiple bytes (Multi-byte characters), so we can construct a string, if the number of characters is less than 65535, and the number of characters in a string is greater than 65535, the following conditions are met:
if ( false !== $value['length'] && mb_strlen( $value['value'] ) > $value['length'] ) { return false;}
When php inserts data into the database, the string is truncated because the number of bytes exceeds the length of the text type and the previous xss can be reused.
Overall bug fixes in WordPress 4.2.2
Two variables are introduced in version 4.2.2:
$ Truncate_by_byte_length: whether to perform byte length verification $ needs_validation: whether multi-byte character compliance verification and length verification wp422/wp-between des/wp-db.php 2626 rows
if ( $truncate_by_byte_length ) { mbstring_binary_safe_encoding(); if ( false !== $length && strlen( $value['value'] ) > $length ) { $value['value'] = substr( $value['value'], 0, $length ); } reset_mbstring_encoding(); if ( ! $needs_validation ) { continue; }}
This solution solves the problem of comparing the actual length and the specified length with the mb_strlen in 4.2.1. Instead, it uses strlen to measure the length and cut the extra-long part, therefore, xss caused by bypass patch 4.2.1 is intercepted.
$regex = '/ ( (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 | [\xE1-\xEC][\x80-\xBF]{2} | \xED[\x80-\x9F][\x80-\xBF] | [\xEE-\xEF][\x80-\xBF]{2}';if ( 'utf8mb4' === $charset ) { $regex .= ' | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 | [\xF1-\xF3][\x80-\xBF]{3} | \xF4[\x80-\x8F][\x80-\xBF]{2} ';}$regex .= '){1,40} # ...one or more times ) | . # anything else /x';$value['value'] = preg_replace( $regex, '$1', $value['value'] );if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) { $value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' );}continue;}
We can see that for utf8 encoding, only the UTF-8 characters in the range are less than or equal to 3 bytes. After the UTF-8 characters are extracted, they are re-confirmed based on the encoding length of the current multi-byte characters. This fix is used to insert four-byte UTF-8 characters into the database for truncation and other special characters Truncation in analyticdb 4.2 or later versions.