Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 99814
Status: rejected
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: tlhackque [...] yahoo.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 0.80_2
Fixed in: (no value)



Subject: Undeserved Insecure dependency error with named nameservers
I patched die() to confess() to debug this (new since 0.6?): Error: ====== Insecure dependency while running with -T switch at /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread-multi/Net/DNS/Resolver/Base.pm line 852 Net::DNS::Resolver::Base::send_udp('Net::DNS::Resolver=HASH(0x9df8f9c)', 'Net::DNS::Update=HASH(0x9de5604)', '\x{fd}\x{d9}(\x{0}\x{0}\x{1}\x{0}\x{0}\x{0}\x{1}\x{0}\x{1}\x{5}litts\x{3}net\x{0}\x{0}\x{6}\x{0}\x{1}\x{c0}\x{c}\x{0}\x{10}\x{0}\x{fe}\x{0}\x{0}\x{0}\x{0}\x{0}\x{7}\x{6}gobble\x{11}internal_view_...') called at /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread-multi/Net/DNS/Resolver/Base.pm line 511 Net::DNS::Resolver::Base::send('Net::DNS::Resolver=HASH(0x9df8f9c)', 'Net::DNS::Update=HASH(0x9de5604)') called at {...}dnsupdate.cgi line 2542 main::doUpdate('delete', 'internal', 'litts.net.', '', 600, 'TXT', 'gobble', 1, 1, ...) called at {...}dnsupdate.cgi line 726 main::processPost() called at {...}dnsupdate.cgi line 317 Analysis: ========= The failure happens if I specify the nameserver as 'ns1.litts.net', but not if I use the IPv4 or IPv6 address associated with that server. The query being sent happens to be a (TSIG-signed) UPDATE to delete (a non-existent) TXT record. Obviously, I have IPv6 support. The root cause is that Socket6::getaddrinfo returns tainted data. modver Socket6 Socket6 => 0.25 Patch: ====== --- /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread-multi/Net/DNS/Resolver/Base.pm~ 2014-10-24 04:15:16.000000000 -0400 +++ /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread-multi/Net/DNS/Resolver/Base.pm 2014-10-26 08:26:15.000000000 -0400 @@ -772,11 +772,11 @@ if ( scalar(@res) < 5 ) { die("can't resolve \"$ns_address\" to address"); } - push @ns, [$ns_address, $dst_sockaddr, $sockfamily]; + push @ns, [_untaint( $ns_address, $dst_sockaddr, $sockfamily )]; } else { next NSADDRESS unless ( _ip_is_ipv4($ns_address) ); my $dst_sockaddr = sockaddr_in( $dstport, inet_aton($ns_address) ); push @ns, [$ns_address, $dst_sockaddr, AF_INET]; Host OS is Linux (an old kernel).
From: rwfranks [...] acm.org
This *not* a bug, it is a feature, and a Perl feature at that. The whole point of taint is to ensure that you can not use data derived from outside your program to affect something else outside your program. The present position is the result of a lengthy discussion some months ago, and is unlikely to change. See RT#96608 and perldoc perlsec. Change in 0.79 was to ensure that taint is detected reliably, and in the right places. On Sun Oct 26 08:37:27 2014, tlhackque wrote: Show quoted text
> I patched die() to confess() to debug this (new since 0.6?): > > Error: > ====== > Insecure dependency while running with -T switch at > /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread- > multi/Net/DNS/Resolver/Base.pm line 852 > Net::DNS::Resolver::Base::send_udp('Net::DNS::Resolver=HASH(0x9df8f9c)',
Subject: Unable to pass nameserver by name with -T
From: tlhackque [...] yahoo.com
On Sun Oct 26 10:50:14 2014, rwfranks@acm.org wrote: Show quoted text
> This *not* a bug, it is a feature, and a Perl feature at that. >
I know the Perl taint feature and its purpose very well. In this case, after looking at RT966-8 I still believe this is a bug. Show quoted text
> The whole point of taint is to ensure that you can not use data > derived from outside your program to affect something else outside > your program.
Yes. However, in the case that I provided, the input to Net::DNS is the literal string 'ns1.litts.net'. This is NOT tainted. The taint is coming from Socket6's translation to a numeric address, internal to Net::DNS. Yes, this is coming from the DNS, which is external. But we can trust the answer for the usage here. There is no way for me to avoid this error by using different arguments. Net::DNS is causing untainted data to become tainted. This means that with -T, one can't pass a nameserver by name - which is an unacceptable regression from 0.66. Note that the current (unpatched) code attempts to deal with names translating to multiple addresses. If one can't pass a name, this is pointless. And this is not a reason to turn off -T for the containing program. So, what harm can come from untainting the result of Socket6's lookup? The usual issue would be if we took the result and passed it to a shell via system() or qx - and the result included backticks. Or used it as a filename, and did a careless open. But that isn't happening here. If Socket6 can return something other than a valid IP address, it's broken. All that's happening is that the result is going to send(). And if there's something wrong with the address, send() will fail. One could argue that a better patch is to only untaint the argument to send(), as the NS can be passed back to the user via answerfrom() - and that might be misused....which is a bit trickier as at that point, we don't know if the nameserver was passed by name or by address. Net::DNS can complain if the input nameserver (address, name) is tainted. But not when it takes untainted input and unavoidably taints it. Show quoted text
> The present position is the result of a lengthy discussion some months > ago, and is unlikely to change. See RT#96608 and perldoc perlsec. > > Change in 0.79 was to ensure that taint is detected reliably, and in > the right places. >
This is not a 'right place' for the reasons given. If you don't like my change, please provide an alternative that allows me to pass a nameserver (that has multiple A/AAA records) by name when running under -T. Show quoted text
> > On Sun Oct 26 08:37:27 2014, tlhackque wrote:
> > I patched die() to confess() to debug this (new since 0.6?): > > > > Error: > > ====== > > Insecure dependency while running with -T switch at > > /usr/lib/perl5/site_perl/5.8.8/i686-linux-thread- > > multi/Net/DNS/Resolver/Base.pm line 852 > > Net::DNS::Resolver::Base::send_udp('Net::DNS::Resolver=HASH(0x9df8f9c)',
From: rwfranks [...] acm.org
On Sun Oct 26 13:36:24 2014, tlhackque wrote: Show quoted text
> > The whole point of taint is to ensure that you can not use data > > derived from outside your program to affect something else outside > > your program.
> > Yes. However, in the case that I provided, the input to Net::DNS is > the literal string > 'ns1.litts.net'. This is NOT tainted.
No, but the IP address is the result of a query to one or more internet nameservers. That IS tainted. Show quoted text
> > Yes, this is coming from the DNS, which is external. But we can trust > the answer for the usage here.
Net::DNS is unable to read your mind. Show quoted text
> This means that with -T, one can't pass a nameserver by name - which > is an unacceptable regression from 0.66.
This only appears to be a regression because the UDP socket code does not detect taint, unlike a TCP socket. When that was pointed out an explicit test was inserted into the resolver to make the behaviour protocol independent. Mark Martinec and I have been through all this in RT96608. The present design is the result of that collaboration and is NOT going to change without much more substantial reasoning than you have displayed so far. The solution to your problem is in there. I strongly suggest that you read and understand it before commenting further.
Yes, safety vs convenience... always a hairy subject. I haven't tried myself yet, but I assume the name came from an environment variable or from a config file which wasn't explicitly passed on Resolver instantiation, yes? Thanks for reporting all the same! -- Willem