on an ubuntu 14.04 lts server...
# apt-get install build-essential mail-utils perl
run cpan get the following cpan dependencies:
# cpan
> install Net::DNS
> install Net::Server
> install YAML
> install MIME::Lite::TT
> install Data::Dumper
> install Getopt::Long
> install Net::IP::Match::Regexp
> exit
place perl script and conf in /usr/local/bin/honey or wherever
do a little ln action.
# ln -s /usr/local/honey/honey.conf /etc/honey.conf
set background to 1 in honey.conf to make it turn into a background process.
and... when putting in your ports, if any ports happen to be open when
honey.pl is called, honey.pl will die.
figure them out?
# netstat -tpln
speaking of which look at the honey.conf below, we're going to be opening
a scad of ports. tune the system:
# ulimit -n 70000
# echo "32768 65535" >/proc/sys/net/ipv4/ip_local_port_range
test it
# perl -c honey.pl should return 'OK'
start with
# perl /usr/local/honey.pl --config /etc/honey.conf
if running via /etc/rc.local :
# chmod +x /etc/rc.local
add the line before exit 0:
perl /usr/local/honey.pl --config /etc/honey.conf
##########
# honey.pl
#!/usr/bin/perl
# version 1.3
package Honey;
use MIME::Lite::TT;
use Net::DNS;
use strict;
use warnings;
use Data::Dumper;
use base qw(Net::Server::PreForkSimple);
use YAML;
use Getopt::Long;
use Net::IP::Match::Regexp qw( create_iprange_regexp match_ip );
sub logger($);
my $configfile = "./honey.conf";
GetOptions ("config=s" => \$configfile);
my ($hashref, $arrayref, $string) = YAML::LoadFile( $configfile );
print Dumper($hashref);
my %config = %$hashref;
#############################
### CONFIG
#############################
my $from_email = $config{'from_email'};
my $subject = $config{'subject'};
my $to_email = $config{'to_email'};
my $mailserver = $config{'mailserver'};
my $mail_thres = $config{'mail_thres'};
my $tempfolder = $config{'tempfolder'};
my $lp_ref = $config{'listenports'};
my $background = $config{'background'};
my $ih_ref = $config{'ignorehosts'};
my $logpath = $config{'logpath'};
unless ( 1 &&
defined($from_email) &&
defined($subject) &&
defined($to_email) &&
defined($mailserver) &&
defined($mail_thres) &&
defined($tempfolder) &&
defined($lp_ref) &&
defined($background) &&
defined($ih_ref) &&
1 ) {
die "invalid configuration\n";
}
unless (defined($logpath)) {
print STDERR "No logpath given, will default to /var/log/honey.log";
$logpath = "/var/log/honey.log";
}
logger("honey init");
#############################
### VARS
#############################
my ($i);
my @lports = @$lp_ref;
my @ih = split(",",$ih_ref);
my $ignorehosts = create_iprange_regexp(@ih);
my $tempcache = $tempfolder . "honeycache";
my $tempports = $tempfolder . "honeyports";
my $template = <<TEMPLATE;
Unauthorized connection noted \n\r
Connection details: [% connection_string %] \n\r
Source details: [% srcip %] ([% srcip_dns %]) \n\r
Timestamp: [% timestamp %]
TEMPLATE
############################################
sub post_accept {
#print STDERR "post accept in $$\n";
}
sub process_request {
my $self = shift;
#print STDERR "process request in $$\n";
my $connection_info = $self->{'server'}->{'peeraddr'} . ":" . $self->{'server'}->{'peerport'};
$connection_info = $connection_info . " --> " . $self->{'server'}->{'sockaddr'} . ":" . $self->{'server'}->{'sockport'};
connection_identified( $self->{'server'}->{'peeraddr'}, $connection_info);
}
sub connection_identified ($$) {
my $srcIP = $_[0];
my $connection_info = $_[1];
logger("ok we got a connection from $srcIP");
# RESTORE HASH
my $ref = restore_hash();
my %last_email_timestamp = %$ref;
my $skip_email = 0;
# check if we should ignore this IP
if (match_ip($srcIP, $ignorehosts)) {
logger("ignoring $srcIP!");
$skip_email = 1;
return 0;
}
# email max every $mail_thres secs
my $current_timestamp = time();
if (defined($last_email_timestamp{$srcIP})) {
logger("We have already seen a connection from the host before");
my $diff = $current_timestamp - $last_email_timestamp{$srcIP};
if ( $diff < $mail_thres) {
logger("OK so we saw a connection less than $mail_thres secs ago .. skippin email");
$skip_email = 1;
} else {
logger("but it was a long time ago, diff is $diff");
}
} else {
logger("we have not seen this IP before");
}
$last_email_timestamp{$srcIP} = $current_timestamp;
save_hash(\%last_email_timestamp);
if ($skip_email) { return; };
logger("ok gonna send an email using $mailserver, timeout 60");
# reverse dns
my $srcip_dns = PTR_lookup($srcIP);
# timestamp
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $timestamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d\n",$year+1900,$mon+1,$mday,$hour,$min,$sec);
# SEND EMAIL?
my %params;
$params{connection_string} = $connection_info;
$params{srcip_dns} = $srcip_dns;
$params{srcip} = $srcIP;
$params{timestamp} = $timestamp;
my $msg = MIME::Lite::TT->new(
From => $from_email,
To => $to_email,
Subject => $subject,
Template => \$template,
TmplParams => \%params,
);
$msg->send('smtp', $mailserver, Timeout => 60 );
logger("email sent using $mailserver");
}
sub PTR_lookup {
my $tname = shift;
my $type = "Reverse (PTR)";
my $rr;
my $res = new Net::DNS::Resolver;
my $query = $res->query("$tname","PTR");
if ($query) {
foreach $rr ($query->answer) {
next unless $rr->type eq "PTR";
my $ip = $rr->ptrdname;
return ($ip);
}
} else {
my $logstring = "Reverse lookup query failed for $tname : " . $res->errorstring . "\n";
logger($logstring);
return ($tname);
}
}
sub restore_hash() {
my %thash = ();
if (-e $tempcache) {
open(FOO,"<$tempcache") or die;
foreach my $line (<FOO>) {
chomp($line);
my ($ip,$time) = split(":",$line);
$thash{$ip} = $time;
}
close(FOO);
}
return \%thash;
}
sub save_hash($) {
my $hash_ref = $_[0];
my %thash = %$hash_ref;
open(FOO,">$tempcache") or die;
foreach my $key (keys %thash) {
if (defined($thash{$key})) {
print FOO $key . ":" . $thash{$key} . "\n";
}
}
close(FOO);
}
sub logger($) {
my $message = $_[0];
# LOG
open(POO,">>$logpath") or die;
print POO get_date() . ": $message\n";
close(POO);
# STDERR
print STDERR get_date() . ": $message\n";
}
sub get_date () {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $timestamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d\n",$year+1900,$mon+1,$mday,$hour,$min,$sec);
chop($timestamp);
return $timestamp;
}
open(FOO,">$tempports") or die;
foreach my $lport (@lports) {
if ($lport =~ /(\d+)-(\d+)/) {
my $startport = $1;
my $stopport = $2;
if ($stopport < $startport) { die "Invalid config, check the range\n"; };
for ($i=$startport;$i<=$stopport;$i++) {
print FOO "port $i\n";
}
} elsif ($lport =~ /^(\d+)/) {
print FOO "port $lport\n";
} else {
logger("Invalid port $lport specified");
}
}
close(FOO);
if ($background) {
Honey->run( background => 1,
conf_file => "$tempports");
} else {
Honey->run(conf_file => "$tempports");
}
##########
# honey.conf
from_email: me@here
to_email: you@there
mailserver: smtpserver
ignorehosts: 10.10.10.10, 0.0.0.0
mail_thres: 60
tempfolder: /tmp/
subject: Unauthorized connection to knockknock
background: 1
logpath: /var/log/honeylog.log
listenports:
- 1-21
- 23-24
- 26-65500
Friday, December 19, 2014
knock know who's there?
sometimes you just want to set up a virtual system to see if there are any scans going on your network.
apache logs to syslog
the other day i flipped out. well, flipped out in my own quiet way. i heard about some apache access issues and it gave me a slight headache.
the super cool thing about linux boxes is that the "truth is in the logs". and i heart logs and log aggregation.
the cool thing about apache is that if configured correctly it will log all access and all errors. sadly, apache, by default, writes its logs on the local system and not via syslog processes. crap.
i really really don't want to go to each of my boxes and grep through /var/log/apache/blah.txt, how do i throw the logs access the network?
well, most linux boxes have tee and logger. tee is a nice program that basically say, do this and this. logger can send arbitrary data to syslog. yay.
in my enabled site, i changed my ErrorLog and CustomLog sections from this:
since i'm using rsyslogd, i edited my /etc/rsyslog.d/50-default conf to pipe off my logs to my remote syslog server:
reload your daemons and voila.
the cool thing about apache is that if configured correctly it will log all access and all errors. sadly, apache, by default, writes its logs on the local system and not via syslog processes. crap.
i really really don't want to go to each of my boxes and grep through /var/log/apache/blah.txt, how do i throw the logs access the network?
well, most linux boxes have tee and logger. tee is a nice program that basically say, do this and this. logger can send arbitrary data to syslog. yay.
in my enabled site, i changed my ErrorLog and CustomLog sections from this:
ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combinedto this:
ErrorLog "|/usr/bin/tee -a /var/log/apache2/error.log | /usr/bin/logger -thttpd -plocal6.err" CustomLog "|/usr/bin/tee -a /var/log/apache2/access.log | /usr/bin/logger -thttpd -plocal6.notice" combinedi'm calling local6 and sending it off to syslog in httpd format. neat.
since i'm using rsyslogd, i edited my /etc/rsyslog.d/50-default conf to pipe off my logs to my remote syslog server:
auth,authpriv.*;local6.* @remotesyslogserverif you'd rather not log to /var/log/syslog, add: local6.none to the -/var/log/messages stanza.
reload your daemons and voila.
Wednesday, December 17, 2014
openvas v7 create a new user
well. there are so many ways to create a user. this allows for integration with greenbone security desktop; a scanner user.
root@openvas:~# openvasmd --create-user younotme User created with password 'd25d4c66-5f7a-4156-84ee-f3ee101381fa'. root@openvas:~# openvasmd --user=younotme --new-password=notcreatedherethat was easy.
Monday, December 8, 2014
create a user via commandline in osx
create a local user with local user group in macos x
list existing local gids:
# dscl . -list /Groups PrimaryGroupID | awk '{print $2}' | sort -n
for new group, choose numeric id not in list; above 1000 is good.
# dscl . -create /Groups/localgroup
# dscl . -create /Groups/localgroup PrimaryGroupID 1001
did you press enter?
# dscl . -read /Groups/localgroup
AppleMetaNodeLocation: /Local/Default
GeneratedUID: 00A738DA-21B7-4CD2-B5D9-7873C77205D1
PrimaryGroupID: 1001
RecordName: localgroup
RecordType: dsRecTypeStandard:Groups
list existing local uids:
# dscl . -list /Users UniqueID | awk '{print $2}' | sort -n
for new user, choose numberic id not in lists; above 1000 is good.
# dscl . -create /Users/localuser
# dscl . -create /Users/localuser UserShell /bin/bash
# dscl . -create /Users/localuser RealName "Local Users"
# dscl . -create /Users/localuser UniqueID "1001"
# dscl . -create /Users/localuser PrimaryGroupID 1001
# dscl . -create /Users/localuser NFSHomeDirectory /Users/localuser
did you really do all that?
# dscl . -read /Users/localuser
AppleMetaNodeLocation: /Local/Default
NFSHomeDirectory: /Users/localuser
GeneratedUID: 47D6D841-C7F1-4962-9F7E-167E8BFC3A91
PrimaryGroupID: 1001
RealName: localuser
RecordName: localuser
RecordType: dsRecTypeStandard:Users
UniqueID: 1001
UserShell: /usr/bash
create home directory.
# mkdir /Users/localuser
# chown localuser:localgroup /Users/localuser
give localuser a password:
# password localuser
# su - localuser
$
neat!
Friday, December 5, 2014
netapp exports and hate
i have a netapp on premises.
it has a couple vfilers. i wanted to create an additional vfiler. sadly, i couldn't. hate. i hate.
i created a volume and i needed to make it have special non-nfsv4 settings cause that's just how the world goes.
but! for whatever reason the netapp won't let me edit /etc/exports via a mount on a management host. it just won't.
so, here's what you do, and you'll see what this is a pain.
ssh root@freakonetapp
rdfile /etc/exports
(and out spits a lot of stuff)
/vol/crap -sec=sys,rw,root=10.6.6.66,nosuid
/vol/crap2 -sec=sys,rw,root=10.6.6.66,nosuid
i need to change /vol/crap2 and add yet another management host.
so, copy all the lines that spit out on the screen. make your spiffy changes on an editor somewhere and issue:
wrfile /etc/export
(copy your spiffy changes you had in an editor elsewhere)
/vol/crap -sec=sys,rw,root=10.6.6.66,nosuid
#/vol/crap2 -sec=sys,rw,root=10.6.6.66,nosuid
/unix-crap -actual=/vol/crap2,sec=sys,rw,root=10.6.6.66:10.6.66.6,nosuid
Ctrl-C
And reexport nfs:
exportfs -a
Thursday, December 4, 2014
am i slob or am i lazy? let's find -exec chown
le sigh. LE SIGH. sometimes people like to do things on their own out of expediency or
because their local sysadmin is a lazy lazy lazy slob.
i'm not a slob.
the issue was that someonenotme updated ubuntu and nfs was broke. or rather,
their home dir wasn't mounted.
this had been the case for months.
sure, i could put this line in /etc/fstab and go my merry way:
slobberserver:/home /home nfs rsize=8192,wsize=8192,soft,_netdev 0 0
but, i'm not a slob.
see that _netdev? that's an awesome directive that says, "hey linuxbox
do not mount me till the network stack it up". awesome.
here's what you do:
record someonenotme's local system uid & gid
# id someonenotme
uid=1000(someonenotme) gid=1000(someonenotme)
kill all someonenotme processes
# kill -9 `ps -ef|grep someonenotme| awk '{print $2}'`
really really?
# lsof |grep someonenotme
... nada ...
ldap & nfs-ize the system
# apt-get install nscd autofs ldap-client
put all your specially conf'd ldap conf files in /etc
refresh the name service
# /etc/init.d/nscd restart
# id someonenotme
uid=15288(someonenotme) gid=101(someonenotme) groups=100(users)
edit passwd and change someonenotme's uid and gid to that in ldap.
oh, and make sure the homedir matches, too.
# vipasswd
now we change all the uids and gids so that someonenotme matches what we have in ldap.
to prevent an unfun time, first umount all nfs mounts of interest.
# umount /home
now we look and change:
# find / -uid 1000 -gid 1000 -exec chown 15288:101 {} \;
after this is complete, mount -a and go about your business.
but wait! you cd'd into their dir, didn't you? you saw they've done stuff as root
in the past. crud. why did you ls -la?
# find /home/someonenotme -uid 0 -gid 0 -exec chown 15288:101 {} \;
still not a slob.
Subscribe to:
Posts (Atom)