OpenVAS Change Request #20: OpenVAS: Improve SSH Credentials ManagementStatus: Voted +4. Done, implemented in SVN trunk, revision 2408.
To make the management of SSH login information easier and more transparent to the user.
To allow specification of SSH Credentials on a per-host basis.
Various NVTs are able to use SSH login information provided by the user to access a remote host and retrieve information from this host. Currently, the user has to create the SSH keys needed himself and provided the appropriate NVT with the filename of his key file, his passphrase and so on.
Additionally, it is not possible to set more than one SSH key. This forces users to use a single key when they want to scan a large number of hosts.
These issues alone make the process more complex and error-prone than necessary. This change request aims to simplify the process by integrating client side key management into OpenVAS-Client, by improving the handling of login credentials in the plugin preferences and in the client-server communication and by ultimately allowing users to select the appropriate keys on a per-host basis.
As a first step, this change request would add a new "type" option to the NASL command "script_add_preference". Existing types for NVT preferences are "checkbox", "entry", "password", "radio" and "file". The new key ("sshlogin") would cause the client GUI to display a dropdown menu containing all SSH keys available to client. Upon execution of the scan, the client would transmit the selected key to the server.
Additionally, the client would gain functionality to generate and manage SSH keys via the GUI.
The next step would be allowing SSH key selection on a per-host basis. Instead of specifying one SSH key via a dropdown menu, it would become possible to select an arbitratry number out of the SSH keys known to the client and associate them with one or more target hosts or netmasks.
If this mechanism proves useful in improving the handling of SSH credentials, it could be extended to other credentials, like SMB, FTP or HTTP login information.
Design and ImplementationThis change Request was implemented in four steps:
- (client + server) Extend NASL script_add_preference types by "sshlogin". (Done)
- (client) Offer list of known keys. (Done)
- (client) Add key management facility. (Done)
- (client + server) Allow ssh-key selection on a per-host basis. (Done)
For convenience, descriptions of the 4 steps are somewhat merged. Although technically incorrect, the code and the following description use the words 'host' and 'targets' synonymously.
New modules have been added to openvas-client, modules in src/openvas-lib have also been added to openvas-libraries.
- src/openvas-lib/openvas_ssh_login manages a struct that keeps login relevant information.
- src/gui/ssh_key_info_form manages a struct that keeps gtk widgets to display openvas_ssh_logins.
- src/gui/ssh_keys_dialog shows a dialog to display information about all keys and the possibility to add new ones.
- src/util/openvas_ssh_key_create with functions that have to to with creation and deletion of the private and public key files.
- src/openvas-lib/hash_table_file provides a simple mechanism to turn 'string' GHashTables into easily readable files and vice versa.
- src/gui/nvt_pref_sshlogin holds what is needed to display and manipulate key-per-host settings in the gui.
A new preference type "sshlogin" has been defined in openvas-libraries/include/libopenvas.h (where the types currently lay around but are never used) and openvas-client/nessus/comm.h. It is not only value- less (although a dummy-value for it has to be created to allow the clients mechanisms to work) but also different from other preference types as its handling is much more hard-wired.
Client: Changes in context module
The client's Context was extended by three fields:
The sshkeys GHashTable maps user-defined names for ssh accounts (e.g. 'Local User - Offices') [key] to instantiations of the openvas_ssh_login struct [value]. This map is valid application-wide (this hash table is supposed to be 'global', meaning that only the global context should have one. It is candidate for being moved out of the context struct). This hash table is created from a file (default: ($OPENVASHOME)/.openvas/.ssh/.logins) at startup and saved to disk when any changes are applied.
gui_sshlogins_per_target is a GtKTable with the widgets to assign logins to targets.
map_target_sshlogin stores this assignment of logins to targets for each context.
Client: OpenVAS SSH Manager
The OpenVAS SSH Manager is a new dialog that can be opened from the settings dialog. It manages the application- wide available openvas_ssh_login structs, displays the information of single logins and allows deletion and creation of openvas_ssh_logins together with the key files. Its 'store' is the Global contexts sshkeys.
If created with the OpenVAS SSH Manager, public and private key files are placed in ($OPENVASHOME)/.openvas/.ssh . The same directory contains a '.logins' file that holds information about all known openvas_ssh_login structs (names, comments, passphrases etc.). To create the key files, the OpenVAS SSH Manager currently uses the external ssh-keygen and openssl tools. They are called as described in the OpenVAS compendium.
Client: GUI for the sshlogins preference
The "sshlogin" preference of a nasl script triggers that a GUI to change the mapping logins to targets is added to the 'Credentials' tab (in openvas-client/nessus/prefs_dialog/prefs_dialog_plugins_prefs.c).
Other preferences hook manipulation widgets (e.g. a text box - GtkEntry -) into nested arglists. In an additional step these widgets have to be unpeeled and inspected to result into a string that can be sent as a prefence value to the server and cached locally at client-side. The GUI for the sshlogins preference type works a bit differently. For consistency it is hooked into the nested arglists, but also directly accessible via the (new) current Contexts gui_sshlogins_per_target field. The GUI is a table, where in every row a label and a combobox are shown. The label shows the name of a target (e.g. 'localhost'), the combobox lists the available ssh logins (e.g. 'Local User - Offices' and 'Local User - Server'). An additional row allows to select a login as 'Default'. This same mapping can be found in the current Contexts map_target_sshlogin. When the GUI is built up, it draws its initial data from that hash table. When the user changes the selection of any combobox, the values in the current Context map_target_sshlogin will be updated immidiately.
The table furthermore contains a button to add a pattern. Pattern- definitions allow for '*' and '?' wildcards. Added patterns are displayed like the targets but have a small icon-button next to the label, to remove the pattern again.
Client: Pushing information to the server
Transmitting variable length preference values to the server (see implementation of "radio" type preference) that additionally defines a mapping and includes a variable number of files is difficult with the current mechanisms. To avoid the difficulties and endless string escaping and parsing, a different approach was chosen for the implementation. On client- side the sshlogin- preference is value-less, but all information is available in files. Since it is possible to push any file to the server, the client just pushes the files as they are, including public and private key files.
Server: Receiving files
The server can handle information about ssh logins in much the same way than the client. When receiving a file (in openvasd/ntp_11.c) the server checks the name. If it equals '.logins' or '.host_sshlogins', it creates openvas_shh_login structs and a hash table (like the client does at startup) and indexes them in the globals arglist under the keys MAP_NAME_SSHLOGIN and MAP_HOST_SSHLOGIN_NAME.
Server: Set per-target host-login information
In openvasd/attack.c the extracted method init_host_kb initializes the knowledge base for a single host. When hash tables were registered in the global arglist (see section 'Server: Receiving files'), it looks up the key 'hostname', (to get the corresponding openvas_ssh_login struct) and sets values in the knowledge base accordingly. If no key exists in the hash table that equals the name of the current host, all user-defined patterns are tried to match against the current hostname. If no match is found, the server falls back to the "Default" login definition.
Sending files with the correct names totally bypasses the "preference system" as it is. The server will set the login- information per host regardless of whether a NVT requested it or not. This is just fine if Credentials Management / Local Checks should become a core part of OpenVAS, but needs consideridation if not.
So far, requesting and handling of SSH login information did take place in ssh_authorization.nasl. To switch to a per-target definition of ssh logins this script has to be modified to just request a sshlogins pereference (and do nothing else). It is important that no other script influences the knowledge base entries for login information (currently: Secret/SSH/login, Secret/SSH/passphrase, Secret/SSH/publickey, Secret/SSH/privatekey).A discussion might follow, that is likely to spawn new Change Requests that tackle these issues:
- (jan) We need to fix up the problem that ssh_funcs needs the public key to work properly. In fact, the public key is not necessary and thus should not be part of the sshcredentials.
- (jan) Are we going to support both uname+pw and uname+key+pw? Or should we drop one of them?
- (miachael) If this mechanism proves useful in improving the handling of SSH credentials, it could be extended to other credentials, like SMB, FTP or HTTP login information.
To be done
Netmasks / regular expressions
The initial Change Request mentioned netmasks, but general regular expressions might be more powerful. As of now a tiny subset of regular expressions (glob-style, allowing '*' and '?' wildcards only) is in use (coming from GLib).
It is assumed that the order of lookups in server is fixed and communicated to the user (first check hostname, then check mask/regexp, then fall back to Default). To bullet-proof this, the client would have to check if two given regexps/netmasks are mutually exclusive and warn if not (e.g. 192.168* and 192*12 both match 192.168.4.12). To ease that, the 'Default' should be expressed as a netmask or regexp as well (0.0.0.0 / *).
- Documentation in the OpenVAS- Compendium.
- In the OpenVAS Client changes of the mapping in the Global Settings does not have any effect. Can be fixed in this fashion: The Global Settings Context (GSC) saves its .hostlogins file in the .openvas/ directory (has to ensure it exists). At startup, the GSC picks up its mapping from there (other scopes pick it up from their 'own' directory). When a new scope is born, copy the mapping from the GSC.
- In OpenVAS Client provide a predictable order when listing targets and patterns. Eventually list patterns seperately.
- Clarify when hostname is an actual hostname and when it is an ip adress.
- 2010-01-06 Felix Wolfsteller <firstname.lastname@example.org>:
Updated status as done.
- 2009-02-06 Felix Wolfsteller <email@example.com>:
- 2009-02-06 Felix Wolfsteller <firstname.lastname@example.org>:
Updated implementation details (pattern definitions), TBD entries.
- 2009-02-04 Felix Wolfsteller <email@example.com>:
Updated implementation details.
- 2008-12-17 Felix Wolfsteller <firstname.lastname@example.org>:
Updated implementation details.
- 2008-12-04 Felix Wolfsteller <email@example.com>:
Included comments from Mailinglist.
- 2008-11-20 Michael Wiegand <firstname.lastname@example.org>: