Well, in an attempt to address this issue, I have written my very first
application. I am not, and have never claimed to be, a coder. Nonetheless,
the attached Python script will solve this issue. No, it's not perfect.
Yes, it does work. :) It has been tested with both the 1.0.10 and
1.1.12 releases.
The script is well commented and I would really be interested in any
feedback.
Renaud - feel free to throw this in a "contrib" (or simiar) folder with
Nessus if you like. Use it, abuse it, whatever. :)
Again, I'd really be interested in any feedback about this or
additions/patches to it. Thanks! :)
~Jay
On Tue, 12 Feb 2002, Renaud Deraison wrote:
> On Tue, Feb 12, 2002 at 02:09:47PM -0500, Dmitriy Kropivnitskiy wrote:
> > For my uses of nessus, making a separate interactive
> > CLI interface would not help things, since it will not
> > generate nessusrc automagically. My suggestion ( not sure
> > if it is easily implementable ) would be to make a separate
> > program/script that would pull current .nessusrc in, pull current
> > plugin list, find differences and insert new plugins according to
> > some kind of a rule set.
>
> You can retrieve the list of plugins from the remote nessusd server
> by doing
> nessus -pq nessusd_host 1241 login password
>
>
> That's a start - feel free to write the rest ;)
>
> -- Renaud
>
--
~Jay
#!/usr/bin/python
####
# PROBLEM: Nessus stores a static list of plugins to use for a particular scan in the
.nessusrc
# file on the client (one line for every plugin). Since the plugins on the nessusd
server are
# updated almost daily, a client's .nessusrc file can become very out-of-date very
quickly.
# Currently, the only way to re-create an updated .nessusrc file is to run the Nessus
GUI client.
# This is not good for in a number of scenarios, like machines without a GUI
environment or
# doing unattended scans (i.e., from cron).
#
# SOLUTION: This script will connect to a nessusd server and dump its plugin list. We
will
# then enable/disable groups of plugins based on their family and write an up-to-date
.nessusrc
# file based on the plugins currently available on the nessusd server.
#
# This script has been tested on Linux and Mac OS X, using Nessus releases 1.0.10 and
1.1.12.
#
# There are several problems with this script. First, it uses telnet to connect to the
nessusd
# server and authenticate. Therefore, everything done with this script is clear-text
and is
# a security risk (ironic, eh? :). Additionally, some plugins have their own
preferences
# defined in the .nessusrc file. However, this script *only* manipulates the
PLUGIN_SET portion
# of the .nessusrc file dynamically - everything else (including PLUGINS_PREFS) is
totally static
# as defined in the "HeaderText" or "FooterText" sections of this script. Therefore,
it is
# possible (likely) that this script will enable a new plugin but will *not* create
individual
# preferences for that plugin. The fix is to just run the Nessus GUI occasionally to
create
# the PLUGINS_PREFS, and then use those new settings in the HeaderText of this script.
# Again, ain't irony grand? :)
#
# I know there are ways to fix the above issues, so if someone would like to
contribute to this
# script that would be great. This script is my very first attempt at a non-Bash-shell
proggie,
# so please excuse any bad coding. Nonetheless, even with its shortcomings, this
script will
# allow you to update the plugins in your .nessusrc file without having to run the GUI
every day.
#
# *** Thank you to the entire Nessus team for all their hard work and a great
product! ***
#
# HISTORY:
# February 8, 2002 - Initial Release
#
# This script is Copyright (C) 2002, Jay Jacobson <[EMAIL PROTECTED]>
####
import sys, time, telnetlib, string
NessusServer = 'localhost' # Name or IP of Nessus server to connect to.
NessusPort = 1241 # nessusd port - Should be either 1241 or
3001.
NTPversion = '< NTP/1.2 >' # Exact NTP version string as specified in NTP
docs.
NessusUser = 'test' # Username for nessusd connection.
NessusPass = 'password' # Password for nessusd connection username.
NessusdVer = '1.0' # Nessusd server version - either '1.0' or
'1.1'
# this will determine if we write plugin names
or ID#s.
##
# Name and path of final .nessusrc file to create
rcFile = '/tmp/.nessusrc'
####
# Must be either 'yes' or 'no' -- case and syntax must be exact
#
# Select which families of plugins to activate in the .nessusrc file. All plugins from
the
# selected family will be activated - even the "dangerous" ones.
####
FamBackdoor = 'yes' # Backdoors
FamCGI = 'yes' # CGI Abuses
FamDoS = 'yes' # Denial of Service
FamFinger = 'yes' # Finger Abuses
FamFirewall = 'yes' # Firewalls
FamFTP = 'yes' # FTP
FamShell = 'yes' # Gain a Shell Remotely
FamRoot = 'yes' # Gain Root Remotely
FamGeneral = 'yes' # General
FamMisc = 'yes' # Misc
FamNIS = 'yes' # NIS
FamScan = 'yes' # Port Scanners
FamFile = 'yes' # Remote File Access
FamRPC = 'yes' # RPC
FamSMTP = 'yes' # SMTP Problems
FamSNMP = 'yes' # SNMP
FamUseless = 'yes' # Useless Services
FamWindows = 'yes' # Windows
####
# Here we'll gather additional text to be added both before and after the generated
plugin set
# to the final .nessusrc file. This is necessary because this script is focused on
*only*
# updating the plugin sets and a complete .nessusrc file requires other stuff in it
too.
# You can probably just cut-n-paste the sections of your Nessus-GUI-created .nessusrc
file here.
####
##
# Stuff to put at the beginning of the generated plugin set. Probably just cut-n-paste
from your
# Nessus-GUI-created .nessusrc file. The last line of this section should be:
begin(PLUGIN_SET)
HeaderText = """
nessusd_host = NESSUSD.DOMAIN.COM
nessusd_user = NESSUSUSER
begin(SCANNER_SET)
Ping the remote host = yes
TCP Ping the remote host = yes
TCP SYN scan = no
FTP bounce scan = no
Nmap tcp connect() scan = no
Nmap = yes
scan for LaBrea tarpitted hosts = no
end(SCANNER_SET)
begin(PLUGINS_PREFS)
SMB use domain SID to enumerate users[entry]:Start UID : = 1000
SMB use domain SID to enumerate users[entry]:End UID : = 1200
Default accounts[entry]:Simultaneous connections : = 10
Anonymous FTP enabled[entry]:FTP login : = ftp
Anonymous FTP enabled[entry]:FTP password : = [EMAIL PROTECTED]
ftp writeable directories[radio]:How to check if directories are writeable : = Trust
the permissions (drwxrwx
--)
Ping the remote host[entry]:TCP ping destination port : = 80
Ping the remote host[checkbox]:Do a TCP ping = yes
Ping the remote host[checkbox]:Do an ICMP ping = yes
Ping the remote host[entry]:Number of retries (ICMP) : = 10
Nmap[radio]:TCP scanning technique : = connect()
Nmap[checkbox]:UDP port scan = no
Nmap[checkbox]:RPC port scan = yes
Nmap[checkbox]:Ping the remote host = no
Nmap[checkbox]:Identify the remote OS = yes
Nmap[checkbox]:Fragment IP packets (bypasses firewalls) = yes
Nmap[checkbox]:Get Identd info = yes
Nmap[checkbox]:Perform a fast scan = yes
Nmap[checkbox]:Do not randomize the order in which ports are scanned = yes
Nmap[entry]:Source port : = any
FTP bounce scan[entry]:FTP server to use : = localhost
end(PLUGINS_PREFS)
begin(SERVER_PREFS)
max_threads = 20
log_whole_attack = yes
cgi_path = /cgi-bin
port_range = 1-65535
optimize_test = yes
language = english
track_iothreads = yes
cookie_logpipe_suptmo = 2
checks_read_timeout = 15
delay_between_tests = 1
plugins_timeout = 160
host_expansion = ip
ping_hosts = no
reverse_lookup = no
end(SERVER_PREFS)
begin(RULES)
end(RULES)
begin(PLUGIN_SET)
"""
##
# ^^^ REMEMBER: The last line of the above section (before the closing """)
# should be: begin(PLUGIN_SET)
##
# Stuff to put at the end of the generated plugin set. This is probably fine the way
it is, but
# check your Nessus-GUI-created .nessusrc file just to be sure. The last line of this
section
# should be: end(PLUGIN_SET)
FooterText = """end(PLUGIN_SET)"""
##
# ^^^ REMEMBER: The last line of the above section (before the closing """)
# should be: end(PLUGIN_SET)
####
# This is the end of the configuration section - do not edit the stuff below here
####
##
# Open the new .nessusrc file and write the HeaderText
f=open(rcFile, 'w')
f.write(HeaderText)
##
# Connect to the nessusd server
tn = telnetlib.Telnet(NessusServer, NessusPort)
##
# Send the login information
tn.write(NTPversion + "\n")
tn.read_until("User : ", 10)
tn.write(NessusUser + "\n")
tn.read_until("Password : ", 10)
tn.write(NessusPass + "\n")
##
# Read until end of nessusd plugin list or 300 seconds
ServerDump = tn.read_until("<|> SERVER\n", 300)
ServerString = string.split(ServerDump, "\n")
##
# Assign the nessusd version to the array position to use. For version 1.1, we'll use
# element [0] in the array, which is the plugin ID#. For version 1.0, we'll use
# element [1] in the array, which is the plugin name.
if NessusdVer == "1.1":
PlugName = 0
else:
PlugName = 1
##
# Kill the very first and last lines - they are just statements from nessusd
# Process all the other lines
for line in ServerString [1:-2]:
RawPlugin = string.split(line, " <|> ")
##
# The following line (commented out) will get the first family word, make all
# lowercase, and strip out trailing "." characters. However, this method also
# makes "gain shell" and "gain root" families look identical.
#
#LineFam = string.split(string.lower(string.split(RawPlugin [6]) [0]), ".")
[0]
##
# ...so, instead, we'll just lowercase everything and go with that.
# However, this method worries me because problems might occur if a non-alpha
# character (.,-_ or something) or typo slips into a plugin's family field.
LineFam = string.lower(RawPlugin [6])
if LineFam == "backdoors" and FamBackdoor == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "backdoors":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "cgi abuses" and FamCGI == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "cgi abuses":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "denial of service" and FamDoS == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "denial of service":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "finger abuses" and FamFinger == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "finger abuses":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "firewalls" and FamFirewall == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "firewalls":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "ftp" and FamFTP == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "ftp":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "gain a shell remotely" and FamShell == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "gain a shell remotely":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "gain root remotely" and FamRoot == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "gain root remotely":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "general" and FamGeneral == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "general":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "misc." and FamMisc == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "misc.":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "nis" and FamNIS == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "nis":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "port scanners" and FamScan == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "port scanners":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "remote file access" and FamFile == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "remote file access":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "rpc" and FamRPC == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "rpc":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "smtp problems" and FamSMTP == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "smtp problems":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "snmp" and FamSNMP == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "snmp":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "useless services" and FamUseless == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "useless services":
f.write(RawPlugin [PlugName] + ' = no\n')
if LineFam == "windows" and FamWindows == "yes":
f.write(RawPlugin [PlugName] + ' = yes\n')
elif LineFam == "windows":
f.write(RawPlugin [PlugName] + ' = no\n')
##
# Write the FooterText and close the file
f.write(FooterText)
f.close()
##
# Close the connection to the nessusd server
tn.close()
#########
## EOF ##
#########