Re: DNSBL and answer id check missing

2008-09-27 Thread Matt Sergeant
On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:
> To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but 
> is not checking the id of the reply received.
> 
> If true this means that an attacker can white- or blacklist any email 
> by sending fake dns replies (only randomisation is source port). 
> Furthermore any other application on same machine also doing dns 
> lookup may end up using same source port and have it's replies being 
> mixed with those plugin DNSBL is waiting for.
> 
> Spamassassin is also using Net::DNS bgsend/bgread, but does verify if 
> the dns answer id matched the request.
> 
> Maybe Net::DNS requires the caller to do the validation, or did I 
> miss something?
> 
> I'm working on a way to test this, but would love to hear others 
> opinion, before doing to much work for maybe nothing :-)

I'm pretty sure you're probably right. The async version uses ParaDNS 
which does do the id checking.

(we should probably do 0x20 checking too, but I think that's beyond my 
skill levels :-/ )


Re: DNSBL and answer id check missing

2008-09-27 Thread Hanno Hecker
Hi Diego,

On Sat, 27 Sep 2008 10:11:15 -0400
Matt Sergeant <[EMAIL PROTECTED]> wrote:
> On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:
> > To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but 
> > is not checking the id of the reply received.
[...] 
> > I'm working on a way to test this, but would love to hear others 
> > opinion, before doing to much work for maybe nothing :-)
> 
> I'm pretty sure you're probably right. The async version uses ParaDNS 
> which does do the id checking.
What about a generic resolver module for qpsmtpd? We're doing quite a
lot of lookups in the different plugins. 
   $ grep -lr bgsend plugins/
   plugins/dnsbl
   plugins/rhsbl
   plugins/dns_whitelist_soft
   plugins/uribl
Plus the non async lookups in require_resolvable_fromhost and the
core.
 
Hanno


Re: DNSBL and answer id check missing

2008-09-27 Thread Diego d'Ambra

Hanno Hecker wrote:

Hi Diego,

On Sat, 27 Sep 2008 10:11:15 -0400
Matt Sergeant <[EMAIL PROTECTED]> wrote:

On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:

To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but
is not checking the id of the reply received.

[...]

I'm working on a way to test this, but would love to hear others
opinion, before doing to much work for maybe nothing :-)

I'm pretty sure you're probably right. The async version uses ParaDNS
which does do the id checking.

What about a generic resolver module for qpsmtpd? We're doing quite a
lot of lookups in the different plugins.
   $ grep -lr bgsend plugins/
   plugins/dnsbl
   plugins/rhsbl
   plugins/dns_whitelist_soft
   plugins/uribl
Plus the non async lookups in require_resolvable_fromhost and the
core.



Excellent idea and especially if the "other places" also need to be fixed.

I'll gladly assist, but maybe somebody with greater knowledge in 
qpsmtpd's inner working should draft some minimum requirements?


Best regards,
Diego d'Ambra


smime.p7s
Description: S/MIME Cryptographic Signature


Re: DNSBL and answer id check missing

2008-09-27 Thread Matt Sergeant
On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:
> To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but 
> is not checking the id of the reply received.
> 
> If true this means that an attacker can white- or blacklist any email 

Thinking more about this - since we don't do any "dnswl" type stuff, it 
doesn't seem that relevant.

All the attacker can do is blacklist more emails, which given the 
timings surely he can only blacklist his own emails?

Just a thought - wondering if this really needs to be fixed.

Matt.


Re: DNSBL and answer id check missing

2008-09-27 Thread Chris Lewis
Matt Sergeant wrote:
> On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:
>> To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but 
>> is not checking the id of the reply received.
>>
>> If true this means that an attacker can white- or blacklist any email 
> 
> Thinking more about this - since we don't do any "dnswl" type stuff, it 
> doesn't seem that relevant.
> 
> All the attacker can do is blacklist more emails, which given the 
> timings surely he can only blacklist his own emails?
> 
> Just a thought - wondering if this really needs to be fixed.

