[TOOL] SSL Capable NetCat



The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html

- - - - - - - - -



SSL Capable NetCat
------------------------------------------------------------------------


SUMMARY



DETAILS

You all know what is netcat (written by Hobbit in 1996), how to use it and
that it should have been integrated in all UNIX systems a long time ago.
netcat lacked some features, and I tried to add them in this Perl version.
For example, SSL support, TCP and UDP proxying and IPv4/IPv6 proxying
features.

Tool source:
#!/usr/bin/perl
#
# $Id: scnc 13 2008-04-27 10:53:59Z gomor $
#

our $SupportSsl = 0;
our $SupportTelnet = 0;
our $SupportIpv6 = 0;

package Scnc;
use warnings; use strict;

use Carp;
use IO::Socket::INET;
use IO::Select;

eval("use IO::Socket::SSL;");
$@ ? warn("*** IO::Socket::SSL module not found, SSL support disabled\n")
: $SupportSsl++;

eval("use Net::Telnet;");
$@ ? warn("*** Net::Telnet module not found, telnet negociation
disabled\n")
: $SupportTelnet++;

eval("use IO::Socket::INET6;");
$@ ? warn("*** IO::Socket::INET6 module not found, IPv6 support
disabled\n")
: $SupportIpv6++;

sub new {
my $self = shift;
bless({
_s => undef,
@_,
}, $self);
}

sub resolv {
my ($self) = @_;
if ($SupportIpv6 && $self->{6}) {
my @res = Socket6::getaddrinfo($self->{s}, 'ftp', AF_INET6,
SOCK_STREAM);
if (@res >= 5) {
my $saddr = $res[3];
my ($ip) = Socket6::getnameinfo(
$res[3], Socket6::NI_NUMERICHOST()|Socket6::NI_NUMERICSERV());
return $ip;
}
die("resolv: unable to resolv host: ".$self->{s}." [$!]\n");
}
else {
my $saddr = gethostbyname($self->{s})
or die("resolv: unable to resolv host: ".$self->{s}." [$!]\n");
return inet_ntoa($saddr);
}
}

sub init {
my ($self) = @_;

$SIG{INT} = sub { $self->exit };
$SIG{CHLD} = 'IGNORE';

STDOUT->blocking(0);
STDOUT->autoflush(1);
STDIN->blocking(0);
STDIN->autoflush(1);

# Set default values
if (! defined($self->{e})) {
$self->{e} = '';
}
if (! defined($self->{s})) {
($SupportIpv6 && $self->{6}) ? do { $self->{s} = '::'; }
: do { $self->{s} = '0.0.0.0'; };
}
if (! defined($self->{p})) {
$self->{p} = 0;
}
$self->{s} = $self->resolv;

# Sanity checks
if ($self->{l} && $self->{r}) {
delete($self->{l});
}
if ($self->{u} && $self->{c}) {
die("init: SSL does not work over UDP\n");
}
}

sub client {
my ($self) = @_;

my $inet;
my %args = (
PeerHost => $self->{s},
PeerPort => $self->{p},
Proto => $self->{u} ? 'udp' : 'tcp',
);
if ($SupportIpv6 && $self->{6}) {
$inet = "IO::Socket::INET6";
$args{Domain} = AF_INET6;
}
elsif ($SupportSsl && $self->{c}) {
$inet = "IO::Socket::SSL";
$args{Domain} = ($SupportIpv6 && $self->{6}) ? AF_INET6 : AF_INET;
if ($self->{a} && $self->{f} && $self->{k}) {
$args{SSL_server} = 0;
$args{SSL_use_cert} = 1;
$args{SSL_ca_file} = $self->{a};
$args{SSL_cert_file} = $self->{f};
$args{SSL_key_file} = $self->{k};
}
}
else {
$inet = "IO::Socket::INET";
$args{Domain} = AF_INET;
}

my $s = $inet->new(%args);
if (! defined($s)) {
if ($SupportSsl && $self->{c}) {
die("client: SSL error connecting to:
".$self->{s}.":".$self->{p}.
" [".IO::Socket::SSL::errstr()."]");
}
else {
die("client: error connecting to: ".$self->{s}.":".$self->{p}.
" [$!]");
}
($SupportIpv6 && $self->{6}) ? print " (IPv6)\n" : print "
(IPv4)\n";
}

$s->blocking(0);
$s->autoflush(1);
$self->{_s} = $s;

# We MUST use connected UDP, otherwise syswrite() and sysread() do not
work
if ($self->{u}) {
if ($SupportIpv6 && $self->{6}) {
connect($s, Socket6::sockaddr_in6($self->{p},
Socket6::inet_pton(AF_INET6, $self->{s})))
or die("client: error doing connect() [$!]\n");
}
else {
connect($s, sockaddr_in($self->{p}, inet_aton($self->{s})))
or die("client: error doing connect() [$!]\n");
}
$s->syswrite("\0"); # So the server will know we are here,
# and will connect() the socket on its side.
}

if ($self->{v}) {
print "client: connected to: ".$self->{s}.":".$self->{p};
($SupportIpv6 && $self->{6}) ? print " (IPv6)\n" : print "
(IPv4)\n";
if ($self->{c}) {
print "client: using cipher: ".$s->get_cipher."\n";
}
}
}

sub _rwLoop {
my ($self, $in, $out, $err) = @_;

my $s = IO::Select->new;
$s->add($self->{_s});
$s->add($in);

while (my @read = $s->can_read) {
my $toRead = 1024; # We read by chunk of 1024 bytes
for my $this (@read) {
if ($this == $self->{_s}) {
while (defined(my $r = $self->{_s}->sysread(my $buf,
$toRead))) {
if ($r > 0) { print $out $buf; last if $r <= $toRead; }
else { return; }
}
}
elsif ($this == $in) {
my $toWrite = '';
while (defined(my $r = $in->sysread(my $buf, $toRead))) {
if ($r > 0) { $toWrite .= $buf; }
}
if (length($toWrite)) { $self->{_s}->syswrite($toWrite); }
}
}
}
}

sub clientLoop {
my ($self, $in, $out, $err) = @_;

if (length($self->{e})) {
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die("clientLoop: socketpair [$!]\n");
CHILD->blocking(0);
CHILD->autoflush(1);
PARENT->blocking(0);
PARENT->autoflush(1);

defined(my $pid = fork()) or die("clientLoop: fork [$!]\n");
if ($pid == 0) {
my $parent = fileno(PARENT);
open(STDIN, "<&=$parent");
open(STDOUT, ">&=$parent");
open(STDERR, ">&=$parent");
system($self->{e});
exit(0);
}
else {
my $child = fileno(CHILD);
open(STDIN, "<&=$child");
open(STDOUT, ">&=$child");
open(STDERR, ">&=$child");
$self->_rwLoop(\*STDIN, \*STDOUT, \*STDERR);
}
}
else {
$self->_rwLoop($in, $out, $err);
}
}

sub server {
my ($self) = @_;

my $inet;
my %args = (
LocalAddr => $self->{s},
LocalPort => $self->{p},
Proto => $self->{u} ? 'udp' : 'tcp',
Type => $self->{u} ? SOCK_DGRAM : SOCK_STREAM,
ReuseAddr => 1,
);
$args{Listen} = 10 if ! $self->{u};
if ($SupportIpv6 && $self->{6}) {
$inet = "IO::Socket::INET6";
$args{Domain} = AF_INET6;
}
elsif ($SupportSsl && $self->{c}) {
$inet = "IO::Socket::SSL";
$args{Domain} = ($SupportIpv6 && $self->{6}) ? AF_INET6 : AF_INET;
if ($self->{a} && $self->{f} && $self->{k}) {
$args{SSL_server} = 1;
$args{SSL_use_cert} = 1;
$args{SSL_ca_file} = $self->{a};
$args{SSL_cert_file} = $self->{f};
$args{SSL_key_file} = $self->{k};
}
}
else {
$inet = "IO::Socket::INET";
$args{Domain} = AF_INET;
}

my $s = $inet->new(%args);
if (! defined($s)) {
if ($SupportSsl && $self->{c}) {
die("server: SSL error listening on: ".$self->{s}.":".$self->{p}.
" [".IO::Socket::SSL::errstr()."]");
}
else {
die("server: error listening on: ".$self->{s}.":".$self->{p}.
" [$!]");
}
($SupportIpv6 && $self->{6}) ? print " (IPv6)\n" : print "
(IPv4)\n";
}

$s->blocking(0);
$s->autoflush(1);
$self->{_s} = $s;

if ($self->{v}) {
if ($SupportSsl && $self->{c}) {
print("server: SSL listening on: ".$self->{s}.":".$self->{p});
}
else {
print("server: listening on: ".$self->{s}.":".$self->{p});
}
($SupportIpv6 && $self->{6}) ? print " (IPv6)\n" : print "
(IPv4)\n";
}
}

sub serverLoop {
my ($self, $in, $out, $err) = @_;

my $s = IO::Select->new;
$s->add($self->{_s});

open(my $oldout, ">&STDOUT");

while (my @ready = $s->can_read) {
if ($self->{u}) {
if (my $new = $self->{_s}->recv(my $tmp, 0)) {
my ($port, $saddr, $ipaddr);
if ($SupportIpv6 && $self->{6}) {
($port, $saddr) = Socket6::sockaddr_in6($new);
$ipaddr = Socket6::inet_ntop(AF_INET6, $saddr);
}
else {
($port, $saddr) = sockaddr_in($new);
$ipaddr = inet_ntoa($saddr);
}

if ($self->{v}) {
print $oldout "serverLoop: connection from:
$ipaddr:$port\n";
if ($self->{c}) {
print "serverLoop: using cipher:
".$new->get_cipher."\n";
}
}

# We MUST use connected UDP, otherwise syswrite() and
sysread()
# do not work
if ($SupportIpv6 && $self->{6}) {
connect($self->{_s}, Socket6::sockaddr_in6($port, $saddr))
or die("serverLoop: error doing connect() [$!]\n");
}
else {
connect($self->{_s}, sockaddr_in($port, $saddr))
or die("serverLoop: error doing connect() [$!]\n");
}
$self->clientLoop($in, $out, $err);
}
}
elsif (my $new = $self->{_s}->accept) {
if ($self->{v}) {
print $oldout "serverLoop: connection from:
".$new->peerhost.":".
$new->peerport."\n";
if ($self->{c}) {
print "serverLoop: using cipher: ".$new->get_cipher."\n";
}
}

$new->blocking(0);
$new->autoflush(1);

defined(my $pid = fork()) or die("serverLoop: fork [$!]\n");
if ($pid == 0) { # Son process
$self->{_s} = $new;
$self->clientLoop($in, $out, $err);
if ($self->{v}) {
print $oldout "serverLoop: client ".$new->peerhost.":".
$new->peerport." disconnected\n";
}
exit(0);
}
}
}
}

sub proxy {
my ($self) = @_;
$self->server;
}

sub proxyLoop {
my ($self, $in, $out, $err) = @_;

my $s = IO::Select->new;
$s->add($self->{_s});

open(my $oldout, ">&STDOUT");

while (my @ready = $s->can_read) {
if ($self->{u}) {
if (my $new = $self->{_s}->recv(my $tmp, 0)) {
my ($port, $saddr, $ipaddr);
if ($SupportIpv6 && $self->{6}) {
($port, $saddr) = Socket6::sockaddr_in6($new);
$ipaddr = Socket6::inet_ntop(AF_INET6, $saddr);
}
else {
($port, $saddr) = sockaddr_in($new);
$ipaddr = inet_ntoa($saddr);
}

if ($self->{v}) {
print $oldout "proxyLoop: connection from:
$ipaddr:$port\n";
if ($self->{c}) {
print "proxyLoop: using cipher: ".$new->get_cipher."\n";
}
}

# We MUST use connected UDP, otherwise syswrite() and
sysread()
# do not work
if ($SupportIpv6 && $self->{6}) {
connect($self->{_s}, Socket6::sockaddr_in6($port, $saddr))
or die("proxyLoop: error doing connect() [$!]\n");
}
else {
connect($self->{_s}, sockaddr_in($port, $saddr))
or die("proxyLoop: error doing connect() [$!]\n");
}
my $new = $self->{_s};

my ($host, $dport, $v6, $ssl) = split(':', $self->{r});
$self->{6} = (defined($v6) && $v6 =~ /ipv6/i) ? 1 : 0;
$self->{c} = (defined($ssl)) ? 1 : 0;
$self->{s} = $host; $self->resolv;
$self->{p} = $dport;
$self->client;
$self->clientLoop($new, $new, $new);
}
}
elsif (my $new = $self->{_s}->accept) {
print $oldout "proxyLoop: connection from: ".$new->peerhost.":".
$new->peerport."\n"
if $self->{v};

$new->blocking(0);
$new->autoflush(1);

defined(my $pid = fork()) or die("proxyLoop: fork [$!]\n");
if ($pid == 0) { # Son process
my ($host, $port, $v6, $ssl) = split(':', $self->{r});
$self->{6} = (defined($v6) && $v6 =~ /ipv6/i) ? 1 : 0;
$self->{c} = (defined($ssl)) ? 1 : 0;
$self->{s} = $host; $self->resolv;
$self->{p} = $port;
$self->client;
$self->clientLoop($new, $new, $new);
print $oldout "proxyLoop: client ".$new->peerhost.":".
$new->peerport." disconnected\n"
if $self->{v};
exit(0);
}
}
}
}

sub run {
my ($self) = @_;

$self->init;
if ($self->{l}) {
$self->server;
$self->serverLoop(\*STDIN, \*STDOUT, \*STDERR);
}
elsif ($self->{r}) {
$self->proxy;
$self->proxyLoop(\*STDIN, \*STDOUT, \*STDERR);
}
else {
$self->client;
$self->clientLoop(\*STDIN, \*STDOUT, \*STDERR);
}
$self->exit;
}

sub exit {
my ($self) = @_;
$self->{_s}->close if defined($self->{_s});
exit;
}

1;

package main;
use warnings; use strict;

my $prog = "scnc";
my $progname = "SSL Capable NetCat 1.00";

use Getopt::Std;

my $opts = '';
my $usage = "$progname\n\nUsage: $prog [-options] target port\n\n";

if ($SupportSsl) {
$usage .= " -c use SSL (default to not)\n";
$usage .= " -a use SSL certificate authority file\n";
$usage .= " -f use SSL certificate file (PEM format)\n";
$usage .= " -k use SSL private key file (PEM format)\n";
$opts .= "ca:f:k:";
}
if ($SupportTelnet) {
$usage .= " -t do telnet negociation (default to not)\n";
$opts .= "t";
}
if ($SupportIpv6) {
$usage .= " -6 use IPv6 (default to not)\n";
$opts .= "6";
}
$usage .= " -e cmd command to execute\n";
$usage .= " -l listen for connections (default to not)\n";
$usage .= " -p port use local port number (default to random
high)\n";
$usage .= " -s address use address for bindings (default to all
addresses)\n";
$usage .= " -u use UDP socket (default to TCP)\n";
$usage .= " -v be verbose (default to not)\n";
$usage .= " -r host:port proxy connection to host:port\n";
$usage .= " -r host:port:ipv6 proxy connection to host:port using
IPv6\n";
$usage .= " -r host:port::ssl proxy connection to host:port using
SSL\n";
$usage .= " -r host:port:ipv6:ssl proxy connection to host:port using
IPv6 and SSL\n";
$opts .= "e:lp:s:uvr:";

