Showing posts with label bugs. Show all posts
Showing posts with label bugs. Show all posts

Sunday, February 7, 2010

When Standards Collide

I can't help but shake my head in disappointment every time I run across some specification that is blatantly in violation of the standards it is built on. When I encounter a specification published by an ostensibly-reputable professional organization that contradicts my understanding of the underlying protocols, at first I'm confused. Is my understanding faulty? My memory bad (hint: it is)? Is there a new RFC that updated the protocol when I wasn't looking?

As a recent example, I finally got my hands on the WRIX Interconnect 1.03 specification from the Wireless Broadband Alliance. In which, they specify that partner ISPs must support "passwords up to 253 characters which contain a mixture of alphabetic, numeric, and special characters"; this is written in the comments for the the User-Password attribute in a RADIUS Access-Request packet.

There are two problems with this text that I'm amazed industry professionals did not correct (assuming they noticed):

  1. RFC 2865 section 5.2 clearly states that the maximum length of the User-Password attribute is 130 octets, including the 2-byte attribute header. In other words, the encrypted password text cannot be longer than 128 octets. If this were the only issue, I'd be inclined to believe that the 128 octet limit has been relaxed in a later RFC.

  2. Which leads to the second issue: RFC 2865 says the *encrypted* password text cannot be longer than 128 octets. Section 5.2 also lays out the encryption algorithm, which is a 16-byte block cipher. Being a block cipher, the password plaintext is padded out to a multiple of 16 bytes before the encryption is applied. Which means that a 7 octet password will encrypt to 16 octets of encrypted text. The 253 character password specified by WRIX would encrypt to 256 octets of encrypted text. RADIUS allocates 8 bits per attribute to represent the length of that attribute in octets, including the attribute's 2-byte header. So, if you have 256 octets of encrypted text, the total length of the attribute would be 258 octets.



So, in order to comply with the WRIX Interconnect 1.03 specification, it would appear you are required to violate both RFC 2865 and physics (to get 258 values represented with just 8 bits).

What baffles me is that I would have expected the difficulty of implementing the specification as written would have become obvious in compatibility testing. Surely someone has written unit tests based on the spec to test their implementation. At least once. Right? Right?

Anyway, I imagine the intent of the specification's authors was only to violate RFC 2865 and leave the violation of physics to the hardware guys. It looks like they wanted partner ISPs to allow the longest password representable by the User-Password attribute, ignoring the 128-octet stated limit. Since the encryption algorithm always produces encrypted text that is a multiple of 16-bytes in length and the longest encrypted text that can be stored in the User-Password attribute is 255 - 2 = 253 octets, the question is what is the largest multiple of 16 less than or equal to 253?

240. 240 octets.

Any plaintext 241 octets long or longer will encrypt to 256 bytes of encrypted data, which is not representable by a RADIUS User-Password attribute. So, a more reasonable specification would require implementers to support "passwords up to 240 characters which contain a mixture of alphabetic, numeric, and special characters."

Maybe in revision 1.04.

Monday, July 27, 2009

Subtle error in RFC 3665 "SIP Basic Call Flow Examples"

RFC 3665 is simply a collection of SIP call flow examples for reference to implementers. However, I noticed what appears to be a small error in section 3.2 "Session Establishment Through Two Proxies" with the digest values.

In step F2 "407 Proxy Authorization Required Proxy 1 -> Alice", the proxy responds with a Proxy-Authenticate header containing the nonce value "f84f1cec41e6cbe5aea9c8e88d359". However, in F4 "INVITE Alice -> Proxy 1", where the user agent should send back the same nonce value to the proxy server along with the calculated digest, it instead sends the nonce "wf84f1ceczx41ae6cbe5aea9c8e88d359". Clearly, this is a typographical error as the nonces are identical except for the leading "w".

A cursory scan of the rest of the examples in RFC 3665 did not turn up any more mismatched nonce values. The "wf84f1ceczx41ae6cbe5aea9c8e88d359" value appears in other call sequences involving proxy authentication while the "f84f1cec41e6cbe5aea9c8e88d359" value never appears again, implying the nonce value with the "w" character prefixed should be the "correct" value.

