View Ticket
Not logged in
2023-02-15
16:51 Ticket [885c86a9a0] convertfrom utf8 breaks for 4 byte utf encodings status still Open with 3 other changes artifact: 15103e545c user: jan.nijtmans
2020-04-19
23:00
We know that Tcl 8.5.19 suffers from [67aa9a2070] -- accepting overlong. check-in: f54a350e47 user: dgp tags: dgp-utf-explore
2020-04-15
17:04 New ticket [5e6346a252] Tcl_UtfPrev does not account for rejecting overlong sequences. artifact: dabcf9db98 user: dgp
2017-06-06
09:23
Follow-up to [67aa9a2070]: Use uppercase consistantly, slight optimization in character tests, comme... check-in: 5b20178e5a user: jan.nijtmans tags: core-8-6-branch
09:02
[67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input as documented. check-in: 3998688718 user: jan.nijtmans tags: core-8-5-branch
2017-06-05
17:15
[67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input as documented. check-in: 8e28fedaa0 user: dgp tags: trunk
17:02 Ticket [67aa9a2070] Security: Invalid UTF-8 can inject unexpected characters status still Closed with 4 other changes artifact: a4249da949 user: dgp
16:56 Ticket [67aa9a2070]: 5 changes artifact: 566512e7c1 user: dgp
16:56
[67aa9a2070] Tcl_UtfToUniChar returns single byte for invalid UTF-8 input as documented. check-in: 164b69bdfd user: dgp tags: core-8-6-branch
2017-06-02
08:17
Fix [67aa9a207037ae67f9014b544c3db34fa732f2dc|67aa9a2070]: Security: Invalid UTF-8 can inject unexpe... check-in: e0f22bedca user: jan.nijtmans tags: bug-67aa9a2070
2017-05-31
14:02 Ticket [67aa9a2070] Security: Invalid UTF-8 can inject unexpected characters status still Closed with 5 other changes artifact: 13db1deba7 user: sebres
13:35 Ticket [67aa9a2070]: 4 changes artifact: 69f6ee2930 user: jan.nijtmans
13:19 Ticket [67aa9a2070]: 5 changes artifact: 8108568ba8 user: jan.nijtmans
12:31 Ticket [67aa9a2070]: 5 changes artifact: 36fdb1d873 user: dgp
12:08 Closed ticket [67aa9a2070]. artifact: ee73284441 user: jan.nijtmans
12:05
Fix [67aa9a207037ae67f9014b544c3db34fa732f2dc|67aa9a2070]: Security: Invalid UTF-8 can inject unexpe... check-in: f1b9559259 user: jan.nijtmans tags: sebres-8-6-clock-speedup-cr1
11:44 New ticket [67aa9a2070] Security: Invalid UTF-8 can inject unexpected characters. artifact: a38c4b4972 user: jan.nijtmans

Ticket UUID: 67aa9a207037ae67f9014b544c3db34fa732f2dc
Title: Security: Invalid UTF-8 can inject unexpected characters
Type: Bug Version: 8.6
Submitter: jan.nijtmans Created on: 2017-05-31 11:44:32
Subsystem: 44. UTF-8 Strings Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2017-06-05 17:02:17
Resolution: Fixed Closed By: dgp
    Closed on: 2017-06-05 17:02:17
Description:

Example:

   encoding convertfrom utf-8 \x3c\xc0\xbc
   <<
So, the byte sequence \xc0\xbc produces the same character as \x3c. This is know as overly long UTF=8 sequences, and it is dangerous. For example, a HTML file can be constructed containing the sequence "\xc0\xbcscript ...". When Tcl reads this file and outputs it again in UTF-8, the sequence becomes "<script ...", which can actually run something!

Most UTF-8 decoders handle this the same as other invalid UTF-8 sequences: Just output valid UTF-8 corresponding with the individual bytes. The original example then becomes:

   encoding convertfrom utf-8 \x3c\xc0\xbc
   <À¼

The characters "À¼" are 'safe' in HTML, since no characters > \x7f have a special meaning.

User Comments: dgp added on 2017-06-05 17:02:17:
See also

https://core.tcl.tk/tcl/tktview?name=2564363

dgp added on 2017-06-05 16:56:12:
From TCLCORE:

"Tcl_UtfToUniChar() is documented as:
    <http://core.tcl.tk/tcl/artifact?ln=142-145&name=eaf0d058d9f17309>
Text:
    If the input is not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will
    store the first byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar
    between 0x0000 and 0x00ff and return 1.

This turns out to be a lie: Some byte-sequences, which are clearly
non-proper according to the UTF-8 standard, this function returns
something else than the first byte. That's what I'm proposing to fix."

Thank you, that's the clear explanation I needed to see.  This is indeed
a good change to make.  Merged to core-8-6-branch. Will further merge
forward.

Seems this has been contrary to documentation since it arrived
in Tcl 8.1.  Possible explanation is a changing standard of
what is considered "proper UTF-8 format" and whether multiple
encodings are permissible for the same codepoint?  Clear standard
now is that they are not.

One thing that might still be improved (?) is to mention the
exception \xc0 \x80 encoding for U+0000 that the routine
explicitly makes.

sebres added on 2017-05-31 14:02:31:

The security people (I hope I may say belonging to those to some extent) say - it is rather undefined behavior, but not directly a kind of vulnerability in sense of "tcl has possible security-leak with grave impact".

The fact is: if you read something from foreign input and want to escape/validate it somehow, you should act in the target encoding (and never with the raw input). This is one of the first rules, that will be applied by security-audits.

I mean that it should be converted previously... Or twice (before and hereafter).

Just as example:


% puts [set buf "\xc0\xbcscript ..."]
À¼script ...
% set buf [encoding convertfrom utf-8 $buf]; #** important before validate **
<script ... 
% if {[regexp -nocase {<script} $buf]} {error NOT-PERMITTED} 
NOT-PERMITTED 
</code>

Just as some thoughts for your info. I'm doing already too much sec-audits (including the source code).

Don't misunderstand my amount, I'm not with Don here (in contrary the changes looks good to me), but... But I do not see this necessarily as argument for theoretical vulnerability to fix ASAP. But also I don't see still any reasons to revert it ASAP.


jan.nijtmans added on 2017-05-31 13:35:55:

Excerpt from the wiki:

More recent converters translate the first byte of an invalid sequence to a replacement character and continue parsing with the next byte. These error bytes will always have the high bit set. This avoids denial-of-service bugs, and it is very common in text rendering such as browser display, since mangled text is probably more useful than nothing for helping the user figure out what the string was supposed to contain. Popular replacements include:

- The replacement character "�" (U+FFFD) (or EF BF BD in UTF-8)
- The invalid Unicode code points U+DC80–U+DCFF where the low eight bits are the byte's value.[16] Sometimes it is called UTF-8B[17]
- The Unicode code points U+0080–U+00FF with the same value as the byte, thus interpreting the bytes according to ISO-8859-1[citation needed]
- The Unicode code point for the character represented by the byte in CP1252,[citation needed] which is similar to using ISO-8859-1, except that some characters in the range 0x80–0x9F are mapped into different Unicode code points. For example, 0x80 becomes the Euro sign, U+20AC.

Tcl uses the 3th possibility for all other invalid sequences it checks for, so it makes most sense to do the same here.


jan.nijtmans added on 2017-05-31 13:19:58:

I think the UTF-8 standard is absolutely clear about what are invalid byte sequences and what not! Tcl already handles many invalid byte sequences, just these ones have always been forgotten.

See: https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences

Currently we only handle 1-3.

Actually, I thought that Tcl already handled this long ago. Fossil has a function invalid_utf8() which does the same checks.

Please talk to security people, it's embarrassing not to handle this nowadays, really!


dgp added on 2017-05-31 12:31:41:
This is far too big a change to make without talking about it.

Please revert.

jan.nijtmans added on 2017-05-31 12:08:46:
Fixed in core-8-6-branch and trunk