my %opts;
getopts($opts, \%opts);

$opts{p} = pop unless defined($opts{p});
$opts{s} = pop unless defined($opts{s});

if ((! $opts{l})
&& (! $opts{r})
&& (! defined($opts{s}) || ! defined($opts{p}))) {
print $usage and exit(0);
}

Scnc->new(%opts)->run;


ADDITIONAL INFORMATION

The information has been provided by <mailto:fd@xxxxxxxxx> GomoR.
The original article can be found at:
<http://www.gomor.org/bin/view/GomorOrg/SslNetcat#Download>
http://www.gomor.org/bin/view/GomorOrg/SslNetcat#Download



========================================


This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx


====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • [TOOL] Multimap - Multithreaded Wrapper for NMap
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... concurrent NMap scans and speed up the scan of large networks. ... Writes the results to an HTML file ... sub getDate { ...
    (Securiteam)
  • [NEWS] Apple OSX Fetchmail Buffer Overflow
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Apple OSX Fetchmail Buffer Overflow ... alarm $timeout; ... sub ERR ...
    (Securiteam)
  • [EXPL] I-Mall Commerce i-mall.cgi Arbitrary Command Execution (Exploit)
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... A remote command execution vulnerability has been discovered in the I-Mall ... sub intro { ... chomp $host; ...
    (Securiteam)
  • ADO Connection Object
    ... I would like a function to test whether I can open a connection to my SQL ... Server database. ... Dim WithEvents m_cnn As ADODB.Connection ... Private Sub Form_Open ...
    (comp.databases.ms-access)
  • Re: Threading.Monitor.Enter that doesnt /quite/ block the thread
    ... Protected Overloads Overrides Sub Dispose ... Public ReadOnly Property Connection() As SqlCeConnection ... Private Sub Form1_Activated(ByVal sender As Object, ...
    (microsoft.public.dotnet.framework.compactframework)