I've extended the async dnsbl plugin to do scoring.  It occured to me a
few days ago that DNSBLs with negative scores (DNSWLs) should be treated
as a hit if they get a timeout or other failure.  This has prompted me
to comment about checking ids too.

The stock one doesn't do scoring, and hence can't do DNSWL.  You want my
code?  You might not like my logging conventions however ;-)


Re: DNSBL and answer id check missing

2008-09-27 Thread Matt Sergeant
On Sat, 27 Sep 2008 20:09:37 -0400, Chris Lewis wrote:
> I've extended the async dnsbl plugin to do scoring.  It occured to me a
> few days ago that DNSBLs with negative scores (DNSWLs) should be treated
> as a hit if they get a timeout or other failure.  This has prompted me
> to comment about checking ids too.
> 
> The stock one doesn't do scoring, and hence can't do DNSWL.  You want my
> code?  You might not like my logging conventions however ;-)

Like I said, the async version doesn't suffer from this bug, because it 
uses ParaDNS which checks the id fields (but doesn't do 0x20 checking - 
I wish I knew enough to be able to extend it to do so).


Re: DNSBL and answer id check missing

2008-09-28 Thread Diego d'Ambra

Matt Sergeant wrote:

On Sat, 27 Sep 2008 13:56:58 +0200, Diego d'Ambra wrote:

To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but
is not checking the id of the reply received.

If true this means that an attacker can white- or blacklist any email


Thinking more about this - since we don't do any "dnswl" type stuff, it
doesn't seem that relevant.

All the attacker can do is blacklist more emails, which given the
timings surely he can only blacklist his own emails?

Just a thought - wondering if this really needs to be fixed.



I made a little change to DNSBL to ensure it randomize scr port and I 
see a major difference.


---snip---
my $res = new Net::DNS::Resolver;
$res->tcp_timeout(30);
$res->udp_timeout(30);
$res->srcport(1024+int(rand(64511)));
---snip---

Anyway the worst is maybe that with current solution, results are very 
wrong - e.g. blacklisting a sender that shouldn't be, but is because no 
checking of received dns replies. The more busy your server is, the more 
it happens - on a server handling around 2 millions SMTP sessions per 
day, I see blacklisting of "valid" sender about every 30 seconds.


I vote for a fix :-)

Best regards,
Diego d'Ambra



smime.p7s
Description: S/MIME Cryptographic Signature


Re: DNSBL and answer id check missing

2008-09-28 Thread Diego d'Ambra

Diego d'Ambra wrote:
[...]


I made a little change to DNSBL to ensure it randomize scr port and I 
see a major difference.




Maybe latest version of Net::DNS does this (after Dan's widely report 
exploit). My box is an older Sarge solution, so others may not see same 
issue.


But even with random src port it will happen - on my system probably 
around 100 times per day.


Best regards,
Diego d'Ambra


smime.p7s
Description: S/MIME Cryptographic Signature


Re: DNSBL and answer id check missing

2008-09-28 Thread Ask Bjørn Hansen


On Sep 28, 2008, at 12:01 AM, Diego d'Ambra wrote:


my $res = new Net::DNS::Resolver;
$res->tcp_timeout(30);
$res->udp_timeout(30);
$res->srcport(1024+int(rand(64511)));


Shouldn't this fix be in Net::DNS::Resolver?


 - ask

--
http://develooper.com/ - http://askask.com/




Re: DNSBL and answer id check missing

2008-09-29 Thread Charlie Brady


On Sun, 28 Sep 2008, Ask Bj?rn Hansen wrote:


On Sep 28, 2008, at 12:01 AM, Diego d'Ambra wrote:


 my $res = new Net::DNS::Resolver;
 $res->tcp_timeout(30);
 $res->udp_timeout(30);
 $res->srcport(1024+int(rand(64511)));


