sexta-feira, setembro 29, 2006

Executando scrips remotamente com GAWK !!

Executar comandos remotamente sem necessitar de senha,
é o sonho de todo hacker e teoricamente o pesadelo de todo
Administrador Unix.

Existem varias maneiras de executar processos remotos, em
muitos preferem usar ssh + chave rsa, que a meu ver
prove mais risco do que solução.

Pensando nisso eu escrevi 2 scripts usando gawk,

O primeiro é o RCSS - Remote Check System Server

#!/usr/local/bin/gawk -f
##
## RCSS -- Remote Check System Server
## Copyright (c) 2005 Ricardo Alves dos Reis <ricardo.areis@gmail.com>
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
##
## THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
function usage( v, s, b, u)
{
v = " -V version -- Server Version"
h = " -h help -- RCSS Help"
s = " -p port -- Server Port"
b = " -b bind -- Bind Address\n"
u = "rcss [options]"
print u > "/dev/stderr"
print "" > "/dev/stderr"
print "Options:" > "/dev/stderr"
print h > "/dev/stderr"
print v > "/dev/stderr"
print s > "/dev/stderr"
print b > "/dev/stderr"
print "Ex. rcss -b 192.168.0.1 -p 8192" > "/dev/stderr"
exit
}
function network()
{
while ((cmd | getline) > 0)
print $0 |& NetService
fflush(NetService)
close(NetService)
fflush()
}
BEGIN {
if ( ARGV[1] == "-h"){
usage()
}
else if ( ARGV[1] == "-V"){
print "CRS Server 1.0 - Check Remote System Server"
exit
}
else if ( ARGV[1] == 0 || ARGV[2] == 0 || ARGV[3] == 0 || ARGV[4] == 0) {
if ( SPORT == 0 ) { SPORT = 6556 }
if ( BIND == 0 ) { BIND = 0 }
}
else if ( ARGV[1] == "-b" ) {
if ( ARGV[2] ~ /[[:digit:]]/ ) {
BIND = ARGV[2]
if ( ARGV[3] == "-p" ) {
if ( ARGV[4] ~ /[[:digit:]]/ ) {
SPORT = ARGV[4]
}
}
}
}
else
usage()
NetService = "/inet/tcp/" SPORT "/" BIND "/0"
NetService |& getline

if ( NF > 2 ) {
exit
}
if ( $1 ~ "1234567890")
cmd = "sh /etc/periodicos/bin/comandos.sh "$2
network()
}

Basicamente este script abre uma porta tcp, por default 6556 e trata
toda a string passada, caso essa tenha mais de 2 colunas
o script continua.

O segundo if garante que para continuar a primeira coluna deve
conter um numero de identificação condizente com "1234567890",
caso isso aconteça a segunda coluna será
passada como argumento para um script em shell comandos.sh.

O meu script comandos.sh é muito extenso, um exemplo basico
do que pode ser feito é:


Uma função loadav_free() que retorna a media de carga do servidor remoto.

loadav_free()
{
OUTPUT=`sysctl vm.loadavg`
outputyesno "$OUTPUT" $PRINT
}


loadav_free $1

Quando repassamos o argumento 2 ou seja "$2" para o script comandos.sh,
este interpreta como argumento 1 ou seja $1.

O segundo é o RCSC - Remote Check System Client:

#!/usr/local/bin/gawk -f
## rcsc -- Remote Check System Client
## Copyright (c) 2005 Ricardo Alves dos Reis < ricardo.areis@gmail.com>
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
##
## THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
function usage( u, v, c, s, p)
{
u = "rcsc [options]"
h = " -h help -- RCSC Help"
v = " -V version -- Program Version"
c = " -c check -- Check Services Number\n\
( [12345] see Server)"
s = " -s server -- CRS Server"
p = " -p port -- RCSS port"
print u > "/dev/stderr"
print "" > "/dev/stderr"
print "Options:" > "/dev/stderr"
print v > "/dev/stderr"
print h > "/dev/stderr"
print s > "/dev/stderr"
print p > "/dev/stderr"
print c > "/dev/stderr"
print "\nEx. rcsc -s 192.168.0.1 -p 8192" > "/dev/stderr"
exit
}
BEGIN {
if ( ARGV[1] == "-V" ){
print "CRS 1.0 - Check Remote System"
exit
}
else if ( ARGV[1] == "-s" ){
if ( ARGV[2] ~ /[[:digit:]]/ ) {
BIND = ARGV[2]
}
if ( ARGV[3] == "-p" ){
if ( ARGV[4] ~ /[[:digit:]]/ ) {
SPORT = ARGV[4]
}
}
if ( ARGV[5] == "-c" ) {
service = ARGV[6]
}
else
usage()
}
else
usage()
NetService = "/inet/tcp/0/" BIND "/"SPORT
print service |& NetService
while ((NetService |& getline) > 0)
print $0
close(NetService)
}

Esse script é básico e a única diferença dele
para um telnet é o caracter terminação adicionado pelo gawk
que indica termino de string.

Testando o script,

[ricardo@ricardo(9:49am)] /ricardo# gawk -f /etc/periodicos/bin/rcsc -s 200.xxx.xxx.xxx -p 6556 -c '1234567890 loadav_free'
vm.loadavg: { 0.53 0.75 0.71 }


Obviamente essa solução torna-se eficaz e realmente segura
com o uso de algum tipo de criptografia, eu normalmente uso com stunnel
o que garante um meio muito mais seguro.

Ja não tenho trabalhado nesses scripts a alguns meses, e sendo assim muitas
coisas só não estão melhores por falta de tempo e estudo.