f.zz.de
posts /

23 year old Bug found in LWP::Useragent

Posted Thu Nov 12 13:41:56 2020 Florian Lohoff in

Finding a decade old bug in some piece of Software which is used in millions of projects is not an every day event and i was astonished nobody really found this.

I was trying to implement HTTP Digest auth based on AnyEvent::HTTP which is an asynchronous event framework. So i had a look at how LWP::Useragent (Now libwww-perl) handles this.

And i found this piece of code. I was not able to find the corresponding RFC for the message-digest request parameter but it turned out, its broken anyway.

So this code supposedly calculated some kind of MD5 on the full PUT/POST request body. But it turns out there is a md5->reset just before exporting the md5 message digest. So the md5 object returns the null md5 digest as the internal state gets resetted.

This code wastes some cpu cycles and cache hits for generating a complicated md5 hash on the request body, and then drops it to present a null md5.

 63     if($request->method =~ /^(?:POST|PUT)$/) {
 64         $md5->add($request->content);
 65         my $content = $md5->hexdigest;
 66         $md5->reset;
 67         $md5->add(join(":", @digest[0..1], $content));
 68         $md5->reset;
 69         $resp{"message-digest"} = $md5->hexdigest;
 70         push(@order, "message-digest");
 71     }

I had a quick look at the git repository for LWP::Useragent which shows that the line has been there since the first import which was in 1997.

98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 63)     if($request->method =~ /^(?:POST|PUT)$/) {
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 64)         $md5->add($request->content);
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 65)         my $content = $md5->hexdigest;
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 66)         $md5->reset;
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 67)         $md5->add(join(":", @digest[0..1], $content));
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 68)         $md5->reset;
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 69)         $resp{"message-digest"} = $md5->hexdigest;
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 70)         push(@order, "message-digest");
98c2a2729 (Gisle Aas      1997-12-01 19:12:06 +0000 71)     }

I guess the whole code for PUT/POST handling can be removed as the message-digest is not mentioned in the default Digest Auth RFCs, nor has it ever contained a valid value.

Here is the Debian bugreport #974572