Shouldn't this fix be in Net::DNS::Resolver?


http://search.cpan.org/src/OLAF/Net-DNS-0.63/Changes

Apparently some hjp caused that to be so in June 2007.

Re: DNSBL and answer id check missing

2008-09-29 Thread Charlie Brady


On Mon, 29 Sep 2008, Charlie Brady wrote:



On Sun, 28 Sep 2008, Ask Bj?rn Hansen wrote:


 On Sep 28, 2008, at 12:01 AM, Diego d'Ambra wrote:

>   my $res = new Net::DNS::Resolver;
>   $res->tcp_timeout(30);
>   $res->udp_timeout(30);
>   $res->srcport(1024+int(rand(64511)));

 Shouldn't this fix be in Net::DNS::Resolver?


http://search.cpan.org/src/OLAF/Net-DNS-0.63/Changes

Apparently some hjp caused that to be so in June 2007.


And from http://rt.cpan.org/Public/Bug/Display.html?id=23961:

 Patch made it into release 0.60

Re: DNSBL and answer id check missing

2008-09-29 Thread Chris Lewis
Charlie Brady wrote:
> 
> On Sun, 28 Sep 2008, Ask Bj�rn Hansen wrote:
> 
>> On Sep 28, 2008, at 12:01 AM, Diego d'Ambra wrote:
>>
>>>  my $res = new Net::DNS::Resolver;
>>>  $res->tcp_timeout(30);
>>>  $res->udp_timeout(30);
>>>  $res->srcport(1024+int(rand(64511)));
>>
>> Shouldn't this fix be in Net::DNS::Resolver?
> 
> http://search.cpan.org/src/OLAF/Net-DNS-0.63/Changes
> 
> Apparently some hjp caused that to be so in June 2007.

In 0.60 actually:

Fix rt 23961
Randomized the ID on the queries. Thanks to "hjp" for reporting and
suggesting a fix.

The randomization of the src port is supposed to be handled by the
setting the source port to "0" (default). Overriding the default
or using persistent sockets may be problematic.

Also see:
http://www.potaroo.net/ietf/idref/draft-hubert-dns-anti-spoofing/


Re: DNSBL and answer id check missing

2008-09-30 Thread Ask Bjørn Hansen

How about making qpsmtpd require Net::DNS 0.60 then?


  - ask


Re: DNSBL and answer id check missing

2008-09-30 Thread Peter J. Holzer
On 2008-09-30 01:30:44 -0700, Ask Bjørn Hansen wrote:
> How about making qpsmtpd require Net::DNS 0.60 then?

I've built in a work-around for the problem in older releases of
Net::DNS. But I'm not sure if that still works - from a casual glance at
the source I'd say no, and I'm not sure how it could ever have worked.
Maybe the dnsbl plugin didn't use async at the time?

hp

-- 
   _  | Peter J. Holzer| Openmoko has already embedded
|_|_) | Sysadmin WSR   | voting system.
| |   | [EMAIL PROTECTED] | Named "If you want it -- write it"
__/   | http://www.hjp.at/ |  -- Ilja O. on [EMAIL PROTECTED]


signature.asc
Description: Digital signature


PATCH: Re: DNSBL and answer id check missing

2008-09-28 Thread Diego d'Ambra

Diego d'Ambra wrote:
To me it seems that plugin DNSBL is using Net::DNS bgsend/bgread, but is 
not checking the id of the reply received.



[...]

Attached suggested patch. Large part of it inspired by how Spamassassin 
does it.


Changelog:
 * Added source port randomisation to DNS queries
 * Added id validation of DNS replies

I did notice a small (but important) change from the version I tested 
and latest DNSBL taken from svn - $dom - it actually saves the request 
and later matches the reply against it. So as I say in OP, maybe a storm 
for nothing.


Anyway, I do think id checking is the best solution (if port and id are 
random).


