{"id":91898,"date":"2019-04-12T17:19:29","date_gmt":"2019-04-12T17:19:29","guid":{"rendered":"http:\/\/www.sickgaming.net\/blog\/2019\/04\/12\/linux-server-hardening-using-idempotency-with-ansible-part-2\/"},"modified":"2019-04-12T17:19:29","modified_gmt":"2019-04-12T17:19:29","slug":"linux-server-hardening-using-idempotency-with-ansible-part-2","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2019\/04\/12\/linux-server-hardening-using-idempotency-with-ansible-part-2\/","title":{"rendered":"Linux Server Hardening Using Idempotency with Ansible: Part 2"},"content":{"rendered":"<div><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/04\/linux-server-hardening-using-idempotency-with-ansible-part-2.jpg\" class=\"ff-og-image-inserted\"><\/div>\n<p><span><span>In the first part of this series, we introduced something called idempotency, which can provide the ongoing improvements to your server estate\u2019s security posture. In this article, we\u2019ll get a little more hands-on with a look at some specific Ansible examples.<\/span><\/span><\/p>\n<h3><span><span>Shopping List<\/span><\/span><\/h3>\n<p><span><span>You will need some Ansible experience before being able to make use of the information that follows. Rather than run through the installation and operation of Ansible let\u2019s instead look at some of the idempotency playbook\u2019s content.<\/span><\/span><\/p>\n<p><span><span>As mentioned earlier there might be hundreds of individual system tweaks to make on just one type of host so we\u2019ll only explore a few suggested Ansible tasks and how I like to structure the Ansible role responsible for the compliance and hardening. You have hopefully picked up on the fact that the devil is in the detail and you should absolutely, unequivocally, understand to as high a level of detail as possible, about the permutations of making changes to your server OS.<\/span><\/span><\/p>\n<p><span><span>Be aware that I will mix and match between OSs in the Ansible examples that follow. Many examples are OS agnostic but as ever you should pay close attention to the detail. Obvious changes like \u201capt\u201d to \u201cyum\u201d for the package manager is a given.<\/span><\/span><\/p>\n<p><span><span>Inside a \u201ctasks\u201d file under our Ansible \u201chardening\u201d role, or whatever you decide to name it, these named tasks represent the areas of a system with some example code to offer food for thought. In other words, each section that follows will probably be a single YAML file, such as \u201caccounts.yml\u201d, and each will have with varying lengths and complexity. <\/span><\/span><\/p>\n<p><span><span>Let\u2019s look at some examples with ideas about what should go into each file to get you started. The contents of each file that follow are just the very beginning of a checklist and the following suggestions are far from exhaustive.<\/span><\/span><\/p>\n<h4><span><span>SSH Server<\/span><\/span><\/h4>\n<p><span><span>This is the application that almost all engineers immediately look to harden when asked to secure a server. It makes sense as SSH (the OpenSSH package in many cases) is usually only one of a few ports intentionally prised open and of course allows direct access to the command line. The level of hardening that you should adopt is debatable. I believe in tightening the daemon as much as possible without disruption and would usually make around fifteen changes to the standard OpenSSH server config file, \u201csshd_config\u201d. These changes would include pulling in a MOTD banner (Message Of The Day) for legal compliance (warning of unauthorised access and prosecution), enforcing the permissions on the main SSHD files (so they can\u2019t be tampered with by lesser-privileged users), ensuring the \u201croot\u201d user can\u2019t log in directly, setting an idle session timeout and so on. <\/span><\/span><\/p>\n<p><span><span>Here\u2019s a very simple Ansible example that you can repeat within other YAML files later on, focusing on enforcing file permissions on our main, critical OpenSSH server config file. Note that you should carefully check every single file that you hard-reset permissions on before doing so. This is because there are horrifyingly subtle differences between Linux distributions. Believe me when I say that it\u2019s worth checking first.<\/span><\/span><\/p>\n<p><span><span>name: Hard reset permissions on sshd server file<\/span><\/span><\/p>\n<p><span><span>file: owner=root group=root mode=0600 path=\/etc\/ssh\/sshd_config<\/span><\/span><\/p>\n<p><span><span>To check existing file permissions I prefer this natty little command for the job:<\/span><\/span><\/p>\n<pre>\n<span><span>$ stat -c \"%a %n\" \/etc\/ssh\/sshd_config<\/span><\/span> <span><span>644 \/etc\/ssh\/sshd_config<\/span><\/span><\/pre>\n<p><span><span>As our \u201cstat\u201d command shows our Ansible snippet would be an improvement to the current permissions because 0600 means only the \u201croot\u201d user can read and write to that file. Other users or groups can\u2019t even read that file which is of benefit because if we\u2019ve made any mistakes in securing SSH\u2019s config they can\u2019t be discovered as easily by less-privileged users.<\/span><\/span><\/p>\n<h4><span><span>System Accounts<\/span><\/span><\/h4>\n<p><span><span>At a simple level this file might define how many users should be on a standard server. Usually a number of users who are admins have home directories with public keys copied into them. However this file might also include performing simple checks that the root user is the only system user with the all-powerful superuser UID 0; in case an attacker has altered user accounts on the system for example.<\/span><\/span><\/p>\n<h4><span><span>Kernel<\/span><\/span><\/h4>\n<p><span><span>Here\u2019s a file that can grow arms and legs. Typically I might affect between fifteen and twenty <\/span><span>sysctl<\/span><span> changes on an OS which I\u2019m satisfied won\u2019t be disruptive to current and, all going well, any future uses of a system. These changes are again at your discretion and, at my last count (as there\u2019s between five hundred and a thousand configurable kernel options using sysctl on a Debian\/Ubuntu box) you might opt to split off these many changes up into different categories. <\/span><\/span><\/p>\n<p><span><span>Such categories might include network stack tuning, stopping core dumps from filling up disk space, disabling IPv6 entirely and so on. Here\u2019s an Ansible example of logging network packets that shouldn\u2019t been routed out onto the Internet, namely those packets using spoofed private IP Addresses, called \u201cmartians\u201d.<\/span><\/span><\/p>\n<p><span><span>name: Keep track of traffic that shouldn\u2019t be routed onto the Internet<\/span><\/span><\/p>\n<p><span><span>lineinfile: dest=&#8221;\/etc\/sysctl.conf&#8221; line=&#8221;{{item.network}}&#8221; state=present<\/span><\/span><span><span> <\/span><\/span><\/p>\n<p><span><span>with_items:<\/span><\/span><span><span> <\/span><\/span><\/p>\n<p><span><span>&#8211; { network: &#8216;net.ipv4.conf.all.log_martians = 1&#8217; }<\/span><\/span><span><span> <\/span><\/span><\/p>\n<p><span><span>&#8211; { network: &#8216;net.ipv4.conf.default.log_martians = 1&#8217; }<\/span><\/span><\/p>\n<p><span><span>Pay close attention that you probably don\u2019t want to use the file \u201c\/etc\/sysctl.conf\u201d but create a custom file under the directory \u201c\/etc\/sysctl.d\/\u201d or similar. Again, check your OS\u2019s preference, usually in the comments of the pertinent files. If you\u2019ve not seen martian packets being enabled before then type \u201cdmesg\u201d (sometimes only as the \u201croot\u201d user) to view kernel messages and after a week or two of logging being in place you\u2019ll probably see some traffic polluting your logs. It\u2019s much better to know how attackers are probing your servers than not. A few log entries for reference can only be of value. When it comes to looking after servers, ignorance is certainly not bliss.<\/span><\/span><\/p>\n<h4><span><span>Network<\/span><\/span><\/h4>\n<p><span><span>As mentioned you might want to include hardening the network stack within your kernel.yml file, depending on whether there\u2019s many entries or not, or simply for greater clarity. For your network.yml file have a think about stopping old-school broadcast attacks flooding your LAN and ICMP oddities from changing your routing in addition.<\/span><\/span><\/p>\n<h4><span><span>Services<\/span><\/span><\/h4>\n<p><span><span>Usually I would stop or start miscellaneous system services (and potentially applications) within this Ansible file. If there weren\u2019t many services then rather than also using a \u201ccron.yml\u201d file specifically for \u201ccron\u201d hardening I\u2019d include those here too.<\/span><\/span><\/p>\n<p><span><span>There\u2019s a bundle of changes you can make around cron\u2019s file permissions etc. If you haven\u2019t come across it, on some OSs, there\u2019s a \u201ccron.deny\u201d file for example which blacklists certain users from accessing the \u201ccrontab\u201d command. Additionally you also have a multitude of cron directories under the \u201c\/etc\u201d directory which need permissions enforced and improved, indeed along with the file \u201c\/etc\/crontab\u201d itself. Once again check with your OS\u2019s current settings before altering these or \u201cbad things\u201d \u2122 might happen to your uptime. <\/span><\/span><\/p>\n<p><span><span>In terms of miscellaneous services being purposefully stopped and certain services, such as system logging which is imperative to a healthy and secure system, have a quick look at the Ansible below which I might put in place for syslog as an example.<\/span><\/span><\/p>\n<p><span><span>name: Insist syslog is definitely installed (so we can receive upstream logs)<\/span><\/span><\/p>\n<p><span><span>apt: name=rsyslog state=present<\/span><\/span><\/p>\n<p><span><span>name: Make sure that syslog starts after a reboot<\/span><\/span><\/p>\n<p><span><span>service: name=rsyslog state=started enabled=yes<\/span><\/span><\/p>\n<h4><span><span>IPtables<\/span><\/span><\/h4>\n<p><span><span>The venerable Netfilter which, from within the Linux kernel offers the IPtables software firewall the ability to filter network packets in an exceptionally sophisticated manner, is a must if you can enable it sensibly. If you\u2019re confident that each of your varying flavours of servers (whether it\u2019s a webserver, database server and so on) can use the same IPtables config then copy a file onto the filesystem via Ansible and make sure it\u2019s always loaded up using this YAML file.<\/span><\/span><\/p>\n<p><span><span>Next time, we\u2019ll wrap up our look at specific system suggestions and talk a little more about how the playbook might be used.<\/span><\/span><\/p>\n<p><span><span>Chris Binnie\u2019s latest book, Linux Server Security: Hack and Defend, shows you how to make your servers invisible and perform a variety of attacks. You can find out more about DevSecOps, containers and Linux security on his website: <\/span><span><a href=\"https:\/\/www.devsecops.cc\/\">https:\/\/www.devsecops.cc<\/a><\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the first part of this series, we introduced something called idempotency, which can provide the ongoing improvements to your server estate\u2019s security posture. In this article, we\u2019ll get a little more hands-on with a look at some specific Ansible examples. Shopping List You will need some Ansible experience before being able to make use [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":91899,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40],"tags":[],"class_list":["post-91898","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux-freebsd-unix"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/91898","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=91898"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/91898\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/91899"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=91898"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=91898"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=91898"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}