I had to make a new SELinux policy to allow logrotate to handle OSSEC-logs. This is a good methodology to not have to make the policy piecemeal(normally code stops at the first operation that fails so you have to run things once for each type of operation that needs fixing):
<?xml version="1.0" encoding="UTF-8"?> <xccdf:Tailoring xmlns:xccdf="http://checklists.nist.gov/xccdf/1.2" id="xccdf_scap-workbench_tailoring_default"> <xccdf:benchmark href="/tmp/scap-workbench-oMQosO/ssg-rl9-ds.xml"/> <xccdf:version time="2024-03-31T21:06:09">1</xccdf:version> <xccdf:Profile id="xccdf_org.ssgproject.content_profile_stig_customized_001"> <xccdf:version>V1R2</xccdf:version> <xccdf:title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">DISA STIG for Red Hat Enterprise Linux 9 [CUSTOMIZED]</xccdf:title> <xccdf:description xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">This profile contains configuration checks that align to the DISA STIG for Red Hat Enterprise Linux 9 V1R2. <snip> <xccdf:refine-value idref="xccdf_org.ssgproject.content_value_var_time_service_set_maxpoll" selector="18_hours"/> <xccdf:refine-value idref="xccdf_org.ssgproject.content_value_login_banner_text" selector="dod_banners"/> <xccdf:refine-value idref="xccdf_org.ssgproject.content_value_var_authselect_profile" selector="sssd"/> </xccdf:Profile> </xccdf:Tailoring>
I should make a new one based on what I’ve learnt from hardering my jumppoints, which are the only nodes on my network reachable from the internet. They only use VPN and SSH and have OSSEC installed to ban anyone that repeatedly trips various rules. They also have SELinux, which was a bit of pain when I installed Keepalived to move a Virtual IP around but I made the requisite type-enforcement:
module newmodule 1.0;
require { type keepalived_t; type systemd_systemctl_exec_t; class file { execute read }; }
So it’s pretty tightly locked down. OSSEC is doing it’s job:
Sat Apr 20 10:43:26 AM CEST 2024 /var/ossec/active-response/bin/firewall-drop.sh add - 218.92.0.XY 1713602606.209438 5752 Sat Apr 20 10:46:08 AM CEST 2024 /var/ossec/active-response/bin/firewall-drop.sh delete - 43.140.225.XY 1712997913.210209 100001 Sat Apr 20 10:46:08 AM CEST 2024 /var/ossec/active-response/bin/firewall-drop.sh delete - 87.248.226.XY 1712997899.208567 100001 Sat Apr 20 10:46:08 AM CEST 2024 /var/ossec/active-response/bin/firewall-drop.sh add - 185.196.8.XY 1713602768.210489 5752 Sat Apr 20 10:49:09 AM CEST 2024 /var/ossec/active-response/bin/firewall-drop.sh delete - 165.227.166.XY 1712998067.212706 100001
But I wanted it to be really secure. In comes OSCAP which checks hosts against known definitions of security standards. When I ran it originally jumppoint02 was so-so:
Generating remediation in the GUI failed so I had to do it via the CLI which in turn required some changes to the oscap-ssh file:
The yml-file needs to be edited since it isn’t valid YAML but I think that’s easy enough to fix. I ran the test again:
I checked things that were Failed and they all checked out so I’m not sure why they show up as failed here. In fairness it sometimes has the wrong path to files(it seems not to understand that /etc/sudoers defaults propagate to defined users).
Not the IDs mentioned in the original file, not even the one we based our tailoring stuff on:
[user@openscap ~]$ oscap info /usr/share/xml/scap/ssg/content/ssg-rl9-ds.xml
Document type: Source Data Stream
Imported: 2024-06-27T17:52:11
Stream: scap_org.open-scap_datastream_from_xccdf_ssg-rhel9-xccdf.xml
Generated: (null)
Version: 1.3
Checklists:
Ref-Id: scap_org.open-scap_cref_ssg-rhel9-xccdf.xml
WARNING: Datastream component 'scap_org.open-scap_cref_security-data-oval-v2-RHEL9-rhel-9.oval.xml.bz2' points out to the remote 'https://access.redhat.com/security/data/oval/v2/RHEL9/rhel-9.oval.xml.bz2'. Use '--fetch-remote-resources' option to download it.
WARNING: Skipping 'https://access.redhat.com/security/data/oval/v2/RHEL9/rhel-9.oval.xml.bz2' file which is referenced from datastream
Status: draft
Generated: 2024-02-26
Resolved: true
Profiles:
Title: ANSSI-BP-028 (enhanced)
Id: xccdf_org.ssgproject.content_profile_anssi_bp28_enhanced
Title: ANSSI-BP-028 (high)
Id: xccdf_org.ssgproject.content_profile_anssi_bp28_high
Title: ANSSI-BP-028 (intermediary)
Id: xccdf_org.ssgproject.content_profile_anssi_bp28_intermediary
Title: ANSSI-BP-028 (minimal)
Id: xccdf_org.ssgproject.content_profile_anssi_bp28_minimal
Title: CCN Red Hat Enterprise Linux 9 - Advanced
Id: xccdf_org.ssgproject.content_profile_ccn_advanced
Title: CCN Red Hat Enterprise Linux 9 - Basic
Id: xccdf_org.ssgproject.content_profile_ccn_basic
Title: CCN Red Hat Enterprise Linux 9 - Intermediate
Id: xccdf_org.ssgproject.content_profile_ccn_intermediate
Title: CIS Red Hat Enterprise Linux 9 Benchmark for Level 2 - Server
Id: xccdf_org.ssgproject.content_profile_cis
Title: CIS Red Hat Enterprise Linux 9 Benchmark for Level 1 - Server
Id: xccdf_org.ssgproject.content_profile_cis_server_l1
Title: CIS Red Hat Enterprise Linux 9 Benchmark for Level 1 - Workstation
Id: xccdf_org.ssgproject.content_profile_cis_workstation_l1
Title: CIS Red Hat Enterprise Linux 9 Benchmark for Level 2 - Workstation
Id: xccdf_org.ssgproject.content_profile_cis_workstation_l2
Title: DRAFT - Unclassified Information in Non-federal Information Systems and Organizations (NIST 800-171)
Id: xccdf_org.ssgproject.content_profile_cui
Title: Australian Cyber Security Centre (ACSC) Essential Eight
Id: xccdf_org.ssgproject.content_profile_e8
Title: Health Insurance Portability and Accountability Act (HIPAA)
Id: xccdf_org.ssgproject.content_profile_hipaa
Title: Australian Cyber Security Centre (ACSC) ISM Official
Id: xccdf_org.ssgproject.content_profile_ism_o
Title: Protection Profile for General Purpose Operating Systems
Id: xccdf_org.ssgproject.content_profile_ospp
Title: PCI-DSS v4.0 Control Baseline for Red Hat Enterprise Linux 9
Id: xccdf_org.ssgproject.content_profile_pci-dss
Title: DISA STIG for Red Hat Enterprise Linux 9
Id: xccdf_org.ssgproject.content_profile_stig
Title: DISA STIG with GUI for Red Hat Enterprise Linux 9
Id: xccdf_org.ssgproject.content_profile_stig_gui
Referenced check files:
ssg-rhel9-oval.xml
system: http://oval.mitre.org/XMLSchema/oval-definitions-5
ssg-rhel9-ocil.xml
system: http://scap.nist.gov/schema/ocil/2
security-data-oval-v2-RHEL9-rhel-9.oval.xml.bz2
system: http://oval.mitre.org/XMLSchema/oval-definitions-5
Checks:
Ref-Id: scap_org.open-scap_cref_ssg-rhel9-oval.xml
Ref-Id: scap_org.open-scap_cref_ssg-rhel9-ocil.xml
Ref-Id: scap_org.open-scap_cref_ssg-rhel9-cpe-oval.xml
Ref-Id: scap_org.open-scap_cref_security-data-oval-v2-RHEL9-rhel-9.oval.xml.bz2
Dictionaries:
Ref-Id: scap_org.open-scap_cref_ssg-rhel9-cpe-dictionary.xml
I’m impressed with Yubikeys and have tinkered a bit with setting up a Linux workstation to use them. The pièce de résistance is requiring two of three Yubikeys to decrypt a system disk. Adding the Yubikey as a second factor to authentication and lock user sessions when a Yubikey is removed is also useful.
Majority unlock for LUKS-encrypted disks
LUKS allows us to have up to 8 passwords for a single disk. Let’s think of how we might use this to allow any two users from a set of three to start the computer by unlocking the encrypted drive. We have three people: A, B and C. They have a password each:
A => passwordA
B => passwordB
C => passwordC
To require two users to unlock the disk we must make every password a combination of two passwords:
Slot 1 => passwordApasswordB
Slot 2 => passwordApasswordC
Slot 3 => passwordBpasswordC
The users would here have to remember their internal ordering since we don’t have a slot with passwordCpasswordB for instance. LUKS will try a provided password against all slots so if two users enter the password(in the right order) the disk will be unlocked. Now we add Yubikeys to the mix which helps us a bit since that allows the scripts to order things based on the serials of each user’s Yubikey. I’ve swiped a lot of code from this suite of tools: https://github.com/cornelinux/yubikey-luks
Indeed I just installed it, replaced /usr/share/yubikey-luks/ykluks-keyscript and made my own enroll-script so this is little more than a hack layered on top of yubikey-luks.
To enroll three Yubikeys we first have to enable challenge-response mode which is basically just “encrypt incoming data with a secret key and return the output”.
#!/bin/bash
if [ -z $1 ]; then
echo "You must provide a disk name as an argument. Example: /dev/sda3." 1>&2
exit 1
fi
DISK=$1
if [ "$(id -u)" -ne 0 ]; then
echo "You must be root." 1>&2
exit 1
fi
declare -a STEPS=(0 1 2)
declare -a KEYSERIAL
declare -a KEYPASS
for INDX in ${STEPS[@]};
do
echo "Index: $INDX"
COUNTER=10
while [ "$COUNTER" -gt 1 ];
do
sleep 0.5
COUNTER=$((COUNTER-1))
if ykinfo -n$INDX -q -2;
then
echo "Success!"
break
else
echo "No YubiKey found."
fi
done
SERIAL=$(ykinfo -s -n$INDX | cut -d ' ' -f2)
echo "Enter challenge(password) for key $SERIAL: "
read -s PW
KEYSERIAL[$INDX]="$SERIAL"
KEYPASS[$SERIAL]=$(printf %s "$PW" | ykchalresp -n$INDX -2 -i- 2>/dev/null || true)
done
SORTEDSERIALS=$(for K in ${!KEYPASS[@]};
do
echo $K;
done | sort)
declare -a PASSWORDS
INDX=0
for K in $SORTEDSERIALS;
do
echo "$K => ${KEYPASS[$K]}";
PASSWORDS[$INDX]=${KEYPASS[$K]};
INDX=$((INDX+1))
done
declare -a COMBINATIONS
COMBINATIONS[0]="${PASSWORDS[0]}${PASSWORDS[1]}"
COMBINATIONS[1]="${PASSWORDS[0]}${PASSWORDS[2]}"
COMBINATIONS[2]="${PASSWORDS[1]}${PASSWORDS[2]}"
OLD=$(/lib/cryptsetup/askpass "Please provide an existing passphrase. This is NOT the passphrase you just entered, this is the passphrase that you currently use to unlock your LUKS encrypted drive:")
SLOTS=$(seq 1 3)
for SLOT in $SLOTS;
do
printf '%s\n' "$OLD" "${COMBINATIONS[$SLOT-1]}" "${COMBINATIONS[$SLOT-1]}" | cryptsetup --key-slot="$SLOT" luksAddKey "$DISK" 2>&1;
SLOT=$((SLOT+1))
done
This is for a total of 3 users with their own keys. It could be made to handle 4 but 5 keys leaves too many permutations to fit into 8 slots. Execution looks like this:
root@yktest2:~# ./ykluks-enroll.sh /dev/sda3
Index: 0
1
Success!
Enter challenge(password) for key 24130422: [password entered]
Index: 1
1
Success!
Enter challenge(password) for key 19652688: [password entered]
Index: 2
1
Success!
Enter challenge(password) for key 23882290: [password entered]
Now we need to introduce a key script /usr/share/yubikey-luks/ykluks-keyscript:
#!/bin/bash
#
#
message()
{
if [ -x /bin/plymouth ] && plymouth --ping; then
plymouth message --text="$*"
else
echo "$@" >&2
fi
return 0
}
# source for log_*_msg() functions, see LP: #272301
if [ -e /scripts/functions ] ; then
. /scripts/functions
else
. /usr/share/initramfs-tools/scripts/functions
fi
if [ -z "$cryptkeyscript" ]; then
cryptkey="Unlocking the disk $cryptsource ($crypttarget)\\nEnter passphrase: "
if [ -x /bin/plymouth ] && plymouth --ping; then
cryptkeyscript="plymouth ask-for-password --prompt" cryptkey=$(printf '%s' "$cryptkey")
else
cryptkeyscript="/lib/cryptsetup/askpass"
fi
fi
check_yubikey_present="$(ykinfo -n0 -q -2)"
check_yubikey2_present="$(ykinfo -n1 -q -2)"
if [ "$check_yubikey_present" = "1" ]; then
N0=$(ykinfo -n0 -s | cut -d ' ' -f 2)
if [ "$check_yubikey2_present" = "1" ]; then
N1=$(ykinfo -n1 -s | cut -d ' ' -f 2)
if [ "$N0" -lt "$N1" ];
then
declare -a ORDER=(0 1)
else
declare -a ORDER=(1 0)
fi
else
PW="$($cryptkeyscript "Please enter disk password: ")"
printf '%s' "$PW"
fi
else
PW="$($cryptkeyscript "Please enter disk password: ")"
printf '%s' "$PW"
fi
FINALPW=""
for INDX in "${ORDER[@]}";
do
SERIAL=$(ykinfo -n$INDX -s)
PW="$($cryptkeyscript "Please enter challenge for YubiKey $SERIAL: ")"
R="$(printf %s "$PW" | ykchalresp -n$INDX -2 -i- 2>/dev/null || true)"
message "Retrieved the response from Yubikey $SERIAL"
FINALPW="$FINALPW$R"
done
printf '%s' "$FINALPW"
exit 0
Oh, right! I had to add bash to initramfs since my use of arrays isn’t compatible with dash which is what Ubuntu typically includes. So add this to /usr/share/initramfs-tools/hooks/yubikey-luks:
cp /usr/bin/bash "${DESTDIR}/bin/bash"
Then run update-initramfs -u
Yubikey U2F on authentication
Install libpam-u2f and pamu2fcfg packages:
apt install libpam-u2f pamu2fcfg
Then add this line to the bottom of /etc/pam.d/common-auth:
Include nouserok to allow users without a Yubikey to log in, i.e. only apply the requirement for those users included in /etc/u2f_mappings: https://developers.yubico.com/pam-u2f/
Which bring us to adding U2F signatures to authfile. The user can run this:
cjp@yktest2:~$ pamu2fcfg
Enter PIN for /dev/hidraw2:
cjp:77hsMUYzPD0poXbu51/TWGW6roJ31F35G01JoiEskczwxqOvzb5zTgLsnWWo2nO0MmZ6L7erxJz2DufhQDuCs9GEQ==,Wrg4zmgQedALIQCBYTAxoIq/bd/Se2tqtOvVn6JdQmezN05Gt3qLmFGvMA7iXV6u2OHN/mQosg/46/LyIoY9gnow==,es256,+presence
And then the admin can add the generated line to /etc/u2f_mappings.
I can’t get it to trigger based on ATTRS which seems reasonable since the device is disconnected when the rule is run. Also loginctl lock-sessions only work for some display managers but works for gdm3+gnome.
Let’s say we have a big company with lots of servers, providing services to lots and lots of customers. Where should they store their owns passwords? A centralized system like LDAP and enforcement of 2-factor authentication is appropriate but what about the encryption keys for financial data? What about administrative overrides for network equipment? If the network is down, how can you let people log in to a router to fix it if the router can’t check the user logging in against the LDAP server? We need break glass accounts and the like.
So there will need to be some repository of sensitive data that is rarely needed. I think we can print it on paper! It has very predictable deterioration properties, unlike electronic devices that can go from 100% functional to 100% completely fried in a nanosecond due to an unfortunate cosmic ray hitting just the wrong atom*. It’s also highly resistant to hackers. The Israeli intelligence service is said to keep their most sensitive data on paper only.
But do we really want to keep these super-admin overrides on a bunch of paper where someone can just flip through them and take pictures of them with their smart phone? No, that would be bad. I have a proposal:
I’d recommend generating these kinds of passwords for sets of devices. You buy ten new switches? Generate admin passwords for those ten and print them out on paper. Two papers. The first half of each password goes on one page. The other half on another. The people doing the work can check that the two pages contain the complete passwords so we know they will work when needed. It’s kind of hard for people to remember ten 20-character random passwords that they’ve seen once, so it’s not a big security issue that the passwords are checked. We want to balance security with reliable access in an emergency.
Now things start to get a bit administrative. I suggest each paper is placed in a sealed envelope with a tamper evident label. I bought some from Amazon just to try it out:
Before I “opened” it the blue color was uninterrupted. Afterwards the white text appeared(I think it’s supposed to say “Void, opened”) and I’d struggle to get the things back to it’s original condition. Note the serial number. I wouldn’t trust the manufacturer to never reuse serial numbers. But it’s not in their interest to offer these labels to people with whatever serial numbers the customer asks for, so it’s not trivial to get your hands on duplicates. You’d probably have to buy an excessive number of labels to have a chance of getting duplicates.
Illustrations with a single password for simplicity:
Now we have our password-halves in sealed envelopes and we can lock them away. Preferably in two locations where no one person has access to both. And the password could only be used with more than one participant involved. The use case would be something like this:
Bob: Uhm, boss? Boss: Yeah, what's up? Bob: Uhm, we need to access the snapshots and binlogs for the database server that handles financial transactions. Boss: What happened? Bob: A bad patch was rolled out that deleted a bunch of stuff. We need to restore the data from snapshots and a binlog replay. Boss: Okey, do it! Bob: We need your help. Boss: How? I don't even know what a binlog is. I've heard you talking about it but that's it. Bob: Well, it turns out the normal decoding stuff isn't working. You know, with the hardware tokens? Boss: Sounds vaguely familiar. Oh, now I get it! We need the override password from the safe? Bob: Well, two safes. One half is in one safe, the other half is in another safe. Here's a write-up of what we want and why. Boss(reads paper): Okey, but we need one more person here. Bob: Oh, right! Jim, get in here! Jim: What? Bob: We need you to sign the paper. It has to be two people asking for the override before we can go ahead. Jim: All right, what do I need to do? Bob: Do we need the override password for the snapshots and binlogs of the financial transaction server? Jim(looking confused why the question is being asked): Yes... Bob: Then sign on the dotted line here.
Jim signs.
Boss: Good, then I'll sign it and we can get cracking.
Department A: Bob: Hi! We need the ledger over secure envelopes in department B. Boss(whispering to Bob): Why doesn't the ledger at department A cover their own envelopes? Bob: Because then they could fiddle with both the ledger and the envelopes and we would none the wiser. If department B wants to open an envelope and edit the ledger to hide that transgression, they need help from department A. Boss(thinking): Okey, makes sense. Also, you could just call it "rule breaking" rather than "transgression". It would be easier.
Bob shrugs.
Bob(grabbing ledger): Thanks!
Department B: Bob: Hi! We need a sealed envelope... (looking in ledger). Number 1203. Harry: Okey. Hi boss! Boss: Hi. Harry: You have the paperwork? Bob: Yeah, here it is. Harry: Good. I'll just get and fetch the envelope. Bob: Oh, we need the ledger for envelopes for department A. Harry(looking at the paperwork again): Sure, I'll get that too.
Harry comes back with the two items.
Harry: May I have the ledger? Harry(talking to himself, comparing records): 488901 from 2023-04-22. Yeah, that's good. I'll just cross it out in the ledger. There! Bob: Can I see it now? I'll need to write down password 7. Harry: Here you go. Bob: Thanks, got it. Will you seal it back up? Harry: Yes, I'll get a new label and envelope.
Harry seals the envelope with a new label.
Harry: Label number 489102 and today is 2023-07-03. I'll sign the label and add a new ledger entry.
Bob and his boss look on as things are prepared.
Harry: Done.
Bob: Good, we'll be back shortly with the ledger.
Department A is the same thing. Talk to someone who can fetch the paper, check that no one has accessed the envelope since the last authorized access, etc. The team then returns the ledgers they got from the two departments.
Bob, Jim and their boss all go to a workstation and log in using the secret password. Bob fixes the problem and logs back out again. They all go to a paper-shredder and destroy the copy of the password. The signed document authorising access to the envelopes is marked as "VOID" using a stamp. Job's done!
To be really secure the system that the password grants access to should have a new password set. Several people have seen the current password after all. But this would require printing out a new pair of papers, getting rid of the old ones and so on. For a bank this might be worth the effort and then there should probably be just one password(half) per envelope. For a tech company the simplification shown above is perhaps more appropriate.
I originally conceived of this system when I was thinking about how it could come to pass that a single systems administrator at the NSA could leak thousands of documents. No one person should have that kind of access to sensitive data.
If circumventing access control at the NSA had required a password split up between two safes, using tamper-evident serialized labels recorded in a ledger held by someone else than the custodian of the envelope, I think the leak would have been much less likely. Now, this system is slow and cumbersome. It would never fly for anything approaching standard password management. But for “the keys to the kingdom” at a service provider or a government agency? It might be worth the hassle.
The inspiration is the American two man-rule for handling nuclear weapons which states that such a weapon can’t be left with any one person. Locking it away in a vault? That’s okey. Having two people wheel one out to a waiting bomber? That’s, okey. Letting Bob watch the nuke while Jim goes in to fetch his mittens? No, it’s the two man-rule. I would be remiss for not recommending the Always/Never series about the development of various technologies developed to make handling nuclear weapons more secure.
The tamper-evident label-thing is inspired by how codes on nuclear submarines are stored and handled. Or how they are allegedly stored and handled, it’s not like the US navy is doing show-and-tell of exactly how a nuclear weapons launch would work. One thing that I’m thinking about is if envelopes can be resealed if you cut them open at the sides. I watched a video about research done by a US lab working with nuclear materials on tamper evident packaging and I don’t think they’d be impressed with “this envelope doesn’t look like it was cut open and then resealed using wet paper, heat and some pressure. See for instance this document published by the IAEA about testing various storage devices tested by Sandia: https://inis.iaea.org/collection/NCLCollectionStore/_Public/27/020/27020417.pdf
Sandia was also heavily involved in nuclear weapons security improvements as shown in the documentary series mentioned earlier. It’s a subject of some importance as can be seen in this short video which also covers civilian use of nuclear fuel and how to avoid diversion of nuclear materials.
Anyway, metal foil seems like a reasonable alternative to paper envelopes. It appears quite difficult to reseal without it being evident. By the way, tamper evident is preferred over tamper resistant because the latter isn’t feasible. It’s better to say “yes, with enough time any barrier can be overcome but we’ve made sure that it’s obvious that someone has opened the item”.
An email provider will want to prevent brute force hacking attempts against their servers. Otherwise it will be too easy for hackers to keep guessing which passwords are used for various accounts and eventually break into them. Are there tools for this in the Linux ecosystem? Sure, there’s the Login Failure Daemon(lfd) that’s part of the ConfigServer Security & Firewall(csf). It counts how many failed login attempts are made from an IP address and when a certain limit has been reached within a certain time it blocks the IP address, for a certain time. There’s also OSSEC which is closer to my heart as well as the up-and-coming Imunify.
Before looking at how these measure up it’s worth to point out a few things:
People choose bad passwords
People screw things
Email clients are often extremely badly coded
Depending on your environment you can enforce some password complexity to deal with item 1. Item 2 is impossible to guard yourself again. People will connect multiple devices to a single IMAP accounts in 2016 and upon changing the password in 2019 have no clue that they have the account connected to anything but their smartphone. At which point the detective work begins: what’s trying to log in to my email account and getting me blocked every fifteen minutes?
The third point is the most aggravating. Why would anyone write an email client that keeps sending login attempts to an email account thousands and thousands of times while being constantly told by the server: “Login credentials invalid”. It’s not like a programmer has to guess what the magical error message from the server is going to be because that’s standardized! See: https://tools.ietf.org/html/rfc5530
But developers big and small continue making email clients that just keep spamming the server with the same login credentials, sometimes at a rate of once a second. So how do we deal with this at the server level? Ideally we would never block actual customers trying to login to their own accounts even when they keep sending the wrong password. But the correct username and password combination is precisely how we distinguish between valid users and everyone else.
The obvious answer is to block those IP-addresses that keep guessing new passwords all the time and not block those that just keep using the same credentials over and over again. In Dovecot the setting auth_verbose_passwords=sha1 can be used to display the sha1 hashsum of passwords used in failed login attempts. Courier has DEBUG_LOGIN=2 though that logs the password in plain text. Login failure daemon can only be made to use this information by rewriting the Perl script that is lfd.
OSSEC might be possible to configure this way but I’m not sure. There’s no ready-made field “password” that you can include and no rule “not same password”. There is for source IP and a rule “same_srcip”, but not for password. I’m not necessarily blaming the developers of lfd and OSSEC for not writing their software to handle a world in which email clients are written by monkeys. But given the whole monkeys-writing-software situation we’re in, they fall short.
Imunify doesn’t try to factor in the password used in a failed login attempt either but does at least have some intelligent alternatives. Most notably that a customer logging on to something like cPanel whitelists their IP address. I would propose that a successful login to any email account on a server should also lead the IP address to be whitelisted on that server.
If successful login to an email account from IP address A, ignore failed logins for 1 day.
This does leave open the possibility of a valid customer trying to hack other accounts on the server with his own account on it. This seems to me a very small risk but one could be more restrictive:
If successful login to any email account x@y.z from IP address A, ignore any failed login attempts to email accounts ending with @y.z.
That wouldn’t work with Imunify white lists because it doesn’t have that kind of granularity. I think we must conclude that we have little choice but to write our own code for handling email login failures and if we’re going to do that then we might as well do it right and analyze a log file with information of the password used.
With quite a lot of both physical machines and even more virtual machines it can be tricky to keep file permissions on shared storage like Ceph in sync. Adding two users in the wrong order on a node can give them the wrong UIDs. This was less of a problem when I accessed files via CIFS/Samba but now I only do that for Windows-machines. Linux-machines use CephFS so UIDs and GIDs have to be correct on all nodes. Therefor I use FreeIPA to keep this stuff in sync. I spent what felt like months trying to get a multi-master LDAP cluster to work – though it might have been a weekend – but gave up.
Turns out FreeIPA has built-in support for replication of data. So I have freeipa01 running on a Ceph RBD disk allowing me to keep it running even as physical nodes are rebooted. freeipa02 is run on a local disk on one of my servers and it’s there in case Ceph stops working. FreeIPA also handles DNS which it replicates down to Bind daemons on three virtual machines that are also running on local storage. The DNS function NOTIFY is used to keep replication lag down when syncing down to the bind slaves.
What else does FreeIPA do? Kerberos and single-sign-on, currently only used for SSH. Certificate issuing, standard centralized PAM log on against the central user directory. I’ve come to use it quite a lot.