The 0x20 stuff is (also) beyond my skills ;-)

Best regards,
Diego d'Ambra
Index: plugins/dnsbl
===
--- plugins/dnsbl   (revision 947)
+++ plugins/dnsbl   (working copy)
@@ -54,24 +54,31 @@
   my $res = new Net::DNS::Resolver;
   $res->tcp_timeout(30);
   $res->udp_timeout(30);
+  $res->srcport(1024+int(rand(64511)));
 
   my $sel = IO::Select->new();
 
   my $dom;
+  my %packet_ids;
   for my $dnsbl (keys %dnsbl_zones) {
 # fix to find A records, if the dnsbl_zones line has a second field 
20/1/04 ++msp
 $dom->{"$reversed_ip.$dnsbl"} = 1;
 if (defined($dnsbl_zones{$dnsbl})) {
   $self->log(LOGDEBUG, "Checking $reversed_ip.$dnsbl for A record in the 
background");
-  $sel->add($res->bgsend("$reversed_ip.$dnsbl"));
+  $packet = _dns_packet("$reversed_ip.$dnsbl");
+  $packet_ids{ _packet_id($packet) } = 1;
+  $sel->add( $res->bgsend($packet) );
 } else {
   $self->log(LOGDEBUG, "Checking $reversed_ip.$dnsbl for TXT record in the 
background");
-  $sel->add($res->bgsend("$reversed_ip.$dnsbl", "TXT"));
+  $packet = _dns_packet( "$reversed_ip.$dnsbl", "TXT" );
+  $packet_ids{ _packet_id($packet) } = 1;
+  $sel->add( $res->bgsend($packet) );
 }
   }
 
   $self->qp->connection->notes('dnsbl_sockets', $sel);
   $self->qp->connection->notes('dnsbl_domains', $dom);
+  $self->qp->connection->notes('dnsbl_ids', \%packet_ids);
 
   return DECLINED;
 }
@@ -92,6 +99,7 @@
 
   my $sel = $conn->notes('dnsbl_sockets') or return "";
   my $dom = $conn->notes('dnsbl_domains');
+  my $packet_ids = $conn->notes('dnsbl_ids');
   my $remote_ip = $self->qp->connection->remote_ip;
 
   my $result; 
@@ -113,6 +121,11 @@
 
 if ($query) {
   my $a_record = 0;
+
+  #check reply is a valid
+  my $id = _packet_id($query);
+  next unless ( exists( $packet_ids->{$id} ) );
+
   foreach my $rr ($query->answer) {
my $name = $rr->name;
$self->log(LOGDEBUG, "name $name");
@@ -206,6 +219,51 @@
   return DECLINED;
 }
 
+#_dns_packet: private function to create new Net::DNS::Packet object
+#arg0: str with host
+#arg1: str with type
+#ret0: ref to dns packet object
+sub _dns_packet
+{
+my $host = shift;#arg0
+my $type = shift;#arg1
+
+#set default
+$type = 'A' if ( !defined($type) );
+
+#create new dns packet
+my $packet = Net::DNS::Packet->new( $host, $type );
+
+#return packet object
+return ($packet);
+}
+
+#_packet_id: private function that calculate id to match dns replies.
+#arg0: ref to dns packet object
+#ret0: str with id
+sub _packet_id
+{
+my $packet = shift;#arg0
+
+#extract data from packet
+my $header= $packet->header;
+my $id= $header->id;
+my @questions = $packet->question;
+my $ques  = $questions[0];
+
+#calculate id
+if ( defined $ques )
+{
+return join '/', $id, $ques->qname, $ques->qtype, $ques->qclass;
+}
+else
+{
+
+#just return (safe) id to support broken DNS servers that replies with 
on question section
+return $id . "NO_QUESTION_IN_PACKET";
+}
+}
+
 1;
 
 =head1 Usage


smime.p7s
Description: S/MIME Cryptographic Signature