Interestingly, while the other nonce values used in examples appear to be 32-character hexadecimal representations of 128-bit values, the "wf84f1ceczx41ae6cbe5aea9c8e88d359" value does not fit this pattern as it is both 33-characters long and "w" is not a valid hexadecimal digit. Which leads me to believe that the "f84f1cec41e6cbe5aea9c8e88d359" value is actually the correct nonce value in the "407 Proxy Authorization Required Proxy 1 -> Alice" call flow and that the other instances where the "w"-prefixed value appears are just the same typographical error replicated via copy-and-paste.

What I don't know, and would be interested in finding out, is whether the calculated digest result value examples were calculated with the "f84f1cec41e6cbe5aea9c8e88d359" nonce or with the "w"-prefixed version. Unfortunately, the RFC does not tell us what password values they used to calculate the digests, so I cannot answer that question myself.

Monday, August 6, 2007

One-liner to crash IE6

A Japanese fellow going by the name Hamachiya2 has stumbled upon one line of HTML/CSS code that crashes IE6. The magic line is:

<style>*{position:relative}</style><table><input></table>

You can try it yourself at: http://hamachiya.com/junk/ie_crash.html.

Of course, if you are running IE6 or anything that embeds IE6 as a component, you can expect it to crash. All other browsers appear to render the code just fine.

I think I may have just found a new signature. :)

Update 2007/08/07 01:16pm:
Zeth wrote in that he noticed that IE7 pukes on the same line of HTML; it just waits until you try to visit a different page before it crashes.

Friday, June 15, 2007

PowerPoint centimeters

Me, I'm 5'10" tall. That would be approximately 178 centimeters. Or 168 PowerPoint centimeters.

Unfortunately, Google Calculator doesn't recognize PowerPoint centimeters as a unit yet so you'll need to whip out a calculator and do the conversion yourself:
1 inch = 2.4 PowerPoint centimeters
1 centimeter = 1.0583 PowerPoint centimeters

How did this unit come about? From Microsoft's Knowledge Base article 189826:
To improve its usability, PowerPoint slightly misdefines the size of a centimeter to make the invisible gridlines fall at convenient points on the ruler. With this conversion, there are 5 picas per centimeter and the gridlines fall at very convenient points on the ruler. So convenient, in fact, that working in the metric system is really easier than working in the English system.

Apparently, the gridlines in PowerPoint 97 were on pica boundaries, which aligned nicely to the inch ruler since a pica is defined as 1/6 of an inch. But if you were to use PowerPoint 97 in one of those metric-using nations, the pica gridlines didn't fall on convenient points on the centimeter ruler. Solution: redefine centimeters to be an even multiple of picas, which are defined to be an integral fraction of an inch. In other words, Microsoft redefined the meaning of centimeters in PowerPoint such that a centimeter was defined in terms of an inch.

Microsoft had the arrogance to redefine an international standard measurement unit to fit their software's user interface. What makes the arrogance all the more palpable is that their Knowledge Base article acknowledging the existence of PowerPoint centimeters doesn't sound the least bit apologetic for the discrepancy.

Personally, I kind of prefer PowerPoint centimeters to metric centimeters: 168 PowerPoint centimeters tall is a lot easier to remember to an American like me than 177.8 metric centimeters tall is. <wink>

Update 2007/06/15 03:45pm:
My wife pointed out that apparently Microsoft redefined the size of a pica too: their Knowledge Base claims 12 picas to an inch, whereas there are supposed to be only 6 to an inch. I would like to suggest the name "PowerPicas" for these new pint-sized picas. That would make me 840 PowerPicas tall.

Thursday, April 19, 2007

What open source is all about

Ian Bicking just confirmed that he has fixed the bug I previously reported in Paste:
I think I did what you suggested in r6482 (just removed the regex check)

Talk about fast turnaround. I only mentioned the bug to Ian today and it was fixed almost immediately. You don't see that kind of response time everywhere. Thanks Ian!

Wednesday, April 4, 2007

Security is a process

Let's say, hypothetically, you had a library of C code which implemented some function, frobulate(const struct foo *fooarray, size_t numfoos). For the sake of discussion, it really isn't important what frobulate does, lets just say that it performs an action on an array of structures. Now, it turns out that it is pretty common to call frobulate() with just a single structure, so we provide a helper function frobulateOne(const struct foo *foop).
I realize this is silly, but bear with me.

Now, lets say a developer using your library finds that passing a malformed structure to frobulateOne causes it to crash. You identify that there is buffer overflow in your library code that is caused by not properly validating the contents of the structure passed as an argument. How do you fix it?

You might add some additional validation to frobulateOne(), but certainly you would fix frobulate() to validate each any every structure. After all, frobulateOne() just turns around and calls frobulate() to do the real work. Obviously, it is necessary to validate the input to frobulate().

In fact, it is so obvious you are probably wondering why I'm wasting my time mentioning it.

Because somehow Microsoft, who made a high-profile effort to fix security bugs in their flagship product, screwed it up. When it was found in November 2004 that malformed animated cursors could lead to a buffer overflow, Microsoft issued a fix (MS05-002) 4 months later. The fix issued added input validation to the LoadCursorIconFromFileMap() function. Being highly-security conscious, you would assume that in that four months developing a fix, someone would have noticed that LoadCursorIconFromFileMap() is a wrapper that loads the icon data from the disk and calls LoadAniIcon() to actually process the data. Or that, after discovering such a bug in one piece of code, they would have their crack team of security experts scour through related code looking for similar bugs.

But, sadly, they did not. Earlier this week, Microsoft had to scramble to issue new patches applying the exact same input validation they added to two years ago to LoadCursorIconFromFileMap() to LoadAniIcon(). Independent security researchers had found Microsoft's obvious error before they did and hackers were exploiting the vulnerability to take control of Windows users' machines.

Of course, the IT press is encouraging everyone to apply Microsoft's patches ASAP due to the severity of the bug. Microsoft's detractors will hold it up as another example of how Microsoft's Windows operating system is inherently more insecure than their favorite OS.

But what strikes me is not the severity of the bug itself, but what it says about the internal processes at Microsoft. This latest security flaw is not the result of some previously-undiscovered bug -- it is the direct manifestation of Microsoft's failure to properly address the exact same flaw two years ago. And the correct solution, as I hope my little example at the start of this post demonstrated, should have been obvious from the start.

I'll avoid the debate of whether Microsoft's development processes are fundamentally flawed; I've never worked there so I wouldn't know. However, this bug should make it abundantly clear that Microsoft's processes for addressing known security issues are not just flawed, but practically non-existent. No organization employing professional software engineers could have missed the proper fix two years ago, much less an organization that professes to take security issues seriously. Microsoft claims to "have dedicated staff whose job it is to perform root-cause analysis of defects". Somehow I don't believe it. Or, if they do, I should expect they'll be hiring a new group soon.

Update 2007/04/06: Apparently I'm not the only one who is baffled how Microsoft could fail to have proactively fixed this recent bug and still profess to be focused on making Windows more secure.

Monday, April 2, 2007

Python: HTTP Accept-Language header parsing

The more I dig through the code, the more Paste is growing on me.

However, I noticed a few nights ago that Paste's Accept-Language header parsing is subtly non-RFC-compliant (sorry JJ!). The issue is that the regular expression it uses (from paste.httpheaders class _AcceptLanguage):
languageRegEx = re.compile(r"^[a-z]{2}(-[a-z]{2})?$", re.I)
does not match all language tags defined by section 3.10 of RFC 2616. Admittedly, it matches all language tags in common usage, but fails to comply with the letter of RFC 2616 in that it fails to match tags such as en-cockney, i-cherokee, or x-pig-latin. The RFC says:
any two-letter primary-tag is an ISO-639 language abbreviation
and any two-letter initial subtag is an ISO-3166 country code.

Note that it does not mandate that all primary-tags and subtags must be two-letters in length nor does it restrict the number of subtags to the set of zero and one. It just says that if they are two-letters, they have the meanings cited. In fact, the augmented BNF grammar only says the primary-tag is one or more 8-bit alphabetic characters followed by 0 or more subtags, each consisting of one or more 8-bit alphabetic characters.

Luckily, the problem regex isn't integral to the parsing algorithm and can be safely removed. As such, all that appears to be necessary to bring to code into RFC 2616 compliance is to remove the definition of languageRegEx as well as the following two lines:
if not self.languageRegEx.match(lang):
continue
With that obscure bug fixed, now you are ready to start serving Upper Sorbian, Cockney, or even Klingon localized versions of your Paste-powered web site.

(Now if we could only get the httpheaders code into the python standard library so everyone can get the benefit of bug-free parsing, whether they use Paste or not.)