<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>costaskou</title>
    <link href="https://me.costaskou.com/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://me.costaskou.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-12-21T00:00:00+00:00</updated>
    <id>https://me.costaskou.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Eternal Alex Coefficient</title>
        <published>2025-12-21T00:00:00+00:00</published>
        <updated>2025-12-21T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/eternal-alex-coefficient/" type="text/html"/>
        <id>https://me.costaskou.com/articles/eternal-alex-coefficient/</id>
        
        <content type="html">&lt;p&gt;Have you ever sat in a meeting when someone asks, “Didn’t Alex fix this back in 2015?”, and the room falls silent as people do the mental math on how long it’s been since Alex left the company?&lt;&#x2F;p&gt;
&lt;p&gt;Alex left the company years ago, yet his name still guides technical decisions.
The Eternal Alex Coefficient (EAC) offers a straightforward coefficient that measures how often an absent employee’s solutions continue to shape present work.&lt;&#x2F;p&gt;
&lt;p&gt;Define Y as the number of full years that have elapsed since the employee’s departure. Define T as the total number of distinct times that the employee’s name is invoked during the current calendar year.&lt;&#x2F;p&gt;
&lt;p&gt;EAC is &lt;code&gt;EAC = Y × T&lt;&#x2F;code&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;When Bob left seven years ago and was still mentioned three times this quarter, his EAC stands at twenty‑one.
This value grows either because the legend strengthens or because time marches on, a dynamic that rewards both narrative stickiness and organisational forgetfulness.&lt;&#x2F;p&gt;
&lt;p&gt;On a Friday afternoon, two colleagues have a chat about a potential issue. &lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Didn&#x27;t Mary try to solve this in 2020 ?&lt;&#x2F;li&gt;
&lt;li&gt;What happened in the end?&lt;&#x2F;li&gt;
&lt;li&gt;The COVID-19 pandemic. Hadn&#x27;t thought about this problem since.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now you could take this a step further and make it a league or a type of hall of fame. &amp;quot;It has been 5 days since we last mentioned an employee that no longer works here&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Apparently, Walsh and Ungson (1991) proposed a structure for organisational memory&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, of which individuals is one of the &amp;quot;storage bins&amp;quot; of information.
In other words one of the ways that organisations remember how to make better decisions is because of the specific people and their roles.
&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;eternal-alex-coefficient&#x2F;OM-1991.png&quot; alt=&quot;OM-1991-theory.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Normally this isn&#x27;t a problem, if the person still works for the organisation.
If the organisation hasn&#x27;t transitioned to other forms of storing information and the person does not work for the organisation anymore, then that could be problematic.&lt;&#x2F;p&gt;
&lt;p&gt;This could lead to &lt;a href=&quot;https:&#x2F;&#x2F;en.wiktionary.org&#x2F;wiki&#x2F;Chesterton&amp;#x27;s_fence&quot;&gt;Chesteron&#x27;s fence&lt;&#x2F;a&gt; type of scenarios at the very least, where no one knows why a single or multiple individuals made a decision.&lt;&#x2F;p&gt;
&lt;p&gt;Other times the organisation might - almost - &lt;a href=&quot;https:&#x2F;&#x2F;www.reuters.com&#x2F;world&#x2F;us&#x2F;us-fda-asks-fired-scientists-return-including-some-reviewing-musks-neuralink-2025-02-22&#x2F;&quot;&gt;seize to function&lt;&#x2F;a&gt; .&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Walsh, J. P., &amp;amp; Ungson, G. R. (1991). Organizational memory. The Academy of Management Review, 16(1), 57–91. &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How common is security.txt in financial services</title>
        <published>2025-10-16T00:00:00+00:00</published>
        <updated>2025-10-16T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/securitytxt/" type="text/html"/>
        <id>https://me.costaskou.com/articles/securitytxt/</id>
        
        <content type="html">&lt;p&gt;I very matter of factly told a colleague that &lt;code&gt;security.txt&lt;&#x2F;code&gt; is a well-known standard but it&#x27;s not widely used in &amp;quot;major corporations&amp;quot;. In the context of our conversation I took &amp;quot;major corporations&amp;quot; to mean financial services.
I didn&#x27;t have the data on hand to back up the claim.&lt;&#x2F;p&gt;
&lt;p&gt;I compiled a list of 207 financial services domains&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Banks, insurers, pension providers, etc., a bit more heavy UK heavy.&lt;&#x2F;p&gt;
&lt;p&gt;Then I wrote a script to check for the presence of &lt;code&gt;.&#x2F;well-known&#x2F;security.txt&lt;&#x2F;code&gt; or &lt;code&gt;security.txt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Out of 207 domains, &lt;em&gt;18&lt;&#x2F;em&gt; or &lt;em&gt;8.7%&lt;&#x2F;em&gt; had a &lt;code&gt;security.txt&lt;&#x2F;code&gt; in place. I didn&#x27;t parse the contents for compliance to the standard, but research&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; suggests that only a subset of &lt;code&gt;security.txt&lt;&#x2F;code&gt; implementations is compliant. It&#x27;s likely that some of these domains would have blocked my requests and an unknown number of false negative results is skewing the result. &lt;&#x2F;p&gt;
&lt;p&gt;Nonetheless the standard was submitted in 2017 and as of April 2022 it&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc9116&quot;&gt;RFC 9116&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The adoption rate, on a global scale, over time has been steadily increasing since 2020 &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; with more recent analysis in 2025 &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; confirming a steady uptake.&lt;&#x2F;p&gt;
&lt;p&gt;After writing my check, I came across &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;markuta&#x2F;go-security-txt&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;markuta&#x2F;go-security-txt&lt;&#x2F;a&gt; which includes a broader survey and detailed analysis of &lt;code&gt;security.txt&lt;&#x2F;code&gt; adoption.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;costasko&#x2F;e2ced6cef50e2aa86b9d9e6727b172b4&quot;&gt;https:&#x2F;&#x2F;gist.github.com&#x2F;costasko&#x2F;e2ced6cef50e2aa86b9d9e6727b172b4&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Hilbig, T., Geras, T., Kupris, E. and Schreck, T. (2023). security.txt Revisited: Analysis of Prevalence and Conformity in 2022. Digital Threats: Research and Practice, 4(3), pp.1–17. doi:&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1145&#x2F;3609234&quot;&gt;https:&#x2F;&#x2F;doi.org&#x2F;10.1145&#x2F;3609234&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Poteat, T. and Li, F. (n.d.). Who You Gonna Call? An Empirical Evaluation of Website security.txt Deployment. [online] doi:https:&#x2F;&#x2F;doi.org&#x2F;10.1145&#x2F;3487552.3487841.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.uriports.com&#x2F;blog&#x2F;security-txt-in-2025&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.uriports.com&#x2F;blog&#x2F;security-txt-in-2025&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using AWS Certificate Manager as a covert exfiltration mechanism</title>
        <published>2025-08-13T00:00:00+00:00</published>
        <updated>2025-08-13T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/acmfs/" type="text/html"/>
        <id>https://me.costaskou.com/articles/acmfs/</id>
        
        <content type="html">&lt;p&gt;One of my hobbies is researching covert exfiltration mechanisms that use public cloud services&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Public cloud at its core has most service endpoints on the internet. If all you need is a bit of compute talking to some storage, you’d rather not involve the internet at all.&lt;&#x2F;p&gt;
&lt;p&gt;Enter private endpoints VPC-only access to managed services. On AWS, you can attach policies to some of them, so only your accounts and networks can use them. But not every service supports VPC endpoints.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s pick AWS Certificate Manager as an example, a service that doesn&#x27;t have a VPC endpoint.
Issuing or importing a certificate that can be used by other services, e.g. elastic load balancers, requires AWS Certificate Manager (ACM).&lt;&#x2F;p&gt;
&lt;p&gt;Two premises follow: &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;You need to involve the internet to use ACM.&lt;&#x2F;li&gt;
&lt;li&gt;If an attacker compromises a host - and that&#x27;s a big if - that can reach ACM’s public endpoint, they can reach ACM in &lt;em&gt;their&lt;&#x2F;em&gt; account with &lt;em&gt;their&lt;&#x2F;em&gt; credentials, a Bring Your Own Credentials (BYOC) attack. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;acmfs&#x2F;ACMFS.png&quot; alt=&quot;ACMFS.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The problem with AWS services that don&#x27;t have VPC endpoints or VPC endpoint policies is that they cannot be configured to prevent BYOC attacks.  &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;whitepapers&#x2F;latest&#x2F;building-a-data-perimeter-on-aws&#x2F;appendix-a-proxy-configuration-example.html&quot;&gt;Building a data perimeter on AWS&lt;&#x2F;a&gt; and using a proxy, doesn&#x27;t solve this, the service is allowed.&lt;&#x2F;p&gt;
&lt;p&gt;The attacker&#x27;s challenge is that even if they &lt;em&gt;did&lt;&#x2F;em&gt; manage to mount a BYOC attack, they wouldn&#x27;t necessarily have access to a storage service like S3. They&#x27;re limited in exfiltrating certificates.&lt;&#x2F;p&gt;
&lt;p&gt;Out of the box ACM does not give an attacker a service that can be used to exfiltrate data. &lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;So how do you exfiltrate arbitrary data when all you&#x27;ve got is a certificate manager?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hello-x-509-my-old-friend&quot;&gt;Hello X.509 my old friend&lt;&#x2F;h3&gt;
&lt;p&gt;We can build a message queue out of anything&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;acm&#x2F;latest&#x2F;APIReference&#x2F;API_Operations.html&quot;&gt;ACM API&lt;&#x2F;a&gt; is fairly straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;Asking AWS to generate a certificate doesn&#x27;t leave much room for data. A Subject Alternative Name (SAN) extension allows up to 100 names, with each name limited to 253 octets. That&#x27;s ~25KB.&lt;&#x2F;p&gt;
&lt;p&gt;However, ACM allows you to import certificates, including a certificate chain with a size of 2097152 bytes&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. That&#x27;s 2MB of data per certificate and we can import ~5_000 in a year.&lt;&#x2F;p&gt;
&lt;p&gt;Now we need to craft a valid X.509 certificate. 
We&#x27;ll use the v3 extension &lt;a href=&quot;https:&#x2F;&#x2F;docs.openssl.org&#x2F;3.4&#x2F;man5&#x2F;x509v3_config&#x2F;#netscape-string-extensions&quot;&gt;nsComments&lt;&#x2F;a&gt;, technically deprecated (?) but it&#x27;s free form with no length limits.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;cat &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;ext.cnf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;lt;&amp;lt;EOF 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;[v3_ext]   
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;nsComment = $(cat ourb64encoded.data)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We don&#x27;t care about anything else at this point so we&#x27;ll create keys, certs, and our cert chain.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;openssl req&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -newkey&lt;&#x2F;span&gt;&lt;span&gt; rsa:2048&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -nodes &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;  -subj &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&#x2F;CN=leaf&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -keyout&lt;&#x2F;span&gt;&lt;span&gt; key.pem&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -out&lt;&#x2F;span&gt;&lt;span&gt; leaf.csr
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;openssl x509&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -req -days&lt;&#x2F;span&gt;&lt;span&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -in&lt;&#x2F;span&gt;&lt;span&gt; leaf.csr&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -signkey&lt;&#x2F;span&gt;&lt;span&gt; key.pem&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -out&lt;&#x2F;span&gt;&lt;span&gt; cert.pem
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;openssl req&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -new -newkey&lt;&#x2F;span&gt;&lt;span&gt; rsa:2048&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -nodes &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;  -subj &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&#x2F;CN=payload‑carrier‑CA&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -keyout&lt;&#x2F;span&gt;&lt;span&gt; ca_key.pem&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -out&lt;&#x2F;span&gt;&lt;span&gt; ca.csr
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;openssl x509&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -req -days&lt;&#x2F;span&gt;&lt;span&gt; 365&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -in&lt;&#x2F;span&gt;&lt;span&gt; ca.csr&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -signkey&lt;&#x2F;span&gt;&lt;span&gt; ca_key.pem \
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;  -extfile&lt;&#x2F;span&gt;&lt;span&gt; ext.cnf&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -extensions&lt;&#x2F;span&gt;&lt;span&gt; v3_ext&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -out&lt;&#x2F;span&gt;&lt;span&gt; chain.pem
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our payload is in &lt;code&gt;chain.pem&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll import everything to ACM&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;aws acm import-certificate --certificate fileb:&#x2F;&#x2F;cert.pem --private-key fileb:&#x2F;&#x2F;key.pem --certificate-chain fileb:&#x2F;&#x2F;chain.pem --output json &amp;gt; importresp&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We now have our data in ACM.
To get our data back we can call &lt;code&gt;get-certificate&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Keep the &lt;code&gt;importresp&lt;&#x2F;code&gt; handy, as it contains the ARN of our certificate.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;aws acm get-certificate&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --certificate-arn&lt;&#x2F;span&gt;&lt;span&gt; (cert_arn_from_importresp)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;jq&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&amp;#39;.CertificateChain&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; out.pem`
&lt;&#x2F;span&gt;&lt;span&gt;openssl x509&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -in&lt;&#x2F;span&gt;&lt;span&gt; chain.pem&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -noout -ext&lt;&#x2F;span&gt;&lt;span&gt; nsComment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;awk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&amp;#39;NR==2&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;tail&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt;+5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;base64&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ourb64encoded.data2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s our data! Looking at CloudTrail&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventVersion&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;1.11&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;userIdentity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;IAMUser&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;principalId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;AIDAWXXXXXXX&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;arn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;arn:aws:iam::0123456789012:user&#x2F;woot&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;accountId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0123456789012&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;accessKeyId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;AKIAXXXXXXX&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;userName&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;woot&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventTime&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;2025-08-05T2:16:39Z&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventSource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;acm.amazonaws.com&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventName&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;ImportCertificate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;awsRegion&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eu-west-1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;sourceIPAddress&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;sourceIPAddress&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;userAgent&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;Boto3&#x2F;1.39.3 md&#x2F;Botocore#1.39.3 ua&#x2F;2.1 os&#x2F;linux#6.8.0-65-generic md&#x2F;arch#x86_64 lang&#x2F;python#3.10.12 md&#x2F;pyimpl#CPython m&#x2F;b,D,Z cfg&#x2F;retry-mode#legacy Botocore&#x2F;1.39.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;requestParameters&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;reason&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;requestParameters too large&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;omitted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;true&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;originalSize&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;4642657&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;responseElements&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;certificateArn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;arn:aws:acm:eu-west-1:0123456789012:certificate&#x2F;56af65b9-7677-37cb-9385-7317bc1e6e3b&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;requestID&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;someuuid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventID&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;anotheruuid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;readOnly&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventType&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;AwsApiCall&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;managementEvent&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;recipientAccountId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0123456789012&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;eventCategory&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;Management&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;tlsDetails&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;tlsVersion&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;TLSv1.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;cipherSuite&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;TLS_AES_128_GCM_SHA256&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;clientProvidedHostHeader&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;acm.eu-west-1.amazonaws.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because the request parameters are too large, detecting this method can only be done via a TLS breaking intercepting proxy, as it stands. 
In other words, our egress filter would need to unpack each imported certificate and scan it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fuse&quot;&gt;FUSE&lt;&#x2F;h3&gt;
&lt;p&gt;Possibly entering the realm of cursed engineering, instead of scripting, we can turn it into a userspace filesystem.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Introducing ACM FS a secure-by-default, HSM-backed storage, capable of storing up to 7.5 GB.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It can&#x27;t do paths, it can split bigger files &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; into multiple certs and has a cache!&lt;&#x2F;p&gt;
&lt;p&gt;You can find an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;costasko&#x2F;acmstorage&quot;&gt;implementation here&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-free-storage&quot;&gt;On &amp;quot;free&amp;quot; storage&lt;&#x2F;h2&gt;
&lt;p&gt;A similar principle exists with AWS IAM and SAML certificates. AWS IAM supports a VPC endpoint only in the us-east-1 region.
Using SAML provider metadata, you can store up to 10 MB per identity provider. There does not appear to be a hard limit on the number of identity providers, which could theoretically allow for very large total storage. A similar approach might be possible with an embedded X.509 certificate.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to storage, honourable mention goes to AWS Lambda, with 50 MB per function and a total of 75 GB. In theory, you could embed data within a Python file (for example, inside a multi-line comment) and upload it using CreateFunction.&lt;&#x2F;p&gt;
&lt;p&gt;API Gateway allows up to 6 MB in ImportRestApi, so you might be able to include unusually long descriptions in certain properties.&lt;&#x2F;p&gt;
&lt;p&gt;The world is your oyster - but this is purely a technical observation, not a recommendation.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Disclaimer: This information is provided for educational and illustrative purposes only. Do not attempt, replicate, or apply any of these techniques in real systems. Doing so may violate terms of service, end-user license agreements, or applicable laws. I take no responsibility whatsoever for any actions you take or consequences you incur. Proceeding with such activities could result in account suspension, legal action, or other serious repercussions.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hackingthe.cloud&#x2F;aws&#x2F;exploitation&#x2F;s3_server_access_logs&#x2F;&quot;&gt;https:&#x2F;&#x2F;hackingthe.cloud&#x2F;aws&#x2F;exploitation&#x2F;s3_server_access_logs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This is not an AWS vulnerability.The security of customer owned EC2 instances falls into the customer&#x27;s part of the shared responsibility model&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;What should probably be called Xe&#x27;s law ? &lt;a href=&quot;https:&#x2F;&#x2F;xeiaso.net&#x2F;blog&#x2F;anything-message-queue&#x2F;&quot;&gt;https:&#x2F;&#x2F;xeiaso.net&#x2F;blog&#x2F;anything-message-queue&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I don&#x27;t know why 2^21&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;We lose about 33% of the 2MB due to base64 encoding on the total theoretical 5_000 certs&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;But I haven&#x27;t really tested this&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fusepy&#x2F;fusepy&quot;&gt;fusepy&lt;&#x2F;a&gt; is a fantastic project&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why are you expiring my password?</title>
        <published>2025-05-14T00:00:00+00:00</published>
        <updated>2025-05-14T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/why-password-rotate/" type="text/html"/>
        <id>https://me.costaskou.com/articles/why-password-rotate/</id>
        
        <content type="html">&lt;p&gt;It seems like you&#x27;re asking me to change my password every x days.
I don&#x27;t think this is a good idea. You&#x27;re signalling that your authentication and IAM maturity isn&#x27;t where it should be &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You don&#x27;t have to take my word for it.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Source&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Quote&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pages.nist.gov&#x2F;800-63-3&#x2F;sp800-63b.html&quot;&gt;NIST 800-63B rev.3&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Verifiers SHOULD NOT require memorized secrets to be changed arbitrarily (e.g., periodically). However, verifiers&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; SHALL force a change if there is evidence of compromise of the authenticator.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ncsc.gov.uk&#x2F;collection&#x2F;passwords&#x2F;updating-your-approach&quot;&gt;NCSC UK&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Regular password changing harms rather than improves security. Many systems will force users to change their password at regular intervals, typically every 30, 60 or 90 days. This imposes burdens on the user and there are costs associated with recovering accounts.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ncsc.nl&#x2F;wat-kun-je-zelf-doen&#x2F;weerbaarheid&#x2F;beschermen&#x2F;authenticatie&quot;&gt;NCSC NL&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Periodic modification of passwords provides only marginal improvement and in practice leads to easier to guess passwords. The NCSC advises not to impose any restrictions on this. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bsi.bund.de&#x2F;DE&#x2F;Service-Navi&#x2F;Presse&#x2F;Pressemitteilungen&#x2F;Presse2025&#x2F;250131_Passwortwechsel_next-level.html&quot;&gt;BSI&#x2F;German Federal Office for Information Security&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Regular, unprovoked password changes lead to the use of increasingly weaker passwords. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cyber.gc.ca&#x2F;en&#x2F;guidance&#x2F;user-authentication-guidance-information-technology-systems-itsp30031-v3&quot;&gt;Canadian Centre for Cyber Security&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Password aging places a heavy burden on users and can result in users engaging in less secure behaviours (such as writing down passwords and not storing them appropriately). The security value these security controls provide is debatable. Even with a 90-day expiration period, password aging provides an average exploitation window of 45 days.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.iso.org&#x2F;standard&#x2F;75652.html&quot;&gt;ISO 27002:2022 5.17&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Requiring frequent change of passwords can be problematic because users can get annoyed by the frequent changes, forget new passwords, note them down in unsafe places, or choose unsafe password.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cheatsheetseries.owasp.org&#x2F;cheatsheets&#x2F;Authentication_Cheat_Sheet.html&quot;&gt;OWASP Authentication Cheat Sheet&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Ensure credential rotation when a password leak occurs, at the time of compromise identification or when authenticator technology changes. Avoid requiring periodic password changes; instead, encourage users to pick strong passwords and enable Multifactor Authentication Cheat Sheet (MFA). According to NIST guidelines, verifiers should not mandate arbitrary password changes (e.g., periodically).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cisecurity.org&#x2F;insights&#x2F;white-papers&#x2F;cis-password-policy-guide&quot;&gt;Google&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Password expiration is turned off by default because research has shown little positive impact on security.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;microsoft-365&#x2F;admin&#x2F;manage&#x2F;set-password-expiration-policy?view=o365-worldwide&quot;&gt;Microsoft&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Current research strongly indicates that mandated password changes do more harm than good. They drive users to choose weaker passwords, reuse passwords, or update old passwords in ways that are easily guessed by hackers.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This sort of problem has been systematically covered for quite a while now.&lt;&#x2F;p&gt;
&lt;p&gt;On the other side for password expiration.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Source&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Quote&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cisecurity.org&#x2F;insights&#x2F;white-papers&#x2F;cis-password-policy-guide&quot;&gt;CIS Benchmarks Password Policy Guide&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Change immediately based on with a one-year expiration “backstop” (annual). &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.pcisecuritystandards.org&#x2F;document_library&#x2F;?category=pcidss&amp;amp;document=pci_dss&quot;&gt;PCI DSS v4.0.1&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;If passwords&#x2F;passphrases are used as the &lt;em&gt;only&lt;&#x2F;em&gt; authentication factor for user access (i.e., in any single-factor authentication implementation) then either: • Passwords&#x2F;passphrases are changed at least once every 90 days, OR • The security posture of accounts is dynamically analyzed, and real-time access to resources is automatically determined accordingly. &lt;strong&gt;This requirement does not apply to in-scope system components where MFA is used.&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.alibabacloud.com&#x2F;help&#x2F;en&#x2F;ack&#x2F;ack-managed-and-ack-dedicated&#x2F;security-and-compliance&#x2F;ack-reinforcement-based-on-classified-protection&quot;&gt;Multi-Level Protection Scheme (MLPS 2.0)&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Check whether passwords are periodically changed.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Your organisation&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Password must be rotated every 90 days&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Research shows &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; password expiry is not beneficial and it is reflected in (some) national guidance and standards.&lt;&#x2F;p&gt;
&lt;p&gt;Unless you&#x27;re subject to MLPS 2.0, please don&#x27;t ask me to change my password without a reason.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;or at the very best that you&#x27;re operating in a space where you have to follow conflicting requirements.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;In NIST 800-63 parlance &amp;quot;the party to be authenticated is called a claimant and the party verifying that identity is called a verifier&amp;quot;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Using Google Translate from Dutch&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Using Google Translate from German&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;I think this is outdated as CIS Controls v8 don&#x27;t mention password expiration or rotation&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;I couldn&#x27;t find a direct link to MLPS 2.0 so I&#x27;m using the Alibaba cloud MLPS compliance checks&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cs.unc.edu&#x2F;~fabian&#x2F;papers&#x2F;PasswordExpire.pdf&quot;&gt;Zhang, Y., Monrose, F. and Reiter, M. (n.d.). The Security of Modern Password Expiration: An Algorithmic Framework and Empirical Analysis&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nvlpubs.nist.gov&#x2F;nistpubs&#x2F;ir&#x2F;2014&#x2F;NIST.IR.7991.pdf&quot;&gt;United States Federal Employees’ Password Management Behaviours (NIST IR 7991, 2014)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using OpenStreetMap to plot Thing A and Thing B on a map</title>
        <published>2025-05-06T00:00:00+00:00</published>
        <updated>2025-05-06T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/youngs-pubs-burgers/" type="text/html"/>
        <id>https://me.costaskou.com/articles/youngs-pubs-burgers/</id>
        
        <content type="html">&lt;p&gt;It all started down at the pub, during a casual, work-adjacent gathering.
Someone asked, &amp;quot;Wouldn&#x27;t it be great if we could easily find all the burger places near here?&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;A classic question. The kind Google Maps can answer.
However, &amp;quot;here&amp;quot; is relative. For the purposes of this, &amp;quot;here&amp;quot; means a Young&#x27;s pub.&lt;&#x2F;p&gt;
&lt;p&gt;The question then becomes, &amp;quot;What if we wanted to find all burger places near Young&#x27;s pubs?&amp;quot;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is to pick a burger place or a Young&#x27;s pub based on how close they are to each other (and of course how close we are to either). I searched around but couldn&#x27;t find anything that did exactly this - no tool that simply plots Thing A and Thing B on map at the same time. No directions, no filters - just a clean view of both, on the same map.&lt;&#x2F;p&gt;
&lt;p&gt;In the spirit of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mashup_(web_application_hybrid)&quot;&gt;2010s mashups&lt;&#x2F;a&gt; I started doing this in python as a one-off. Static HTML, get the data using python, put it on a map, point-in-time accurate.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the &lt;a href=&quot;https:&#x2F;&#x2F;wiki.openstreetmap.org&#x2F;wiki&#x2F;Overpass_API&quot;&gt;Overpass API&lt;&#x2F;a&gt;, there was no authentication required.
I could issue direct queries using just a bit of JS and get current data, not just point-in-time.&lt;&#x2F;p&gt;
&lt;p&gt;It seemed fairly straightforward, until I realised that some Young&#x27;s pubs were mysteriously missing. Not ideal &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I headed to the &lt;a href=&quot;https:&#x2F;&#x2F;www.youngs.co.uk&#x2F;our-pubs?cardContentId=&amp;amp;cardContentName=&amp;amp;location=170&amp;amp;locationId=170&quot;&gt;Young&#x27;s pubs&lt;&#x2F;a&gt; website to get a list of pubs in London. That meant trading off accuracy, as it&#x27;ll now be postcode wide, but gain completeness.&lt;&#x2F;p&gt;
&lt;p&gt;After scraping the data, I now needed to geocode the postcodes, i.e. convert them to latitude and longitude coordinates, so I could send them to Overpass.&lt;&#x2F;p&gt;
&lt;p&gt;The data woes don&#x27;t stop here. Young&#x27;s lists a pub, the Nine Elms Tavern at &lt;em&gt;SW8 5BP&lt;&#x2F;em&gt;. This postcode doesn&#x27;t exist.
Therefore using the &lt;a href=&quot;https:&#x2F;&#x2F;nominatim.org&#x2F;&quot;&gt;Nominatim API&lt;&#x2F;a&gt; returned null, which Overpass didn&#x27;t appreciate. The actual postcode is &lt;em&gt;SW11 8AY&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After that final bit, we now have our map.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;special&#x2F;Youngspubburgerplaces.html&quot;&gt;Young&#x27;s pubs and burger places&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;iframe src=&quot;&#x2F;special&#x2F;Youngspubburgerplaces.html&quot; width=&quot;800&quot; height=&quot;800&quot; allow=&quot;fullscreen&quot; loading=&quot;lazy&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;and here&#x27;s a map to plot any Thing A and Thing B within London&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 
You need to press &lt;code&gt;Plot&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;special&#x2F;ThingAThingBmap.html&quot;&gt;Thing A and Thing B on a map&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;iframe src=&quot;&#x2F;special&#x2F;ThingAThingBmap.html&quot; width=&quot;800&quot; height=&quot;800&quot; allow=&quot;fullscreen&quot; loading=&quot;lazy&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Young&#x27;s pubs do burgers. However, the groups&#x27; intent was to move away from the pub and to a different establishment&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I believe the reason has to do with the branding that the pubs have. For example The Fellow at King&#x27;s Cross does not have any Young&#x27;s Pub relevant branding, but it is part of the chain. There was a delta between what OpenStreetMap thought was a pub operated by Young&#x27;s and what Young&#x27;s have on their website&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;You can change the bounding box to anything else fairly trivially&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Redox keyboard after 6 years</title>
        <published>2025-01-19T00:00:00+00:00</published>
        <updated>2025-01-19T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/my-redox-mechanical-keyboard-after-6-years/" type="text/html"/>
        <id>https://me.costaskou.com/articles/my-redox-mechanical-keyboard-after-6-years/</id>
        
        <content type="html">&lt;p&gt;2025 started with me ripping off the USB port of the left hand side of my redox keyboard.&lt;&#x2F;p&gt;
&lt;p&gt;The micro USB cable that connected to my keyboard, had two tiny &amp;quot;hooks&amp;quot;. These latch into the arduino USB receiver port.
It is apparently a common feature of micro USB cables.&lt;&#x2F;p&gt;
&lt;p&gt;After 6 years these hooks decided to detach with the USB port, leaving the arduino USB-less.&lt;&#x2F;p&gt;
&lt;p&gt;I built my keyboard a &lt;a href=&quot;https:&#x2F;&#x2F;costask.medium.com&#x2F;build-your-own-keyboard-5df65cb68839&quot;&gt;redox in 2018&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It has been great and the parts have kept up, after heavy daily use.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve read riveting reviews of &lt;a href=&quot;https:&#x2F;&#x2F;www.zsa.io&#x2F;moonlander&quot;&gt;ZSA Moonlander&lt;&#x2F;a&gt;. I didn&#x27;t want to build a new keyboard from scratch.
I would have bought a redox again, but I couldn&#x27;t find the same case nor any ready to ship units at &lt;a href=&quot;https:&#x2F;&#x2F;falbatech.click&#x2F;&quot;&gt;falba.tech&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;a href=&quot;https:&#x2F;&#x2F;infosec.exchange&#x2F;@CostasK&#x2F;113771111568151147&quot;&gt;asked around for recommendations&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Split mechanical keyboards are pricey, but worth it.&lt;&#x2F;p&gt;
&lt;p&gt;In an attempt to salvage it in combination with prices, shipping times, and the fact that I had to learn a new keyboard layout, I reconsidered and tried to repair.&lt;&#x2F;p&gt;
&lt;p&gt;I had three options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Try and re-flash the firmware on the right side as &amp;quot;Master&amp;quot;&lt;&#x2F;li&gt;
&lt;li&gt;De-solder the current arduino solder and buy an arduino micro ~£8 &lt;&#x2F;li&gt;
&lt;li&gt;Buy a new keyboard&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;software-option&quot;&gt;Software option&lt;&#x2F;h1&gt;
&lt;p&gt;I recalled that I used &lt;code&gt;avrdude&lt;&#x2F;code&gt; and looking at the git history of redox I could &lt;em&gt;possibly&lt;&#x2F;em&gt; get away with setting up the master as right.&lt;&#x2F;p&gt;
&lt;p&gt;Now to install qmk on Ubuntu I did.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;git clone https:&#x2F;&#x2F;github.com&#x2F;qmk&#x2F;qmk_firmware.git
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; qmk_firmware
&lt;&#x2F;span&gt;&lt;span&gt;python3&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span&gt; pip install&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --user&lt;&#x2F;span&gt;&lt;span&gt; qmk
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install avrdude gcc-avr avr-libc
&lt;&#x2F;span&gt;&lt;span&gt;qmk setup
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After completing the setup (press Y everywhere)&lt;&#x2F;p&gt;
&lt;p&gt;I then edited &lt;code&gt;keyboards&#x2F;redox&#x2F;keymap&#x2F;default&#x2F;config.h&lt;&#x2F;code&gt; and added &lt;code&gt;#define MASTER_RIGHT&lt;&#x2F;code&gt; just after the pragma declaration &lt;&#x2F;p&gt;
&lt;p&gt;I compiled&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;qmk flash&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -kb&lt;&#x2F;span&gt;&lt;span&gt; redox&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -km&lt;&#x2F;span&gt;&lt;span&gt; default
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Plugged my keyboard, and the left side was dead.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out that the keymap I was running, had declared &lt;code&gt;#define MASTER_LEFT&lt;&#x2F;code&gt;. There is no way out of this. I need to remove the old arduino.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;hardware-option&quot;&gt;Hardware option&lt;&#x2F;h1&gt;
&lt;p&gt;Armed with a de-soldering pump, tweezers, and snips, it took about 30mins to remove the broken arduino pro, without breaking anything else.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;my-redox-mechanical-keyboard-after-6-years&#x2F;brokenarduino.jpg&quot; alt=&quot;Arduino pro without its micro usb and quite damaged&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Flashed the new arduino pro with the default keymap, re-soldered it and realised that my old keymap can no longer compile.
Seems like there were breaking changes. At this point I was tempted to try ZMK, but the QMK configurator came through!&lt;&#x2F;p&gt;
&lt;p&gt;After making a new-ish layout which is pretty much &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qmk&#x2F;qmk_firmware&#x2F;pull&#x2F;5491&quot;&gt;this one&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;my-redox-mechanical-keyboard-after-6-years&#x2F;mykblayout.png&quot; alt=&quot;my keyboard layout from QMK configurator&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The resilience of modern PCBs and keyboard parts is quite understated. The serviceability should be a major selling point.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Yet Another AWS IAM primer</title>
        <published>2025-01-14T00:00:00+00:00</published>
        <updated>2025-01-14T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/yet-another-aws-primer/" type="text/html"/>
        <id>https://me.costaskou.com/articles/yet-another-aws-primer/</id>
        
        <content type="html">&lt;p&gt;How many IAM layers exist when accessing an S3 object from within an AWS VPC using an AWS principal? 
In AWS, even if an identity has the required permissions to access a resource, that does not guarantee the resource will be accessible.&lt;&#x2F;p&gt;
&lt;p&gt;There are generally three IAM layers: identity, network (VPC), and resource.&lt;&#x2F;p&gt;
&lt;p&gt;The rule of thumb of AWS IAM evaluation logic is that as long as there isn&#x27;t an explicit deny, but there is an explicit allow, access will be granted. If we think of the journey from identity to resource, we can build a very approximate mental model of how to think about AWS IAM&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. You should now print the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_evaluation-logic_policy-eval-denyallow.html&quot;&gt;AWS IAM evaluation reference logic&lt;&#x2F;a&gt;, get a pen and write “VPC endpoint policies” above “Evaluate all applicable policies” to reflect how VPC endpoints factor into the process.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;yet-another-aws-primer&#x2F;IAMeval.png&quot; alt=&quot;IAM evaluation logic but with VPC endpoint policies&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When you make a request from within a VPC - targeting a VPC endpoint -  the request, carrying its SigV4, is sent to the AWS service&#x27;s respective VPC endpoint.
The VPC endpoint evaluates the identity&#x27;s permissions against the resource it&#x27;s trying to access and either forwards (allows) or rejects the request to the resource. 
The other policy evaluations follow after that. This isn&#x27;t applicable if the request isn&#x27;t reaching the VPC endpoint and it&#x27;s reaching the public endpoint of the AWS service. Access points are on a similar level.
The first core point is that if the request never reaches the service&#x27;s endpoint, because &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ClothoProxy&#x2F;Clotho&quot;&gt;a proxy&lt;&#x2F;a&gt; or VPC endpoint decide not to forward it, the rest of the evaluation stops early.&lt;&#x2F;p&gt;
&lt;p&gt;We still need to understand the interactions between all of these IAM constructs.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a diagram to help us build our reasoning.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;yet-another-aws-primer&#x2F;IAM.png&quot; alt=&quot;IAM in different parts of its journey from identity to vpc endpoint policy and resource policy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Does a session policy that allows &lt;code&gt;s3:GetObject&lt;&#x2F;code&gt;, automatically enable to access the S3 object?
No. Not if the identity didn&#x27;t allow it in the first place. What&#x27;s the relationship between a permissions boundary, a session policy, and an identity policy.
Identity policies are directly attached to your user or role. I&#x27;m going to hand-wave and pretend that only roles and users exist in AWS as principals. This isn&#x27;t the case, but it simplifies stuff.&lt;&#x2F;p&gt;
&lt;p&gt;Back to identity policies.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;ll use permission boundaries as a guardrail to enforce boundaries on roles whose policies you cannot control. For example the app team can manage a role and you want to try to stop the role from creating VPCs. 
You&#x27;ll use session policies when assuming a role and want to drop permissions. For example the app team has built an &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;transfer&#x2F;latest&#x2F;userguide&#x2F;users-policies-session.html&quot;&gt;S3 router&lt;&#x2F;a&gt;. The role has access to the whole of the bucket but the session only allows access to a &lt;em&gt;specific&lt;&#x2F;em&gt; key of the bucket. 
You&#x27;ll use a Service Control Policy to as a guardrail against account level access. For example, allowlisting AWS services altogether.&lt;&#x2F;p&gt;
&lt;p&gt;Use the diagram above to help you with the applicability and associations of policies against AWS principals, VPCs, and resources. If you&#x27;re making a request to an AWS service that uses the public endpoint, remove the VPC endpoint policy.&lt;&#x2F;p&gt;
&lt;p&gt;A few cautionary notes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Not all &lt;em&gt;identities&lt;&#x2F;em&gt; have the same IAM resource constructs. IAM users can be part of groups which have their own policies.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Not all AWS &lt;em&gt;resources&lt;&#x2F;em&gt; have the same IAM resource constructs, not all AWS resources support policies, not all AWS services have VPC endpoints and not all VPC endpoint support policies.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Part of the perceived AWS IAM complexity stems from inconsistency.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For instance, Amazon EFS has similar IAM constructs to S3, Amazon OpenSearch Service has &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;opensearch-service&#x2F;latest&#x2F;developerguide&#x2F;fgac.html&quot;&gt;Fine-grained-access controls&lt;&#x2F;a&gt;, a different IAM construct. Even S3 has Access Control Lists, another IAM construct, which I&#x27;m going to pretend they don&#x27;t exist in this primer, and so should you.&lt;&#x2F;p&gt;
&lt;p&gt;In most cases, the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_aws-services-that-work-with-iam.html&quot;&gt;AWS services that work with IAM&lt;&#x2F;a&gt; page offers the de facto reference.
However, don&#x27;t lean too heavy against it. As I mentioned earlier, what constitutes a &amp;quot;resource-based policy&amp;quot; varies. Take for example Amazon CloudSearch, which isn&#x27;t listed as having one, but it does.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The policy evaluation within an account goes like this -  &amp;quot;if an action is allowed by an identity-based policy, a resource-based policy, or both, then AWS allows the action.&amp;quot;
Next time you see an empty S3 bucket policy, but the identity allows access and they&#x27;re both in the same account, you now know why access will be granted. This is true for the majority of the cases that support resource-based policies - they don&#x27;t require an explicit allow.&lt;&#x2F;p&gt;
&lt;p&gt;A lesser known corollary is that if a resource allows access to the role (session) then neither the permissions boundary or the session policy are evaluated. Access is granted.
This is quite problematic in cases where you can explicitly control the identity-policies but cannot control the resource policies. This is where Resource Control Policies (RCPs) can shine.
More on that later.&lt;&#x2F;p&gt;
&lt;p&gt;There are certain conditions on which the above diagram is not true.
For example when dealing with cross account access, things are different. When an identity from another AWS account is making requests to our resources, either via public or VPC endpoints.
Remember that all IAM policies apply to your AWS accounts&#x27; identities and resources only. If an attacker lands on your VPC they can use their identity and only the VPC policies would apply. &lt;&#x2F;p&gt;
&lt;p&gt;The take away is that an AWS account is the logical access container.&lt;&#x2F;p&gt;
&lt;p&gt;Before we move on, let&#x27;s recap on our IAM components.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Identity policies – The policies directly attached to your user or role&lt;&#x2F;li&gt;
&lt;li&gt;Permissions boundary - An allowlist that is &lt;em&gt;always&lt;&#x2F;em&gt; attached to your role&lt;&#x2F;li&gt;
&lt;li&gt;Session policy -  A subset of permissions attached when you assume a role&lt;&#x2F;li&gt;
&lt;li&gt;Service control policy - An SCP is an AWS organisation wide policy and is the ultimate allow or block list against services and identities&lt;&#x2F;li&gt;
&lt;li&gt;Resource-based policies - Depends on the service, for example an S3 bucket policy&lt;&#x2F;li&gt;
&lt;li&gt;Resource control policy - An RCP is an AWS organisation wide policy and is the ultimate allow or block list against services and resources&lt;&#x2F;li&gt;
&lt;li&gt;VPC endpoint policy - When inside a VPC these policies allow or deny access to service requests. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, how can we determine which permissions affect our role trying to access an S3 object via a VPC endpoint ?&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The ultimate answer, is via automation and tooling.
Look at &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;what-is-access-analyzer.html#what-is-access-analyzer-policy-checks&quot;&gt;AWS IAM Access Analyzer&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;welldone-cloud&#x2F;aws-lint-iam-policies&quot;&gt;aws-lint-iam-policies&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;iam.cloudcopilot.io&#x2F;tools&#x2F;policy-tester&quot;&gt;cloudpilot.io&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AirWalk-Digital&#x2F;AWSXenos&quot;&gt;AWSXenos&lt;&#x2F;a&gt;, among many others. &lt;&#x2F;p&gt;
&lt;p&gt;The check marks denote effective permissions. In other words where you see a check mark on the intersection of policies and none of the policies involved explicitly deny access, then access will be granted.&lt;&#x2F;p&gt;
&lt;p&gt;Reminder An SCP or RCP on their own cannot grant permissions. An IAM role needs to have permissions to access a resource. As long as the SCP doesn&#x27;t deny access to the identity or specific resource, then the identity can access the resource. If there&#x27;s a resource policy in place&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;yet-another-aws-primer&#x2F;eulerIAM.png&quot; alt=&quot;euleriam&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The red check marks effective permissions are &lt;em&gt;only&lt;&#x2F;em&gt; true when an identity &lt;em&gt;outside&lt;&#x2F;em&gt; of the organisation is inside the VPC. The service control policy wouldn&#x27;t be applied to that identity.
If you&#x27;re inside a VPC owned by AWS account A and organisation A, and use credentials from AWS account B in organisation B, the service control policy of organisation A will not apply to your credentials from organisation B. Service Control Policies only apply to identities in the same organisation.&lt;&#x2F;p&gt;
&lt;p&gt;You can bring your own credentials to a compute resource and as long as the VPC endpoint policy allows your principal then you can access a resource. The same applies if you&#x27;re trying to access a resource via the service&#x27;s public endpoint and not via the VPC endpoint.
Account B&#x27;s principal won&#x27;t be able to access account A&#x27; S3 bucket by default, as AWS resources are account bound&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but they would be able to access Account&#x27;s B resources, which can lead to data exfiltration if this wasn&#x27;t intended.&lt;&#x2F;p&gt;
&lt;p&gt;This is where RCPs come in. In the event that you have a leaky S3 resource policy, your RCP can blanket deny access to &lt;em&gt;all&lt;&#x2F;em&gt; principals outside the organisation.
In general for a data perimeter, i.e. for establishing a baseline in keeping your AWS data to your AWS organisation, you&#x27;d need to sprinkle &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;security&#x2F;control-access-to-aws-resources-by-using-the-aws-organization-of-iam-principals&#x2F;&quot;&gt;aws:Principal*&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;security&#x2F;how-to-control-access-to-aws-resources-based-on-aws-account-ou-or-organization&#x2F;&quot;&gt;aws:Resource*&lt;&#x2F;a&gt; IAM conditions.&lt;&#x2F;p&gt;
&lt;p&gt;These conditions, prevent your AWS Principals from reaching to other account&#x27;s resources. They would also prevent other AWS principals, outside of your AWS organisation, from reaching in to your resources.
Things get tricky when AWS services get involved or when you&#x27;re hitting &lt;a href=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;cross-account-access-in-public-cloud&#x2F;&quot;&gt;public endpoints because reasons&lt;&#x2F;a&gt; but the principles remain the same.&lt;&#x2F;p&gt;
&lt;p&gt;While you could establish high-level guardrails for your AWS Principals, you couldn&#x27;t do the same with your resources, until RCPs were introduced.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, it’s important to remember that IAM in AWS is constantly evolving and each service may bring its own nuances or additional policy constructs. By layering identity, VPC endpoint, and resource policies, plus leveraging organization-wide guardrails like SCPs and RCPs, you can build a robust data perimeter that keeps your accounts more secure. &lt;&#x2F;p&gt;
&lt;p&gt;As always, though, real-world scenarios often blur these clean lines—especially once you factor in cross-account access, public endpoints, or specialized service features. That’s why having a solid mental model of the evaluation flow can help you troubleshoot and refine your security posture when it feels like the policies are all stacked on top of each other.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;s not meant to represent how AWS IAM actually works. If you want to know more about how IAM actually works perhaps start with &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;what-is&#x2F;automated-reasoning&#x2F;&quot;&gt;a gentle intro to Automated Reasoning&lt;&#x2F;a&gt; or a not so gentle &lt;a href=&quot;https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;~hunt&#x2F;FMCAD&#x2F;FMCAD18&#x2F;papers&#x2F;paper3.pdf&quot;&gt;intro to Zelkova&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Trying excalidraw because I don&#x27;t want to admit that PowerPoint is the best diagramming tool. That goes for you Phil H.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I won&#x27;t go into IAM Identity Center because there is a great overlap of terminology with completely different meaning.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Perhaps all&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;ve reported the issue to the good folks as AWS&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Ultimately via automation and tooling. Look at &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;what-is-access-analyzer.html#what-is-access-analyzer-policy-checks&quot;&gt;AWS IAM Access Analyzer&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;welldone-cloud&#x2F;aws-lint-iam-policies&quot;&gt;aws-lint-iam-policies&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;iam.cloudcopilot.io&#x2F;tools&#x2F;policy-tester&quot;&gt;cloudpilot.io&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AirWalk-Digital&#x2F;AWSXenos&quot;&gt;AWSXenos&lt;&#x2F;a&gt;, among many others. &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;This is an Euler diagram and not a Venn diagram&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;Most of them&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A practical mnemonic for cybersecurity maturity</title>
        <published>2024-09-19T00:00:00+00:00</published>
        <updated>2024-09-19T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/a-practical-mnemonic-for-cybersecurity-maturity/" type="text/html"/>
        <id>https://me.costaskou.com/articles/a-practical-mnemonic-for-cybersecurity-maturity/</id>
        
        <content type="html">&lt;p&gt;Sometimes I use a simple mnemonic to evaluate an organisation&#x27;s cybersecurity maturity. It&#x27;s not perfect. It’s a useful tool to spark meaningful discussions about their security posture. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It boils down to asking one question.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How does an organisation decide what technical controls to implement?&lt;&#x2F;strong&gt; In other words, what drives the decision to enable a mitigation?&lt;&#x2F;p&gt;
&lt;p&gt;There are roughly three different ways an organisation builds practical cybersecurity:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Incident-led&lt;&#x2F;strong&gt; : Reactive approach - Focus on security after an incident. Everything is on fire all the time&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Controls-led&lt;&#x2F;strong&gt; - Compliance based - Follow a control framework to the letter on every decision&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Risk-led&lt;&#x2F;strong&gt; - Contextual - Justifiable decisions to mitigate plausible threat scenarios under the context that the organisation operates&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Imagine you&#x27;re managing a typical 3-tier web application hosted on a cloud service provider like AWS.
To secure that application, where do you begin?&lt;&#x2F;p&gt;
&lt;p&gt;Your first thoughts should consider business requirements, risk frameworks, or asking for more context.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s build some context. This is an e-commerce web app, hosted in AWS. Even if you&#x27;re not familiar with AWS, follow along.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;a-practical-mnemonic-for-cybersecurity-maturity&#x2F;3tierarch.png&quot; alt=&quot;three tier architecture diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The decision you need to make is whether you need to segment this web application from the staging environment or not.&lt;&#x2F;p&gt;
&lt;p&gt;I used the word &lt;em&gt;need&lt;&#x2F;em&gt;, because the application can definitely work and deliver value, without any segmentation.
Who is to say that we need to segment stuff&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; ?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;incident-led&quot;&gt;Incident-led&lt;&#x2F;h2&gt;
&lt;p&gt;An incident-led approach is typically driven by external pressure—either from auditors, regulators, or after a security incident.
Security changes happen most likely &lt;em&gt;after&lt;&#x2F;em&gt; something has gone wrong. A security capability is found to be lacking.&lt;&#x2F;p&gt;
&lt;p&gt;The organisation needs this security capability or you otherwise risk a licence or a fine.
There was no prior consideration, but external forces drive decision-making.
We can sprinkle knee-jerk reactions and constant firefighting.&lt;&#x2F;p&gt;
&lt;p&gt;The need for the capability is driven by a past incident that caused downtime or a fine.
A vendor came in and promised to do everything and then more.
Maybe the organisation bought into Software Composition Analysis because in 2021 they didn&#x27;t realise they were running Log4j. &lt;&#x2F;p&gt;
&lt;p&gt;Back to our example. Do we segregate our staging and production environments ? No.&lt;&#x2F;p&gt;
&lt;p&gt;Is there any sort of compartmentalisation? No.&lt;&#x2F;p&gt;
&lt;p&gt;We start a programme of work to do this, after a developer accidentally deployed to production instead of staging.
Get very specific requirements from a third party and try to deliver those to a T.&lt;&#x2F;p&gt;
&lt;p&gt;The requirements focus on capabilities and the answers are often &lt;em&gt;a security product&lt;&#x2F;em&gt;. 
Usually at this point there is a Request For Proposal sent out to vendors to try to match and build that capability.
After purchasing the capability, it&#x27;s revealed that it doesn&#x27;t quite fit the mitigation that the organisation had in mind.&lt;&#x2F;p&gt;
&lt;p&gt;The collective understanding of what the organisation is trying to achieve is lacking. &lt;&#x2F;p&gt;
&lt;p&gt;We now have a firewall appliance and have split the network into two, but the appliance doesn&#x27;t work with anything else in our network.
We will probably have to pay the vendor to operate it and in order to promote workloads from staging to prod, the appliance pretty much allows all to all between the &amp;quot;two networks&amp;quot; so it&#x27;s just an extra hop now. We don&#x27;t want to break stuff.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s cheaper short-term than tackling the root causes, so we&#x27;ll follow a capability model of what the vendor offers.&lt;&#x2F;p&gt;
&lt;p&gt;Next year we&#x27;ll buy a better capability and possibly pivot to another area.&lt;&#x2F;p&gt;
&lt;p&gt;The direction of this type of organisation will be to go cybersecurity shopping every year, buying products to fulfill their missing capabilities, largely reactionary.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is usually enquiring on how to build a structured approach to cyber security. Stop being driven by external priorities.
However, it tends to focus on panacea seeking solutions. That one product that can really help solve that problem.
Because it&#x27;s almost always the problem of the product - &amp;quot;we bought the wrong thing&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;By the time the organisation reaches a pivot point, an external force resets the cycle, and the whole thing starts again.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The overall approach is &lt;em&gt;binary&lt;&#x2F;em&gt; and &lt;em&gt;vendor-led&lt;&#x2F;em&gt;.
Overall it represents the lowest form of cybersecurity maturity, and puts a lot of pressure to the people on the ground.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;controls-led&quot;&gt;Controls-led&lt;&#x2F;h2&gt;
&lt;p&gt;In a controls-led approach, the organisation follows predefined frameworks dogmatically.ISO27001, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Standard_of_Good_Practice_for_Information_Security&quot;&gt;SOGP&lt;&#x2F;a&gt;, NIST, CIS Critical Security Controls, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Pick any of them, we&#x27;ll find something like ABC-10: Segmentation and Subnetworks. Aha! It says: &lt;&#x2F;p&gt;
&lt;blockquote&gt;
  &amp;quot;Define segmentation, label your stuff with classification, build subnetworks, think of regulators and risk.&amp;quot;. &lt;br&gt;
      -- Your favourite control framework
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We can do this. We draw a line on our diagram. If customer data goes down a path, we&#x27;ll call this production.
If customer data doesn&#x27;t go down that path, it&#x27;s... not production.&lt;&#x2F;p&gt;
&lt;p&gt;These two paths never merge. We&#x27;ll put them in different VPCs, or maybe even different accounts. Great.
Alice though will still have access to deploy to both environments from her machine. Maybe we&#x27;ll stop Alice, but we can&#x27;t &amp;quot;stop&amp;quot; Jenkins.&lt;&#x2F;p&gt;
&lt;p&gt;Now we&#x27;ve got segmentation. Except the things that need to talk to both environments at the same time like security scanners, &amp;quot;break glass&amp;quot; access, CI&#x2F;CD pipelines, observability tooling, that ETL job that anonymises data from prod to dev every Friday so we can run analytics, and those two components that point from prod to test because if we migrate them, we might break everything, and they are way down our backlog.&lt;&#x2F;p&gt;
&lt;p&gt;Upon review that might not quite fit with what the frameworks are prescribing, or it might.
In general there is nervousness about the approach, but the debate never settles. There isn&#x27;t an established agreed position, and the solution is to mostly read further on the scripture.&lt;&#x2F;p&gt;
&lt;p&gt;An organisation like that struggles to understand why segmentation is or will be important to their business, but they have a north star to follow. &lt;&#x2F;p&gt;
&lt;p&gt;The direction of this type of organisation is that it constraints itself arguing against the usefuless of a control vs the requirements from the control catalogue.&lt;&#x2F;p&gt;
&lt;p&gt;The approach is unfortunately self-limiting as the decisions that need to be made are also &lt;em&gt;binary&lt;&#x2F;em&gt;, like our incident-led approach, albeit they are better informed and not reactive.
If there is a relevant control to your application, then you &lt;em&gt;must&lt;&#x2F;em&gt; apply that control. There is no gradient, it&#x27;s either on or off.&lt;&#x2F;p&gt;
&lt;p&gt;The organisation tends to associate a control that&#x27;s enabled as compliance and a control that isn&#x27;t enabled as non-compliant.
Compliance drives security. If a decision doesn&#x27;t make sense from a security perspective, we&#x27;ll still argue the potential compliance merits, imagining requirements from mythical regulators.
Phrases like &amp;quot;defence in depth&amp;quot; without corresponding attack trees or threat models, are very popular.&lt;&#x2F;p&gt;
&lt;p&gt;Context is not included. Context specific decisions are difficult to make. First turn everything on, then ask questions.
Cybersecurity becomes a burden and a tick-box exercise. It&#x27;s sometimes performative or &lt;a href=&quot;https:&#x2F;&#x2F;www.philvenables.com&#x2F;post&#x2F;ceremonial-security-and-cargo-cults&quot;&gt;ceremonial security&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;risk-led&quot;&gt;Risk-led&lt;&#x2F;h2&gt;
&lt;p&gt;The risk-led approach starts by asking why. In contrast to controls-led, it starts with understanding the context and qualities of the system.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe it&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;adamshostack&#x2F;4QuestionFrame&quot;&gt;Shostack&#x27;s 4 question frame for threat modeling&lt;&#x2F;a&gt;, or it&#x27;s just asking &amp;quot;what&#x27;s an example where someone could have been in a better place if they have would segmented their network&amp;quot; ?&lt;&#x2F;p&gt;
&lt;p&gt;Is this a property of the system that would help its resilience ? Is the &lt;a href=&quot;https:&#x2F;&#x2F;addxorrol.blogspot.com&#x2F;2020&#x2F;03&#x2F;before-you-ship-security-mitigation.html&quot;&gt;cost of this mitigation&lt;&#x2F;a&gt; worth its implementation for this system?&lt;&#x2F;p&gt;
&lt;p&gt;The organisation understands the regulatory requirements. Where they need to apply controls indiscriminately. Sometimes go as far as to argue against them, as the regulator&#x27;s recommendation is lagging behind current understanding.&lt;&#x2F;p&gt;
&lt;p&gt;The approach goes back to providing the context for the requirement. It tests the assumptions we make of the system that we&#x27;re trying to protect.
It validates the security properties and principles we&#x27;re trying to uphold.&lt;&#x2F;p&gt;
&lt;p&gt;The organisation understands why &lt;a href=&quot;https:&#x2F;&#x2F;www.bankofengland.co.uk&#x2F;-&#x2F;media&#x2F;boe&#x2F;files&#x2F;financial-stability&#x2F;financial-sector-continuity&#x2F;understanding-cyber-threat-intelligence-operations.pdf&quot;&gt;intelligence-led&lt;&#x2F;a&gt; operations are important.&lt;&#x2F;p&gt;
&lt;p&gt;Why resilience and stressed exit plans are part of your &lt;a href=&quot;https:&#x2F;&#x2F;www.bankofengland.co.uk&#x2F;-&#x2F;media&#x2F;boe&#x2F;files&#x2F;prudential-regulation&#x2F;supervisory-statement&#x2F;2021&#x2F;ss221-march-21.pdf&quot;&gt;regulatory requirements&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Following our example.
We can justify why there is a need separate our staging environment from our production environment.
We apply the same controls across the environments. People don&#x27;t have direct access to data, definitely not to prod.
We have confidence in our CI&#x2F;CD and our deployment is the same across environments.
Our app server in test won&#x27;t have authentication credentials to the prod database, or vice versa.&lt;&#x2F;p&gt;
&lt;p&gt;The direction of this organisation is that it makes justifiable decisions to mitigate plausible threat scenarios under the context that they operate.&lt;&#x2F;p&gt;
&lt;p&gt;Product comes first and security is an enabler.&lt;&#x2F;p&gt;
&lt;p&gt;Decisions are not &lt;em&gt;binary&lt;&#x2F;em&gt; and tradeoffs are understood, and captured.
In 6 months time we might have to make a different decision.
That&#x27;s fine, the system is changing and we need to adapt. That&#x27;s the core part of &lt;a href=&quot;https:&#x2F;&#x2F;kellyshortridge.com&#x2F;blog&#x2F;posts&#x2F;security-chaos-engineering-sustaining-software-systems-resilience-cliff-notes&#x2F;&quot;&gt;resilience after all&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next&lt;&#x2F;h2&gt;
&lt;p&gt;Next time your organisation is about to implement a technical control, stop and ask.
Why are we &lt;em&gt;really&lt;&#x2F;em&gt; doing this ?&lt;&#x2F;p&gt;
&lt;p&gt;It might help you assess where you stand and the drivers of your cybersecurity programme.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;This model can also be useful, aside from being wrong.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Before you bring up your favourite control catalogue, risk framework, or public breach&#x2F;anecdote, that&#x27;s the point I&#x27;m making.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cross-account access in public cloud</title>
        <published>2024-03-11T00:00:00+00:00</published>
        <updated>2024-03-11T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/cross-account-access-in-public-cloud/" type="text/html"/>
        <id>https://me.costaskou.com/articles/cross-account-access-in-public-cloud/</id>
        
        <content type="html">&lt;p&gt;Check out &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clothoproxy&#x2F;Clotho&quot;&gt;Clotho&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clothoproxy&#x2F;integrations&quot;&gt;a working example using Squid&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In the realm of public cloud computing, the necessity of utilizing public endpoints is an inherent characteristic — it&#x27;s what defines the &amp;quot;public&amp;quot; in public cloud.&lt;&#x2F;p&gt;
&lt;p&gt;Consider this scenario: It&#x27;s Monday, and you&#x27;re logging into Outlook on the web (OWA) to access your work email. &lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, the same URL that grants you access to your work account also allows you to log into your personal account. 
You have the capability to transfer data directly from your work laptop to your personal email. You simply open a new tab, login to your personal email and upload all your work files.&lt;&#x2F;p&gt;
&lt;p&gt;At first glance, this might seem like a convenient feature. However, it&#x27;s precisely this type of activity that a ~$2bn market is trying to mitigate. 
Data Loss Prevention (DLP) solutions are designed to detect such unauthorized data transfers or exfiltration events.&lt;&#x2F;p&gt;
&lt;p&gt;A DLP solution would be able to spot an exfiltration event from your work email to your personal email. The responsibility falls under the email provider. 
The email provider needs to provide the security controls to prevent or detect exfiltration events. &lt;&#x2F;p&gt;
&lt;p&gt;However, that&#x27;s not your path. You&#x27;re uploading data to a trusted vendor endpoint, from a trusted work device, in a trusted work network, to your own email.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;re after all, login in to Outlook, there is nothing malicious. The responsibility falls under your own network and devices.&lt;&#x2F;p&gt;
&lt;p&gt;The endpoint serves everyone; therefore, if you decide to email yourself a spreadsheet, the responsibility for preventing or detecting this event, falls under your own network and devices.&lt;&#x2F;p&gt;
&lt;p&gt;We need a way to prevent an attacker from accessing &lt;em&gt;their&lt;&#x2F;em&gt; email, from &lt;em&gt;our&lt;&#x2F;em&gt; network, whilst allowing access to the endpoint. &lt;&#x2F;p&gt;
&lt;p&gt;Instead of &lt;em&gt;email&lt;&#x2F;em&gt;, think about any service from a major public Cloud Service Provider (CSP).&lt;&#x2F;p&gt;
&lt;p&gt;There are two ways to connect to CSPs services. Establish a connection over the internet or over Private Link.&lt;&#x2F;p&gt;
&lt;p&gt;In AWS specifically, &lt;em&gt;some&lt;&#x2F;em&gt; private endpoints &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;privatelink&#x2F;aws-services-privatelink-support.html#vpce-endpoint-policy-support&quot;&gt;do &lt;em&gt;not&lt;&#x2F;em&gt; support policies&lt;&#x2F;a&gt; and some services do not support endpoints at all &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We need access to AWS endpoints, sometimes over the internet. Sometimes it&#x27;s an S3 bucket that has a picture of cat. This is how a chunk of the web still works, by having intentionally publicly readable S3 buckets.&lt;&#x2F;p&gt;
&lt;p&gt;It follows that over the internet, an attacker can access their S3 bucket - or other service with no endpoint or endpoint policy - from our network, using their account credentials, and we won&#x27;t be able to prevent or trivially detect the event.&lt;&#x2F;p&gt;
&lt;p&gt;The risk becomes apparent when: &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We place people next to data&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; - i.e. an insider risk.&lt;&#x2F;li&gt;
&lt;li&gt;An attacker is in our network with data and wants to get out.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It&#x27;s a challenge to not place people next to data. Once achieved, it removes a significant amount of risk from the system and the organisation &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Insider risks are well known&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,  &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Swiss_Leaks&quot;&gt;especially&lt;&#x2F;a&gt; in &lt;a href=&quot;https:&#x2F;&#x2F;www.fintechfutures.com&#x2F;2016&#x2F;08&#x2F;thousands-and-thousand-of-times-a-tale-of-an-insider-data-breach&#x2F;&quot;&gt;large&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.priv.gc.ca&#x2F;en&#x2F;opc-actions-and-decisions&#x2F;investigations&#x2F;investigations-into-businesses&#x2F;2020&#x2F;pipeda-2020-005&#x2F;&quot;&gt;organisations&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When we PUT an object in an S3 bucket, over the internet, our request would be to &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;general&#x2F;latest&#x2F;gr&#x2F;s3.html&quot;&gt;one of these endpoints&lt;&#x2F;a&gt;. How can we identify that the PUT happens in our S3 bucket and not the attacker&#x27;s ? In other words, how do we stop cross account&#x2F;tenant&#x2F;organisation access over the internet ? 
How can we prevent an attacker from inside our network, accessing cloud service public endpoints?&lt;&#x2F;p&gt;
&lt;p&gt;In AWS, Azure, and GCP, this is a known threat. Azure and GCP share a similar approach and enable you to put tenant&#x2F;organisation restrictions in place.
Here&#x27;s how they work:&lt;&#x2F;p&gt;
&lt;p&gt;The traffic sent from anything inside your corporate network, &lt;em&gt;must&lt;&#x2F;em&gt; go via an egress proxy before it reaches the public endpoint of the CSP.&lt;&#x2F;p&gt;
&lt;p&gt;The proxy will &amp;quot;break&amp;quot; TLS, inject a custom HTTP header and forward the request to the CSP&#x27;s public endpoint.&lt;&#x2F;p&gt;
&lt;p&gt;The HTTP header that will be injected contains the unique IDs of the corporate tenants. In other words it&#x27;s an allowlist.
If the request tries to access resources or authenticate to anything other than the allowlisted tenants, it will get denied.&lt;&#x2F;p&gt;
&lt;p&gt;Which means that we don&#x27;t have to do any further inspection into the credentials or the type of the request that was sent.
All we need to do, is get a list of our tenant&#x2F;organisation ID, force everyone to go via the egress proxy - probably already doing this - and we&#x27;ve just mitigated our cross-tenant&#x2F;org threat.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;cross-account-access-in-public-cloud&#x2F;simpleegress.png&quot; alt=&quot;simpleegress.png&quot; &#x2F;&gt; &lt;&#x2F;p&gt;
&lt;p&gt;Azure and GCP, provide more granular capabilities with &lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;entra&#x2F;external-id&#x2F;tenant-restrictions-v2&quot;&gt;Azure tenant restrictions v2&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;resource-manager&#x2F;docs&#x2F;organization-restrictions&#x2F;configure-organization-restrictions&quot;&gt;GCP organisation restrictions&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;support.google.com&#x2F;a&#x2F;answer&#x2F;1668854?hl=en&quot;&gt;Google consumer domain blocks&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What about AWS ? It&#x27;s complicated. AWS launched &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;security&#x2F;access-accounts-with-aws-management-console-private-access&#x2F;&quot;&gt;Management Console Private Access&lt;&#x2F;a&gt;.
You build a VPC in an AWS account and create two new VPC Endpoints - &lt;code&gt;console&lt;&#x2F;code&gt; and &lt;code&gt;signin&lt;&#x2F;code&gt;. Then you force all of your corporate users traffic to these VPC endpoints instead of the public endpoints.&lt;&#x2F;p&gt;
&lt;p&gt;There are problems with this approach.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It doesn&#x27;t support API access. We&#x27;re still not solving the issue of services that lack VPC Endpoints or VPC Endpoint Policies. &lt;&#x2F;li&gt;
&lt;li&gt;It complicates the setup when we need both console and API access. &lt;&#x2F;li&gt;
&lt;li&gt;Supported regions and services are not 100% there.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Which is why I made Clotho.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clotho&quot;&gt;Clotho&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clothoproxy&#x2F;Clotho&quot;&gt;Clotho&lt;&#x2F;a&gt; aims to be a fast and secure AWS sigv4 verification library, written in Rust, that can be used as an external authoriser with your favourite forward proxy.&lt;&#x2F;p&gt;
&lt;p&gt;It aims to act like the Azure and GCP solutions in AWS, but without the need to inject any headers or alter the request in any way.&lt;&#x2F;p&gt;
&lt;p&gt;Why do you need this ?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Security - You can filter sigv4 based on account IDs, regions, or AWS services.
For example your internet egress traffic can be limited only to your AWS account. This is very important especially for AWS services that do not support VPC endpoints.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Cost savings - It can be cheaper to run vs VPC endpoints&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Clotho won&#x27;t apply any IAM policy checks depending on your IAM identity. Clotho will simply parse the &lt;code&gt;Authorization&lt;&#x2F;code&gt; header and apply an allowlist check based on the account, region, or service.&lt;&#x2F;p&gt;
&lt;p&gt;Before I continue on how Clotho works, we first need to understand what&#x27;s in a typical AWS API request, and specifically the authorisation part, sigv4.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example &lt;code&gt;Authorization&lt;&#x2F;code&gt; header of an HTTP request to the AWS &lt;code&gt;STS&lt;&#x2F;code&gt; public endpoint API using the sigv4 scheme.&lt;&#x2F;p&gt;
&lt;p&gt;Building this request is an offline operation. All you need is an &lt;code&gt;aws_secret_access_key&lt;&#x2F;code&gt;, the &lt;code&gt;region&lt;&#x2F;code&gt; which you intent to send the request, and the &lt;code&gt;service&lt;&#x2F;code&gt; that you&#x27;re operating.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;1. &amp;quot;Authorization&amp;quot;: &amp;quot;AWS4-HMAC-SHA256 
&lt;&#x2F;span&gt;&lt;span&gt;2. Credential=AKIAWNIPTZABWMEXAMPLE&#x2F;20240107&#x2F;eu-west-1&#x2F;sts&#x2F;aws4_request,
&lt;&#x2F;span&gt;&lt;span&gt;3. SignedHeaders=content-type;host;x-amz-date,
&lt;&#x2F;span&gt;&lt;span&gt;4. Signature=03707c980d16f1eecdf36551112fa6244764079272b6bb5cd708a4bd25d43e1e&amp;quot;,
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Line 1: The algorithm used to calculate line 4, the &lt;code&gt;Signature&lt;&#x2F;code&gt; component.&lt;&#x2F;p&gt;
&lt;p&gt;Line 2 : &lt;code&gt;Credential&lt;&#x2F;code&gt; component. It includes the &lt;code&gt;access_key_id&lt;&#x2F;code&gt;, the date the request was signed, the region and service that the request is targeting, and the type of the signature &lt;code&gt;aws4_request&lt;&#x2F;code&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;Line 3: &lt;code&gt;SignedHeader&lt;&#x2F;code&gt; component - describe the contents used to generate the signature.&lt;&#x2F;p&gt;
&lt;p&gt;Line 3 references HTTP headers that are not part of the snippet above, but are part of the request.&lt;&#x2F;p&gt;
&lt;p&gt;Clotho &amp;quot;verifies&amp;quot; the &lt;code&gt;Credential&lt;&#x2F;code&gt; component, against a provided allowlist.&lt;&#x2F;p&gt;
&lt;p&gt;Since the &lt;code&gt;Credential&lt;&#x2F;code&gt; component is part of the signature, if an attacker modifies any part of it, the verification of the signature will fail.
Tampering of the &lt;code&gt;Signature&lt;&#x2F;code&gt; will equally result into the verification of the signature failing since it won&#x27;t match the &lt;code&gt;Credential&lt;&#x2F;code&gt; component.
Therefore a Monster in the Middle (MitM) attacker can replay a sigv4 request &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; but cannot tamper with it.&lt;&#x2F;p&gt;
&lt;p&gt;The first and primary information we need to take is to identify the account that owns the &lt;code&gt;access_key_id&lt;&#x2F;code&gt;.
Normally this could be done by calling &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;STS&#x2F;latest&#x2F;APIReference&#x2F;API_GetAccessKeyInfo.html&quot;&gt;GetAccessKeyInfo&lt;&#x2F;a&gt;.
However, we can unpack the AWS account ID &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; from the &lt;code&gt;access_key_id&lt;&#x2F;code&gt;. This saves as network call to the STS endpoint. Our verification can take place offline.&lt;&#x2F;p&gt;
&lt;p&gt;We can then build an egress proxy that inspects any AWS API request, reads the &lt;code&gt;Credential&lt;&#x2F;code&gt; component of the &lt;code&gt;Authorization&lt;&#x2F;code&gt; header and compares the request to our own allowlist.&lt;&#x2F;p&gt;
&lt;p&gt;An allowlist in Clotho looks like this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#e8bf6a;&quot;&gt;accounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;581039954779&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;regions&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;services&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;s3&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will allow any request from account &lt;code&gt;581039954779&lt;&#x2F;code&gt;, to any region, to the s3 service.
If Clotho receives the following request &lt;code&gt;... Credential=AKIAIOSFODNN7EXAMPLE&#x2F;20130524&#x2F;us-east-1&#x2F;s3&#x2F;aws4_request&lt;&#x2F;code&gt; it can unpack the AWS Account id from the &lt;code&gt;access_key_id&lt;&#x2F;code&gt; and make decision based on the allowlist. In this case the request would be allowed. You can clone the repo and run the example yourself.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve included an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clothoproxy&#x2F;integrations&quot;&gt;example implementation in squid&lt;&#x2F;a&gt;, and an implementation in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clothoproxy&#x2F;PyClotho&quot;&gt;Python&#x27;s mitmproxy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A back-of-the-envelope calculation comparing VPC Endpoints and Clotho, shows that Clotho &lt;em&gt;could&lt;&#x2F;em&gt; be cheaper.
Here&#x27;s a cost comparison, with the following assumptions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Running on us-east-1&lt;&#x2F;li&gt;
&lt;li&gt;Everything runs across x3 AZs&lt;&#x2F;li&gt;
&lt;li&gt;There is no intra region traffic when reaching clotho instances &lt;&#x2F;li&gt;
&lt;li&gt;There are no egress costs for reaching out to AWS Services in the same region - &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;architecture&#x2F;overview-of-data-transfer-costs-for-common-architectures&#x2F;&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Clotho runs on graviton and the pricing is on-demand&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Traffic&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;VPCE Count&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;VPCE Price&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Clotho Cost&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Clotho instance type&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;1 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;10&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$226&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$9.072&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;t4g x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;1 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;20&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$433&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$9.072&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;t4g x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;10 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;10&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$316&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$83.16&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;c6gd x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;10 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;20&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$532&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$83.16&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;c6gd x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;100 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;10&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$1216&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$1078.27&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;c7gn.2xlarge x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;100 TB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;20&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$1432&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;$1078.27&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;c7gn.2xlarge x3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;With Clotho you pay &lt;em&gt;only&lt;&#x2F;em&gt; for the compute cost.
The vertical scale up calculation happens to accommodate for higher bursts.
A VPC Endpoint can burst to 100 Gbit&#x2F;s with sustained 10Gbit&#x2F;s.&lt;&#x2F;p&gt;
&lt;p&gt;A t4g instance would cater for up to 5 Gbit&#x2F;s, and a c7gn.2xlarge up to 50Gbit&#x2F;s . Figures taken from &lt;a href=&quot;https:&#x2F;&#x2F;instances.vantage.sh&#x2F;?filter=graviton&quot;&gt;ec2instances.info&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Clotho is at a very early stage, and contributions are welcome.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;AWS Certificate Manager, AWS WAF, and Route 53 come immediately to mind.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;wellarchitected&#x2F;latest&#x2F;security-pillar&#x2F;sec_protect_data_rest_use_people_away.html&quot;&gt;SEC08-BP05&lt;&#x2F;a&gt; Keep people away from data. This principle extends outside of the cloud. &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thenewstack.io&#x2F;more-lessons-from-hackers-how-it-can-do-better&#x2F;&quot;&gt;The Ice Cream Cone of Hierarchy of Security Solutions&lt;&#x2F;a&gt; by Kelly Shortridge is a fantastic example. The less dependent your system is to human behaviour the better. An engineer creating a &amp;quot;builder&amp;quot; VPC with an admin-like role that has access to the internet, so that the platform can import certificates to AWS ACM is necessary, but risky. It doesn&#x27;t have to be spreadsheets.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ncsc.gov.uk&#x2F;guidance&#x2F;reducing-data-exfiltration-by-malicious-insiders&quot;&gt;https:&#x2F;&#x2F;www.ncsc.gov.uk&#x2F;guidance&#x2F;reducing-data-exfiltration-by-malicious-insiders&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Depending on the nature of the request and whether it&#x27;s idempotent or not. Not all AWS APIs are the same. The replay also has a time limit of ~15 mins&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@TalBeerySec&#x2F;a-short-note-on-aws-key-id-f88cc4317489&quot;&gt;https:&#x2F;&#x2F;medium.com&#x2F;@TalBeerySec&#x2F;a-short-note-on-aws-key-id-f88cc4317489&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A day in Squid with ICAP</title>
        <published>2024-02-14T00:00:00+00:00</published>
        <updated>2024-02-14T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/a-day-in-squid-with-icap/" type="text/html"/>
        <id>https://me.costaskou.com/articles/a-day-in-squid-with-icap/</id>
        
        <content type="html">&lt;p&gt;I&#x27;m writing an authorisation library for AWS in Rust and Python.
I want to parse requests sent to AWS public endpoints, say &lt;code&gt;s3.amazonaws.com&lt;&#x2F;code&gt; and figure out if I should forward them or not.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of writing my own proxy, &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; I thought I&#x27;d integrate my library with &lt;a href=&quot;http:&#x2F;&#x2F;www.squid-cache.org&quot;&gt;Squid proxy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Squid was initially released in 1996. Written in C++, it has survived the test of time, in that it is still widely used.&lt;&#x2F;p&gt;
&lt;p&gt;As an example AWS writes usecases using &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;security&#x2F;how-to-set-up-an-outbound-vpc-proxy-with-domain-whitelisting-and-content-filtering&#x2F;&quot;&gt;Squid as an outbound proxy&lt;&#x2F;a&gt;.
A similar case with GCP using Squid for &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;data-fusion&#x2F;docs&#x2F;how-to&#x2F;egress-control&quot;&gt;egress control&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I want to use Squid for something similar.&lt;&#x2F;p&gt;
&lt;p&gt;I started my integration journey with &lt;code&gt;external_acl_type&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Squid runs instances of a program of your choosing. You can define what parameters you can pass to this program.&lt;&#x2F;p&gt;
&lt;p&gt;Squid expects a response. An &lt;code&gt;OK&lt;&#x2F;code&gt; if the request should be allowed or &lt;code&gt;ERR&lt;&#x2F;code&gt; if the request should be denied.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example program that allows all requests:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;sys.stdin.readline().strip()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;line:
&lt;&#x2F;span&gt;&lt;span&gt;        sys.stdout.write(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;OK&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        time.sleep( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Squid run the authoriser in the background. In your squid config you setup something like &lt;code&gt;external_acl_type my_auth_helper %SRC my_authoriser&lt;&#x2F;code&gt;.
&lt;code&gt;%SRC&lt;&#x2F;code&gt; passes the source IP as an argument to &lt;code&gt;my_authoriser&lt;&#x2F;code&gt;. That works pretty well, but only when you&#x27;re not dealing with HTTPS requests.&lt;&#x2F;p&gt;
&lt;p&gt;Squid cannot send HTTPS request headers to an &lt;code&gt;external_acl_type&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, for reasons unknown. The &amp;quot;classical&amp;quot; way of dealing with this in Squid is ICAP.&lt;&#x2F;p&gt;
&lt;p&gt;ICAP stands for Internet Content Adaptation Protocol and has been defined since 2003 in &lt;a href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc3507&quot;&gt;RFC 3507&lt;&#x2F;a&gt;.
Two decades later it seems to still be in use. There is a crowd that supports anti-virus scanning on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;darold&#x2F;squidclamav&quot;&gt;egress traffic&lt;&#x2F;a&gt;. It&#x27;s all the &lt;code&gt;adaptation_&lt;&#x2F;code&gt; directives in Squid.&lt;&#x2F;p&gt;
&lt;p&gt;ICAP is aimed at being &amp;quot;a lightweight protocol for executing a &#x27;remote procedure call&#x27; on HTTP messages&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;It is nothing like that&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;ICAP is symbiotic to HTTP. A wrapper. It has two main methods of operations &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Request modification -REQMOD and response modification RESPMOD.
In &lt;code&gt;REQMOD&lt;&#x2F;code&gt;, the request is forwarded to the ICAP server for a decision.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;a-day-in-squid-with-icap&#x2F;reqmod.png&quot; alt=&quot;reqmod sequence diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;RESPMOD&lt;&#x2F;code&gt;, the response from the origin webserver is forwarded to the ICAP server for a decision.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;a-day-in-squid-with-icap&#x2F;respmod.png&quot; alt=&quot;respmod sequence diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Squid has its own ICAP client.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;REQMOD&lt;&#x2F;code&gt;, when squid receives an HTTP request from a client it would craft the following request to the ICAP server.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;   REQMOD icap:&#x2F;&#x2F;icap-server.net&#x2F;server?arg=87 ICAP&#x2F;1.0
&lt;&#x2F;span&gt;&lt;span&gt;   Host: icap-server.net
&lt;&#x2F;span&gt;&lt;span&gt;   Encapsulated: req-hdr=0, null-body=76
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;   GET &#x2F; HTTP&#x2F;1.1
&lt;&#x2F;span&gt;&lt;span&gt;   Host: www.example.com
&lt;&#x2F;span&gt;&lt;span&gt;   Accept: text&#x2F;html, text&#x2F;plain
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first headers indicate byte offsets ala &lt;code&gt;Content-Length&lt;&#x2F;code&gt; in HTTP. &lt;code&gt;Req-hdr&lt;&#x2F;code&gt; tells us that the headers start from byte 0.
&lt;code&gt;Null-body&lt;&#x2F;code&gt; tells us, there&#x27;s no HTTP body that follows and there&#x27;s 76 bytes of headers.&lt;&#x2F;p&gt;
&lt;p&gt;The core of the &lt;code&gt;REQMOD&lt;&#x2F;code&gt; ICAP request is the &lt;code&gt;Encapsulated&lt;&#x2F;code&gt; header, which is the HTTP header plus the HTTP body, if there is any.
Requests terminate with &lt;code&gt;0\r\n\r\n&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The ICAP server would send a response back&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;   ICAP&#x2F;1.0 200 OK
&lt;&#x2F;span&gt;&lt;span&gt;   Server: ICAP-Server-Software&#x2F;1.0
&lt;&#x2F;span&gt;&lt;span&gt;   Connection: close
&lt;&#x2F;span&gt;&lt;span&gt;   Encapsulated: req-hdr=0, null-body=197
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;   GET &#x2F;modified-path HTTP&#x2F;1.1
&lt;&#x2F;span&gt;&lt;span&gt;   Host: www.example.com
&lt;&#x2F;span&gt;&lt;span&gt;   Via: 1.0 icap-server.net (ICAP Example ReqMod Service 1.1)
&lt;&#x2F;span&gt;&lt;span&gt;   Accept: text&#x2F;html, text&#x2F;plain, image&#x2F;gif
&lt;&#x2F;span&gt;&lt;span&gt;   Accept-Encoding: gzip, compress
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example the ICAP server has modified the request, but it can also send a 403 Forbidden, or a 204 No Content response.&lt;&#x2F;p&gt;
&lt;p&gt;This behaviour seems to fit the bill. I&#x27;ll setup an ICAP server that will inspect the HTTPS headers forwarded by Squid.
Even better someone has written an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chills42&#x2F;icaparse&quot;&gt;ICAP parsing library&lt;&#x2F;a&gt;. Huzzah!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; icap_headers &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;ICAP_EMPTY_HEADER&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; icap_request &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ICAPRequest::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; icap_headers);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;&#x2F;&#x2F; We parse the ICAP request first
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; icap_request.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;buf) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(icaparse::Status::Complete(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;&#x2F;&#x2F; icap_request.encapsulated_sections contains our HTTP request 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;&#x2F;&#x2F; send response   
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; response &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;format!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;ICAP&#x2F;1.0 204 No Content&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;\r\n\r\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You might notice that like in HTTP, in ICAP we could end up with &lt;code&gt;Partial&lt;&#x2F;code&gt; responses, but we&#x27;ll pretend that this sort of thing can never happen.
The RFC makes chunking of encapsulated bodies mandatory but encapsulated headers are not chunked. I only care about encapsulated headers.
Interestingly enough the mandatory use of chunking, is what prohibited the authors from building ICAP on top of HTTP as an application-layer protocol.&lt;&#x2F;p&gt;
&lt;p&gt;The Squid config to forward all requests to the ICAP server.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ini&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-ini &quot;&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;icap_enable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;on
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;icap_service &lt;&#x2F;span&gt;&lt;span&gt;iservice reqmod_precache bypass&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;icap:&#x2F;&#x2F;127.0.0.1:1344
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That seems straightforward. Which is why Squid never forwarded any HTTP request to my ICAP server.
Baffling.  Remember how I said ICAP had two main modes? Well I lied. I discovered that Squid sent a third type of method, &lt;code&gt;OPTIONS&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Before squid forwards the first HTTP request, it asks the ICAP server for &amp;quot;options&amp;quot;.
Asking if it&#x27;s a REQMOD or RESPMOD server, what&#x27;s the date, what&#x27;s the name of the ICAP server, that sort of thing.
The &lt;code&gt;c-icap-client&lt;&#x2F;code&gt;, is very handy &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It can craft an OPTIONS ICAP request.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s craft our OPTIONS response&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;OPTIONS&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;#&amp;quot;ICAP&#x2F;1.0 200 OK
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;Methods: REQMOD
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;Service: Rust ICAP Server
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;Allow: 204
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;ISTag: RustICAPServer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;Encapsulated: null-body=0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;#
&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;tokens.html#raw-string-literals&quot;&gt;raw string literals&lt;&#x2F;a&gt; are neat like that. We don&#x27;t need to mess around with &lt;code&gt;\r\n&lt;&#x2F;code&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s inevitable that someone will write a fully fledged ICAP server in Rust. For now my implementation works pretty well.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I still might end up writing my own, because it could be simpler. There aren&#x27;t many pluggable MiTM proxies out there.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Quite possibly. There&#x27;s a chance I haven&#x27;t unlocked the right arcane incantation that is the Squid configuration.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;s actually three as I found out later.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;For example &lt;code&gt;c-icap-client -i 127.0.0.1 -p 1344 -s service_name&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On trusting cloud vendors and insider threats</title>
        <published>2024-01-14T00:00:00+00:00</published>
        <updated>2024-01-14T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/on-trusting-cloud-vendors-and-insider-threats/" type="text/html"/>
        <id>https://me.costaskou.com/articles/on-trusting-cloud-vendors-and-insider-threats/</id>
        
        <content type="html">&lt;p&gt;I stumbled upon this post on the AWS subreddit:
&lt;a href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;aws&#x2F;comments&#x2F;18xvh75&#x2F;how_are_you_mitigating_the_risk_of_a_rogue_aws&#x2F;&quot;&gt;How are you mitigating the risk of a rogue AWS engineer accessing our data or damaging the RDS instance?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The author wants to address the CISO&#x27;s concerns about this scenario.&lt;&#x2F;p&gt;
&lt;p&gt;The top responses dismissed the concern. &lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This sounds like more of an issue with your leadership not understanding how AWS works[...]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;and &lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Honestly, this sounds like more of a managerial question[...]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Comments fall into one of the three categories:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It&#x27;s in an audit, certification report&#x2F;AWS Artifacts.&lt;&#x2F;li&gt;
&lt;li&gt;Something about encryption&lt;&#x2F;li&gt;
&lt;li&gt;Maybe the CISO is on to something&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The majority of the responses included the sentiment that &amp;quot;the CISO doesn&#x27;t get it&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I don&#x27;t think this is the case&lt;&#x2F;em&gt;. This is a realistic and legitimate concern.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a situation where everyone is somewhat correct.&lt;&#x2F;p&gt;
&lt;p&gt;Before we address the comments, let me rephrase the concern&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;AWS staff can access customer data in RDS, either via direct access to the infrastructure or via the sys-level super users of database engines.&lt;&#x2F;p&gt;
&lt;p&gt;This concern isn&#x27;t limited to AWS, it&#x27;s common  across all cloud service providers (CSP).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;it-s-certifiably-not-accessible&quot;&gt;It&#x27;s certifiably not accessible&lt;&#x2F;h1&gt;
&lt;p&gt;Regulations, standards, certifications, etc. tend to not prohibit user interactions with a system.&lt;&#x2F;p&gt;
&lt;p&gt;For example, there are strict access controls guidelines in PCI DSS&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, Financial Conduct Authority&#x27;s (FCA) handbook &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, etc. but nothing that would suggest that AWS RDS - or other service - is certifiably not accessible by AWS staff. The controls are mostly self-imposed by AWS, and other CSPs.&lt;&#x2F;p&gt;
&lt;p&gt;The goal here it to prove that we&#x27;ve done our due diligence&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; for our vendor. It&#x27;s compliance. We haven&#x27;t really talked about the mechanisms in place to prevent this. Even further, how these mechanisms are visible to the customer.
An attacker cannot be stopped by calling out &amp;quot;but that would break policy&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;An organisation will mitigate third party risks by compliance. Pragmatic due diligence stops here.
Realistically as a customer you wouldn&#x27;t have the means to enquire about the inner workings of your vendor, and that&#x27;s OK.
The customer will never know the mechanism, but can &lt;em&gt;trust&lt;&#x2F;em&gt; that they are in place.
As a customer you trust a CSP that their staff don&#x27;t have access to &lt;em&gt;your&lt;&#x2F;em&gt; customer data.&lt;&#x2F;p&gt;
&lt;p&gt;In any event, you can invoke the shared responsibility model, and your organisation can &lt;em&gt;possibly&lt;&#x2F;em&gt; escape the &lt;em&gt;accountability&lt;&#x2F;em&gt; of the concern.
You can say to your customers: &amp;quot;It wasn&#x27;t us, and we definitely didn&#x27;t have such an expectation from our due diligence.&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;CSPs &lt;em&gt;want&lt;&#x2F;em&gt; their customers to make this argument.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
  We prohibit -- and our systems are designed to prevent -- remote access by AWS personnel to customer data for any purpose, including service maintenance, unless that access is requested by you or unless access is required to prevent fraud and abuse, or to comply with law. &lt;br&gt;
      -- AWS documentation
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;encryption&quot;&gt;Encryption&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;ve written about AWS&#x27; KMS threat model&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. When it comes to encryption in CSPs, the pragmatic threats to accessing your data derives from IAM.&lt;&#x2F;p&gt;
&lt;p&gt;Server side encryption is customer insurance against a &amp;quot;black swan&amp;quot; event against your CSP. Including the External Key Store (XKS) scheme and bringing your own key.
With any server side encryption scheme, you&#x27;re trusting your CSP to encrypt the data and secure the key.
The customer hands the data and points to a CSP hosted key. The rest is up to the CSP. &lt;&#x2F;p&gt;
&lt;p&gt;There is again a level of trust - albeit enforced by a stronger premise - to the CSP. For example, in XKS you trust your CPS will delete your data key after each encrypt and decrypt operation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;on-trusting-cloud-vendors-and-insider-threats&#x2F;slide.jpg&quot; alt=&quot;Snowden slide, decrypt and encrypt here&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You get the idea.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly HSMs also involve a level of trust in that AWS staff cannot retrieve the Domain Key. This extends the trust in a different direction. A fourth party company &lt;em&gt;certifiably&lt;&#x2F;em&gt; builds the HSM in such a way that no one would be able to retrieve the HSM&#x2F;Domain Key.&lt;&#x2F;p&gt;
&lt;p&gt;But server side encryption is meaningless for RDS in this scenario and has a completely different threat model. 
In our scenario AWS staff would have direct access to the database. In server side encryption the encryption&#x2F;decryption is transparent and in this case doesn&#x27;t require IAM permissions to KMS, unlike S3. &lt;&#x2F;p&gt;
&lt;p&gt;Client side encryption&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is where a customer can potentially increase the security of their system. 
It makes the provider&#x27;s position a lot more complex when it comes to retrieving your data. Even if AWS staff can login as a &amp;quot;SUPER&amp;quot;, they now get encrypted data. They need to get access to your client key as well. A case of self-imposed separation of duties for CSPs.&lt;&#x2F;p&gt;
&lt;p&gt;If your data is encrypted before being stored, the CSP has to go through more steps in order to retrieve a key that they don&#x27;t have in the first place. 
Arguably - again with an enforced premise of trust - potentially impossible&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; or potentially noticeable by the customer.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-ciso-might-be-on-to-something&quot;&gt;The CISO might be on to something&lt;&#x2F;h1&gt;
&lt;p&gt;By now you should notice a theme, it&#x27;s all about trust. &lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;CSPs build security controls to defend against their own machinations and their own internal threat actors.&lt;&#x2F;em&gt; By extension, the CSPs protect their customers. 
This isn&#x27;t something that you can easily and openly talk about as a vendor, but this is the reality of cyber security.&lt;&#x2F;p&gt;
&lt;p&gt;How often do data centre operators put controls in place because they do not trust their staff?&lt;&#x2F;p&gt;
&lt;p&gt;The argument then goes that we can enable logs. CSPs provide transparent operations, by enabling logging, customers &lt;em&gt;should&lt;&#x2F;em&gt; be able to have an unfettered view of access to their database.
This is the case with AWS CloudTrail, Azure Audit Logs, GCP Cloud Audit Logs, etc.&lt;&#x2F;p&gt;
&lt;p&gt;The difference between AWS and other CSPs is that AWS doesn&#x27;t provide a separate access transparency logs service.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GCP has &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;security&#x2F;products&#x2F;access-transparency?hl=en&quot;&gt;Access Transparency and Access Approval&lt;&#x2F;a&gt;, &lt;&#x2F;li&gt;
&lt;li&gt;Azure has &lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;azure&#x2F;security&#x2F;fundamentals&#x2F;customer-lockbox-overview&quot;&gt;Customer Lockbox&lt;&#x2F;a&gt;,&lt;&#x2F;li&gt;
&lt;li&gt;AWS has no equivalent. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These services make access requests to customer data, visible to the customer.
Because a customer might actually request CSP staff to access their account and get &lt;em&gt;very&lt;&#x2F;em&gt; close to the data as part of a support ticket.
Because not every database holds private data.&lt;&#x2F;p&gt;
&lt;p&gt;Following this, what makes transparency logs trustworthy then, and not AWS RDS audit logs?
Why trust one and not the other? 
Can we even verify the provenance and integrity of CSP logs ?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;~rdriley&#x2F;487&#x2F;papers&#x2F;Thompson_1984_ReflectionsonTrustingTrust.pdf&quot;&gt;Reflections on Trusting Trust&lt;&#x2F;a&gt;, seems apropos.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
  The moral is obvious. You can&amp;#x27;t trust code that you did not totally create yourself. (Especially code from companies that employ people like me.) No amount of source-level verification or scrutiny will protect you from using untrusted code. &lt;br&gt;
      -- Ken Thomson
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s &lt;em&gt;trust&lt;&#x2F;em&gt; turtles all the way down.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I purposefully use the word &lt;em&gt;concern&lt;&#x2F;em&gt; instead of &lt;em&gt;risk&lt;&#x2F;em&gt;. We&#x27;re not going into formalities and likelihoods. We want to first address if this is a legitimate &lt;em&gt;concern&lt;&#x2F;em&gt; that we should even consider, at least based on the responses from the post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&amp;quot;Access to payment account data must be granted only on a business need-to-know basis. Logical access controls are technical means used to permit or deny access to data on computer systems.&amp;quot; - PCI DSS 4.0&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&amp;quot;Automation may reduce a firm&#x27;s exposure to some &#x27;people risks&#x27; (including by reducing human errors or controlling access rights to enable segregation of duties), but will increase its dependency on the reliability of its IT systems.&amp;quot; - FCA handbook SYSC 13.7.|&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;This is the definition of due diligence. As a customer you&#x27;re showing that you&#x27;ve fulfilled your reasonable standard of care for your industry or at least risk appetite. The extent to which you need or can go further depends on the vendor, your pockets, the industry, etc.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;airwalkreply.com&#x2F;aws-kms-threat-model&quot;&gt;https:&#x2F;&#x2F;airwalkreply.com&#x2F;aws-kms-threat-model&lt;&#x2F;a&gt; &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Transparent Data Encryption (TDE) or similar technologies included. The data is encrypted before it&#x27;s stored, and preferably not using a CSPs KMS. &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;whitepapers&#x2F;latest&#x2F;security-design-of-aws-nitro-system&#x2F;no-aws-operator-access.html&quot;&gt;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;whitepapers&#x2F;latest&#x2F;security-design-of-aws-nitro-system&#x2F;no-aws-operator-access.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The website that sets the most cookies</title>
        <published>2023-12-09T00:00:00+00:00</published>
        <updated>2023-12-18T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/the-website-that-sets-the-most-cookies/" type="text/html"/>
        <id>https://me.costaskou.com/articles/the-website-that-sets-the-most-cookies/</id>
        
        <content type="html">&lt;p&gt;With my browser setup I don&#x27;t get to see the GDPR &lt;a href=&quot;https:&#x2F;&#x2F;community.mozilla.org&#x2F;en&#x2F;campaigns&#x2F;firefox-cookie-banner-handling&#x2F;&quot;&gt;cookie banners&lt;&#x2F;a&gt;.
You can achieve the same by using &lt;a href=&quot;https:&#x2F;&#x2F;easylist.to&quot;&gt;ublock origin&lt;&#x2F;a&gt; .&lt;&#x2F;p&gt;
&lt;p&gt;After an update, my default browser changed. I opened a link to a news website, and there it was, the cookie banner, asking me if I want to accept sharing my data with 1174 partners&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. 
That&#x27;s a lot of partners. There&#x27;s probably some website out there that has more partners than this, and I need to find out.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve got a &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;bejaneps&#x2F;ba8d8eed85b0c289a05c750b3d825f61&quot;&gt;list of websites&lt;&#x2F;a&gt;, installed &lt;a href=&quot;https:&#x2F;&#x2F;playwright.dev&#x2F;python&#x2F;&quot;&gt;playwright&lt;&#x2F;a&gt;, and I&#x27;m off to check how many cookies do these websites self-report they have.&lt;&#x2F;p&gt;
&lt;p&gt;Every website has a &amp;quot;we have 5 partners that ...&amp;quot; in the cookie banner, right ? 
I wrote a regular expression to capture that number.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;font-style:italic;color:#cc7833;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;extract_numbers&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    pattern &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;\b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;(?:partner&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;vendor&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;\b|\b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;(?:partner&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;vendor&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#519f50;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;\b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    matches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;re.findall(pattern, text)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;# Flatten the list of tuples and remove empty strings
&lt;&#x2F;span&gt;&lt;span&gt;    matches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[num &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;tup &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;matches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;num &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;tup &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;num]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;matches[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It turns that most websites on my list don&#x27;t have this partner count.
I ended up with lots of missing or inaccurate data. Getting the self-reported data isn&#x27;t as straightforward. 
There is no requirement to self report the &lt;em&gt;count&lt;&#x2F;em&gt; of all advertising partners. This approach was a dud.&lt;&#x2F;p&gt;
&lt;p&gt;The next best approach that I thought of was to find and click every &amp;quot;Opt-in&amp;quot; or &amp;quot;Accept&amp;quot; button. Then count the number of cookies, that are set.
This isn&#x27;t ideal either. I won&#x27;t know the advertising partners, I&#x27;ll just know how many cookies. It&#x27;s fair assumption to make that the count of domains would represent the count of advertising partners, more or less.&lt;&#x2F;p&gt;
&lt;p&gt;The data was a lot more accurate however, playwright gets confused between multiple buttons that have the same text.&lt;&#x2F;p&gt;
&lt;p&gt;For example&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;Error: strict mode violation: locator(&amp;quot;button:has-text(\&amp;quot;Accept\&amp;quot;), button:has-text(\&amp;quot;Agree\&amp;quot;)&amp;quot;) resolved to 2 elements:
&lt;&#x2F;span&gt;&lt;span&gt;    1) &amp;lt;button id=&amp;quot;onetrust-accept-btn-handler&amp;quot;&amp;gt;Accept All Cookies&amp;lt;&#x2F;button&amp;gt; aka get_by_role(&amp;quot;button&amp;quot;, name=&amp;quot;Accept All Cookies&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    2) &amp;lt;button id=&amp;quot;accept-recommended-btn-handler&amp;quot;&amp;gt;Accept All Cookies&amp;lt;&#x2F;button&amp;gt; aka get_by_label(&amp;quot;ORCID Cookie Settings&amp;quot;).get_by_text(&amp;quot;Accept All Cookies&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at some of the websites, the first button, tended to be the &amp;quot;Accept&amp;quot; option, so I decided to tell playwright to click the first button, always. 
I&#x27;m not sure if I&#x27;m even clicking on the cookie banner, or another button somewhere on the website that says &amp;quot;Accept&amp;quot;, but the chances of that happening are fairly low.&lt;&#x2F;p&gt;
&lt;p&gt;However, I still couldn&#x27;t make sure that I clicked the &amp;quot;right&amp;quot; button.&lt;&#x2F;p&gt;
&lt;p&gt;Continuing with this approach, I started playwright with Firefox using the &amp;quot;Desktop Firefox&amp;quot;, User-Agent.
Switching to Chromium with a mix of &lt;code&gt;Desktop Edge&lt;&#x2F;code&gt; and &lt;code&gt;Desktop Chrome&lt;&#x2F;code&gt; User-Agents, proved to be a lot more successful, but there are still a lot of websites that I never managed to reach. Ultimately what worked consitently was rotating between &lt;code&gt;Firefox&lt;&#x2F;code&gt; and &lt;code&gt;Chromium&lt;&#x2F;code&gt; and using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AtuboDad&#x2F;playwright_stealth&quot;&gt;playwright_stealth&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Before I present the data, a recap of all the assumptions: &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I&#x27;m not login in into any of these websites. Facebook.com seems to drop exactly one cookie from their own domain after accepting all cookies. I imagine this isn&#x27;t the case after login &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; .&lt;&#x2F;li&gt;
&lt;li&gt;These are the cookies stored in the browser just after I click on - what I believe to be - &amp;quot;Accept all cookies&amp;quot;, i.e. the data is &lt;em&gt;still not accurate&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;There are websites on the list thatdon&#x27;t have a cookie banner, e.g. vk.com . &lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Removing some of the duplicates and domains that no longer exist, I ended up with data from 962 websites.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;top-10-websites-that-give-you-the-most-cookies&quot;&gt;Top 10 websites that give you the most cookies&lt;&#x2F;h4&gt;
&lt;p&gt;The website that sets the most cookies after you accept all cookies is &lt;code&gt;songkick.com&lt;&#x2F;code&gt;, with a total of 172.
This includes cookies set under the &lt;code&gt;.songkick.com&lt;&#x2F;code&gt; domain.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Domain&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Number of cookies set&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;songkick.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;172&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;hollywoodreporter.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;132&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;boredpanda.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;132&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;vanityfair.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;128&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;newyorker.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;121&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;businessinsider.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;117&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;stocktwits.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;112&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;wired.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;111&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;vogue.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;111&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;mlb.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;111&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h4 id=&quot;top-10-websites-that-give-you-cookies-from-different-domains&quot;&gt;Top 10 websites that give you cookies from different domains&lt;&#x2F;h4&gt;
&lt;p&gt;Cookies from 62 different domains were set in &lt;code&gt;songkick.com&lt;&#x2F;code&gt;. &lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Domain&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Number of domains&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;songkick.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;62&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;hollywoodreporter.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;49&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;boredpanda.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;48&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;vanityfair.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;aljazeera.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;stocktwits.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;lesechos.fr&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;42&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;huffpost.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;41&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;businessinsider.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;39&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;huffingtonpost.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;39&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h4 id=&quot;top-10-cookie-domains&quot;&gt;Top 10 cookie domains&lt;&#x2F;h4&gt;
&lt;p&gt;The most common domain cookies were set under was &lt;code&gt;.linkedin.com&lt;&#x2F;code&gt;, found in 330 websites.
The top 10 of the most common domains:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Domain&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Count&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.linkedin.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;330&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.doubleclick.net&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;176&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.pubmatic.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;165&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.twitter.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;104&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.adobe.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;100&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.casalemedia.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;96&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.demdex.net&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;91&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.bing.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;72&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.adnxs.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;70&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;.yahoo.com&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;69&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;It was the dailymail.co.uk&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.facebook.com&#x2F;privacy&#x2F;policies&#x2F;cookies&#x2F;?annotations%5B0%5D=explanation%2F3_companies_list&quot;&gt;https:&#x2F;&#x2F;www.facebook.com&#x2F;privacy&#x2F;policies&#x2F;cookies&#x2F;?annotations[0]=explanation%2F3_companies_list&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Enteprise problem solving</title>
        <published>2023-11-27T00:00:00+00:00</published>
        <updated>2023-11-27T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/enterprise-problem-solving/" type="text/html"/>
        <id>https://me.costaskou.com/articles/enterprise-problem-solving/</id>
        
        <content type="html">&lt;p&gt;You can solve any problem in an enterprise setting by assigning it to the team that is not in the meeting.&lt;&#x2F;p&gt;
&lt;p&gt;You can potentially extend this to settings other than meetings, as long as you get agreement with the rest of the participants that the problem sits with team X.&lt;&#x2F;p&gt;
&lt;p&gt;There are certain quorum criteria that you need to meet, depending on the size of the problem.
For instance, a problem that requires a quarter&#x27;s worth of work from team X, might require at least 2 different teams to agree, a 2 out of 3.
Of course this isn&#x27;t really solving any problems, it&#x27;s assigning blame.
But you can pretend it&#x27;s problem solving, as &lt;em&gt;you&lt;&#x2F;em&gt; have one less problem to solve. That&#x27;s how a lot of the problems are &amp;quot;solved&amp;quot; today. You pass them to someone else, and as long as you&#x27;ve achieved some form of consensus, your team can be successful. &lt;&#x2F;p&gt;
&lt;p&gt;I call this the enterprise problem solving law.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
If the most efficient way for a team to &amp;quot;solve&amp;quot; a problem is to assign it to another team, they will do.
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Problems are &amp;quot;solved&amp;quot; not by direct action but by strategic reallocation.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a couple of examples of how this works in practice.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;re part of an application team that wants to integrate with the central identity provider.
You&#x27;re in a meeting with the identity team but can&#x27;t figure out a way to integrate. The tooling team is missing from the conversation.
You&#x27;re in luck because that&#x27;s exactly what the tooling &lt;em&gt;must&lt;&#x2F;em&gt; add to their remit, and immediate roadmap. The tooling team just became the blocker and the actual problem solver.&lt;&#x2F;p&gt;
&lt;p&gt;Or maybe you&#x27;re part of the vulnerability management team. You&#x27;re in a meeting with the platform team to identify why you&#x27;re not making a dent on your vulnerability metrics.
The application team is missing from the meeting. The platform team insists that the majority of the vulnerabilities originate from dependencies that are the within the application team&#x27;s remit.&lt;&#x2F;p&gt;
&lt;p&gt;No one communicated or agreed with the application team that this is within their remit.
But, you&#x27;ve achieved consensus, the problem is solved. After all ignorantia juris non excusat, you proclaim happily.&lt;&#x2F;p&gt;
&lt;p&gt;Anthropology has a lot to teach us about this behaviour. Mary Douglas has just the quote from Risk and Blame &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
  If you want to cast blame, there are always loopholes for reading the evidence right. Science has not produced a run of people who don&amp;#x27;t wish to dominate one another. &lt;br&gt;
      -- Mary Douglas
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In other words: &amp;quot;it comes natural to some humans to pass blame&amp;quot;, and there are common reasons to it.&lt;&#x2F;p&gt;
&lt;p&gt;For starters, negative experiences. The brain responds more strongly to bad experiences than good ones and retains the memory of bad experiences longer. There&#x27;s a ratio that depends on your mental health, emotions and age. The ratio between positive and negative effects is three good experiences for a negative experience &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Assigning direct blame, without constructive outcomes, leads to negative experiences, which leads to more blame. Criticism and reprimanding naturally make people averse to taking responsibility. &lt;&#x2F;p&gt;
&lt;p&gt;This negative feedback loop starts to form, where staff see themselves and other teams as cogs in the machine as opposed to human beings. &amp;quot;It&#x27;s that other team of faceless people that I never interact with that are to blame, I acknowledge non of their circumstances, and have no incentives to understand them&amp;quot;. This is called the Knobe effect &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. We perceive the goodness or badness of the actions of other people based on the intentions&#x27; of the people who took the action. Obviously when it comes to the &amp;quot;faceless people that I never interact with&amp;quot;, their intentions are bad.&lt;&#x2F;p&gt;
&lt;p&gt;As a result organizational chaos ensues. Confused roles and responsibilities within the organization contribute to its blame culture, and solidify through the organisation&#x27;s communication structures.
Assigning blame becomes the modus operandi of teams. Blame in modern organisations takes many forms. &lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve started to acknowledge that blame culture is toxic &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. If you&#x27;re in tech, you might have heard of blameless postmorterms &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Worth noting that in sectors like aviation and patient safety another methodology is currently being promoted, just culture &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In this form, the analysis starts with identifying intent.&lt;&#x2F;p&gt;
&lt;p&gt;Like the Knobe effect mentioned above, and unlike blameless postmorterms, an assumption that everyone involved has good intentions is not the default position of the analysis. Just culture aims to start by identifying whether there was gross negligence or malice, in order to identify further actions.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the most common misconception in tech, is that Root Cause Analysis (RCA) ends in a single node. Notice the singular form of &lt;em&gt;cause&lt;&#x2F;em&gt;. No matter whether we try to operate within blameless, just culture, or otherwise, the belief that there is a single source of all that is to blame. Perhaps the word &amp;quot;root&amp;quot; is to blame 😉 .&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;enterprise-problem-solving&#x2F;dns.webp&quot; alt=&quot;SSBroski it&#x27;s always DNS&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;It&#x27;s always DNS&amp;quot; is a common adage in RCA, but is it &lt;em&gt;only&lt;&#x2F;em&gt; DNS. Dekker talks about causal meshes and webs. &amp;quot;A root is simply where you stop looking any further&amp;quot;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
  Cause is not something you find. Cause is something you construct. How you construct it, and from what evidence, depends on where you look, what you look for, who you talk to, what you have seen before and likely on who you work for. &lt;br&gt;
      -- Sidney Dekker
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Combining Dekker&#x27;s &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fn_7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and Douglas&#x27; understanding of RCA, and blame, respectively, we can be confident in saying that if you want to cast blame, you must be able to assign the root cause.
In the examples above, the teams did exactly that. They assigned the root cause of the issue, blocker, vulnerability, etc. to another team.&lt;&#x2F;p&gt;
&lt;p&gt;They transformed a problem, into a root cause. Not many root causes, just one, that other team, and in certain organisations we allow this to be the most efficient way of solving a problem.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Risk_and_Blame&quot;&gt;Risk and Blame&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ncbi.nlm.nih.gov&#x2F;pmc&#x2F;articles&#x2F;PMC3158962&#x2F;&quot;&gt;Diehl, Manfred, Elizabeth L. Hay, and Kathleen M. Berg. 2011. “The Ratio between Positive and Negative Affect and Flourishing Mental Health across Adulthood.” Aging &amp;amp; Mental Health 15 (7): 882–93. https:&#x2F;&#x2F;doi.org&#x2F;10.1080&#x2F;13607863.2011.569488.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.jstor.org&#x2F;stable&#x2F;43854197&quot;&gt;Knobe Effect&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hbr.org&#x2F;2022&#x2F;02&#x2F;blame-culture-is-toxic-heres-how-to-stop-it&quot;&gt;Timms, Blame Culture Is Toxic. Here’s How to Stop It. HBR&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;postmortem-culture&#x2F;&quot;&gt;Beyer, B., Jones, C., Petoff, J. and Niall Richard Murphy (2016). Site reliability engineering : how Google runs production systems. Sebastopol, Ca: Oreilly.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.england.nhs.uk&#x2F;patient-safety&#x2F;a-just-culture-guide&#x2F;&quot;&gt;A just culture guide, NHS&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fn_7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Dekker, S. (2016) ‘The construction of cause’, in The field guide to understanding ‘human error’. Ashgate Publishing Company: Ashgate Publishing, pp. 75–76.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Greek Keno Statistics</title>
        <published>2023-08-30T00:00:00+00:00</published>
        <updated>2023-08-30T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/greek-keno-statistics/" type="text/html"/>
        <id>https://me.costaskou.com/articles/greek-keno-statistics/</id>
        
        <content type="html">&lt;p&gt;I stumbled upon &lt;a href=&quot;https:&#x2F;&#x2F;www.lottery.co.uk&#x2F;lotto&#x2F;statistics&quot;&gt;lottery statistics&lt;&#x2F;a&gt; which are very useful if you have never come across the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gambler&amp;#x27;s_fallacy&quot;&gt;gambler&#x27;s fallacy&lt;&#x2F;a&gt;. On the UK national lottery you pick 6 numbers out of 59 (1-59). Of these 6 numbers are drawn.&lt;&#x2F;p&gt;
&lt;p&gt;I wondered how this plays out in other lottery-like games, and how do I get to verify these numbers.
Verify in the sense for example, that the mean of the uniform distribution of lottery draws is what is expected. &lt;&#x2F;p&gt;
&lt;p&gt;First of all we need numbers, lots of numbers.&lt;&#x2F;p&gt;
&lt;p&gt;I was after a readily available dataset and a lottery-like game where there&#x27;s no current known analysis that I can find with a quick internet search.&lt;&#x2F;p&gt;
&lt;p&gt;First of all we need numbers, lots of numbers. I&#x27;m aiming to at least reproduce (most of) the statistics on lottery.co.uk.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up picking Greek &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Keno&quot;&gt;Keno&lt;&#x2F;a&gt; named &amp;quot;Kino&amp;quot; because the data is &lt;a href=&quot;https:&#x2F;&#x2F;www.opap.gr&#x2F;en&#x2F;kino-draw-results&quot;&gt;available online for free&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In the Greek version of Keno, you pick up to 12 numbers out of 80 (1-80). Of these 20 numbers are drawn.
The pay table is formed in relation to the amount of numbers you&#x27;ve picked against the amount of numbers drawn that match your pick.&lt;&#x2F;p&gt;
&lt;p&gt;For example if you pick 2 numbers, and both of them match then you win €2.5. If one of them matches you win €0.5.
However if you pcik 6 numbers, if two of them match, you don&#x27;t qualify for any winnings.&lt;&#x2F;p&gt;
&lt;p&gt;After downloading and loading the excel spreadsheets, you can find Kino stats below, from 2015 to 2023 for &lt;em&gt;559_505&lt;&#x2F;em&gt; draws.&lt;&#x2F;p&gt;
&lt;p&gt;Read about the gambler&#x27;s fallacy, &lt;a href=&quot;https:&#x2F;&#x2F;www.begambleaware.org&#x2F;&quot;&gt;BeGambleAware&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.gamingcommission.gov.gr&#x2F;index.php&#x2F;en&#x2F;responsible-gaming&quot;&gt;Responsible Gaming&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;frequency-graph&quot;&gt;Frequency Graph&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;greek-keno-statistics&#x2F;.&#x2F;freq_table.png&quot; alt=&quot;Frequency Table&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;most-common-numbers&quot;&gt;Most common numbers&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;#     Times Drawn
&lt;&#x2F;span&gt;&lt;span&gt;28    140504
&lt;&#x2F;span&gt;&lt;span&gt;34    140519
&lt;&#x2F;span&gt;&lt;span&gt;16    140525
&lt;&#x2F;span&gt;&lt;span&gt;3     140632
&lt;&#x2F;span&gt;&lt;span&gt;26    140687
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;least-often-picked-numbers&quot;&gt;Least often picked numbers&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;#     Time Drawn
&lt;&#x2F;span&gt;&lt;span&gt;54    139049
&lt;&#x2F;span&gt;&lt;span&gt;47    139115
&lt;&#x2F;span&gt;&lt;span&gt;23    139166
&lt;&#x2F;span&gt;&lt;span&gt;33    139196
&lt;&#x2F;span&gt;&lt;span&gt;55    139257
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;most-common-triplets&quot;&gt;Most common triplets&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;3, 26, 34
&lt;&#x2F;span&gt;&lt;span&gt;3, 26, 28
&lt;&#x2F;span&gt;&lt;span&gt;3, 16, 26
&lt;&#x2F;span&gt;&lt;span&gt;3, 15, 26
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;most-common-consecutive-pairs&quot;&gt;Most common consecutive pairs&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;1,  2
&lt;&#x2F;span&gt;&lt;span&gt;79, 80
&lt;&#x2F;span&gt;&lt;span&gt;15, 16
&lt;&#x2F;span&gt;&lt;span&gt;18, 19
&lt;&#x2F;span&gt;&lt;span&gt;26, 27
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;most-common-consecutive-triplets&quot;&gt;Most common consecutive triplets&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;1,  2,  3
&lt;&#x2F;span&gt;&lt;span&gt;78, 79, 80
&lt;&#x2F;span&gt;&lt;span&gt;34, 35, 36
&lt;&#x2F;span&gt;&lt;span&gt;2,  3,  4
&lt;&#x2F;span&gt;&lt;span&gt;14, 15, 16
&lt;&#x2F;span&gt;&lt;span&gt;73, 74, 75
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;descriptive-statistics&quot;&gt;Descriptive Statistics&lt;&#x2F;h3&gt;
&lt;p&gt;The numbers at the top indicate the order of the drawn numbers, i.e. for &lt;em&gt;1&lt;&#x2F;em&gt;, all the numbers that have been drawn first have a mean of &lt;code&gt;40.46&lt;&#x2F;code&gt;.
This is the output from calling &lt;code&gt;describe()&lt;&#x2F;code&gt; on the pandas dataframe.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;                  1              2              3              4   \
&lt;&#x2F;span&gt;&lt;span&gt;count  559505.000000  559505.000000  559505.000000  559505.000000   
&lt;&#x2F;span&gt;&lt;span&gt;mean       40.469942      40.514873      40.490982      40.475603   
&lt;&#x2F;span&gt;&lt;span&gt;std        23.086179      23.109007      23.112292      23.096609   
&lt;&#x2F;span&gt;&lt;span&gt;min         1.000000       1.000000       1.000000       1.000000   
&lt;&#x2F;span&gt;&lt;span&gt;25%        21.000000      20.000000      20.000000      20.000000   
&lt;&#x2F;span&gt;&lt;span&gt;50%        40.000000      41.000000      40.000000      40.000000   
&lt;&#x2F;span&gt;&lt;span&gt;75%        60.000000      61.000000      61.000000      60.000000   
&lt;&#x2F;span&gt;&lt;span&gt;max        80.000000      80.000000      80.000000      80.000000   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                  5              6              7              8   \
&lt;&#x2F;span&gt;&lt;span&gt;count  559505.000000  559505.000000  559505.000000  559505.000000   
&lt;&#x2F;span&gt;&lt;span&gt;mean       40.477388      40.520717      40.451901      40.476062   
&lt;&#x2F;span&gt;&lt;span&gt;std        23.095309      23.104026      23.091244      23.101723   
&lt;&#x2F;span&gt;&lt;span&gt;min         1.000000       1.000000       1.000000       1.000000   
&lt;&#x2F;span&gt;&lt;span&gt;25%        20.000000      20.000000      20.000000      20.000000   
&lt;&#x2F;span&gt;&lt;span&gt;50%        40.000000      41.000000      40.000000      40.000000   
&lt;&#x2F;span&gt;&lt;span&gt;75%        61.000000      61.000000      60.000000      61.000000   
&lt;&#x2F;span&gt;&lt;span&gt;max        80.000000      80.000000      80.000000      80.000000   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                  9              10             11             12  \
&lt;&#x2F;span&gt;&lt;span&gt;count  559505.000000  559505.000000  559505.000000  559505.000000   
&lt;&#x2F;span&gt;&lt;span&gt;mean       40.523447      40.536674      40.514626      40.495322   
&lt;&#x2F;span&gt;&lt;span&gt;std        23.092834      23.099860      23.096518      23.116335   
&lt;&#x2F;span&gt;&lt;span&gt;min         1.000000       1.000000       1.000000       1.000000   
&lt;&#x2F;span&gt;&lt;span&gt;25%        21.000000      21.000000      21.000000      20.000000   
&lt;&#x2F;span&gt;&lt;span&gt;50%        40.000000      41.000000      41.000000      40.000000   
&lt;&#x2F;span&gt;&lt;span&gt;75%        61.000000      61.000000      61.000000      61.000000   
&lt;&#x2F;span&gt;&lt;span&gt;max        80.000000      80.000000      80.000000      80.000000   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                  13             14             15             16  \
&lt;&#x2F;span&gt;&lt;span&gt;count  559505.000000  559505.000000  559505.000000  559505.000000   
&lt;&#x2F;span&gt;&lt;span&gt;mean       40.502623      40.503633      40.507095      40.510634   
&lt;&#x2F;span&gt;&lt;span&gt;std        23.088596      23.098390      23.094724      23.097256   
&lt;&#x2F;span&gt;&lt;span&gt;min         1.000000       1.000000       1.000000       1.000000   
&lt;&#x2F;span&gt;&lt;span&gt;25%        21.000000      21.000000      21.000000      21.000000   
&lt;&#x2F;span&gt;&lt;span&gt;50%        40.000000      40.000000      40.000000      41.000000   
&lt;&#x2F;span&gt;&lt;span&gt;75%        60.000000      61.000000      61.000000      61.000000   
&lt;&#x2F;span&gt;&lt;span&gt;max        80.000000      80.000000      80.000000      80.000000   
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                  17             18             19             20  
&lt;&#x2F;span&gt;&lt;span&gt;count  559505.000000  559505.000000  559505.000000  559505.000000  
&lt;&#x2F;span&gt;&lt;span&gt;mean       40.514905      40.445926      40.478031      40.496453  
&lt;&#x2F;span&gt;&lt;span&gt;std        23.094424      23.088998      23.070759      23.069527  
&lt;&#x2F;span&gt;&lt;span&gt;min         1.000000       1.000000       1.000000       1.000000  
&lt;&#x2F;span&gt;&lt;span&gt;25%        21.000000      20.000000      21.000000      21.000000  
&lt;&#x2F;span&gt;&lt;span&gt;50%        41.000000      40.000000      40.000000      40.000000  
&lt;&#x2F;span&gt;&lt;span&gt;75%        61.000000      60.000000      60.000000      60.000000  
&lt;&#x2F;span&gt;&lt;span&gt;max        80.000000      80.000000      80.000000      80.000000  
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;frequency-table&quot;&gt;Frequency Table&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;#     Times Drawn
&lt;&#x2F;span&gt;&lt;span&gt;1     140137
&lt;&#x2F;span&gt;&lt;span&gt;2     140219
&lt;&#x2F;span&gt;&lt;span&gt;3     140632
&lt;&#x2F;span&gt;&lt;span&gt;4     140107
&lt;&#x2F;span&gt;&lt;span&gt;5     139789
&lt;&#x2F;span&gt;&lt;span&gt;6     139551
&lt;&#x2F;span&gt;&lt;span&gt;7     139568
&lt;&#x2F;span&gt;&lt;span&gt;8     140095
&lt;&#x2F;span&gt;&lt;span&gt;9     139330
&lt;&#x2F;span&gt;&lt;span&gt;10    139571
&lt;&#x2F;span&gt;&lt;span&gt;11    139371
&lt;&#x2F;span&gt;&lt;span&gt;12    139436
&lt;&#x2F;span&gt;&lt;span&gt;13    139971
&lt;&#x2F;span&gt;&lt;span&gt;14    140205
&lt;&#x2F;span&gt;&lt;span&gt;15    140481
&lt;&#x2F;span&gt;&lt;span&gt;16    140525
&lt;&#x2F;span&gt;&lt;span&gt;17    139383
&lt;&#x2F;span&gt;&lt;span&gt;18    140004
&lt;&#x2F;span&gt;&lt;span&gt;19    140090
&lt;&#x2F;span&gt;&lt;span&gt;20    139587
&lt;&#x2F;span&gt;&lt;span&gt;21    140146
&lt;&#x2F;span&gt;&lt;span&gt;22    140410
&lt;&#x2F;span&gt;&lt;span&gt;23    139166
&lt;&#x2F;span&gt;&lt;span&gt;24    139879
&lt;&#x2F;span&gt;&lt;span&gt;25    139936
&lt;&#x2F;span&gt;&lt;span&gt;26    140687
&lt;&#x2F;span&gt;&lt;span&gt;27    140179
&lt;&#x2F;span&gt;&lt;span&gt;28    140504
&lt;&#x2F;span&gt;&lt;span&gt;29    140041
&lt;&#x2F;span&gt;&lt;span&gt;30    140000
&lt;&#x2F;span&gt;&lt;span&gt;31    139548
&lt;&#x2F;span&gt;&lt;span&gt;32    139418
&lt;&#x2F;span&gt;&lt;span&gt;33    139196
&lt;&#x2F;span&gt;&lt;span&gt;34    140519
&lt;&#x2F;span&gt;&lt;span&gt;35    139883
&lt;&#x2F;span&gt;&lt;span&gt;36    139892
&lt;&#x2F;span&gt;&lt;span&gt;37    139518
&lt;&#x2F;span&gt;&lt;span&gt;38    139864
&lt;&#x2F;span&gt;&lt;span&gt;39    140237
&lt;&#x2F;span&gt;&lt;span&gt;40    139737
&lt;&#x2F;span&gt;&lt;span&gt;41    139868
&lt;&#x2F;span&gt;&lt;span&gt;42    139994
&lt;&#x2F;span&gt;&lt;span&gt;43    140063
&lt;&#x2F;span&gt;&lt;span&gt;44    139436
&lt;&#x2F;span&gt;&lt;span&gt;45    139830
&lt;&#x2F;span&gt;&lt;span&gt;46    139961
&lt;&#x2F;span&gt;&lt;span&gt;47    139115
&lt;&#x2F;span&gt;&lt;span&gt;48    139872
&lt;&#x2F;span&gt;&lt;span&gt;49    139829
&lt;&#x2F;span&gt;&lt;span&gt;50    140115
&lt;&#x2F;span&gt;&lt;span&gt;51    140007
&lt;&#x2F;span&gt;&lt;span&gt;52    140355
&lt;&#x2F;span&gt;&lt;span&gt;53    139289
&lt;&#x2F;span&gt;&lt;span&gt;54    139049
&lt;&#x2F;span&gt;&lt;span&gt;55    139257
&lt;&#x2F;span&gt;&lt;span&gt;56    139994
&lt;&#x2F;span&gt;&lt;span&gt;57    139720
&lt;&#x2F;span&gt;&lt;span&gt;58    140023
&lt;&#x2F;span&gt;&lt;span&gt;59    139763
&lt;&#x2F;span&gt;&lt;span&gt;60    139454
&lt;&#x2F;span&gt;&lt;span&gt;61    139506
&lt;&#x2F;span&gt;&lt;span&gt;62    140186
&lt;&#x2F;span&gt;&lt;span&gt;63    140134
&lt;&#x2F;span&gt;&lt;span&gt;64    140397
&lt;&#x2F;span&gt;&lt;span&gt;65    139743
&lt;&#x2F;span&gt;&lt;span&gt;66    139802
&lt;&#x2F;span&gt;&lt;span&gt;67    139635
&lt;&#x2F;span&gt;&lt;span&gt;68    139592
&lt;&#x2F;span&gt;&lt;span&gt;69    139732
&lt;&#x2F;span&gt;&lt;span&gt;70    139873
&lt;&#x2F;span&gt;&lt;span&gt;71    139952
&lt;&#x2F;span&gt;&lt;span&gt;72    139981
&lt;&#x2F;span&gt;&lt;span&gt;73    139953
&lt;&#x2F;span&gt;&lt;span&gt;74    140312
&lt;&#x2F;span&gt;&lt;span&gt;75    140471
&lt;&#x2F;span&gt;&lt;span&gt;76    139809
&lt;&#x2F;span&gt;&lt;span&gt;77    139709
&lt;&#x2F;span&gt;&lt;span&gt;78    139629
&lt;&#x2F;span&gt;&lt;span&gt;79    139813
&lt;&#x2F;span&gt;&lt;span&gt;80    140065
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Race conditions in Cloud Security Posture Management</title>
        <published>2023-08-16T00:00:00+00:00</published>
        <updated>2024-02-02T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/race-conditions-in-cspm/" type="text/html"/>
        <id>https://me.costaskou.com/articles/race-conditions-in-cspm/</id>
        
        <content type="html">&lt;h3 id=&quot;race-conditions-in-cloud-security-posture-management&quot;&gt;Race Conditions in Cloud Security Posture Management&lt;&#x2F;h3&gt;
&lt;p&gt;Race conditions - the archenemy of all detective and corrective controls.&lt;&#x2F;p&gt;
&lt;p&gt;Cloud Security Posture Management (CSPM) a well established market with a market cap &lt;a href=&quot;https:&#x2F;&#x2F;www.bloomberg.com&#x2F;press-releases&#x2F;2022-04-13&#x2F;cloud-security-posture-management-market-worth-8-6-billion-by-2027-exclusive-report-by-marketsandmarkets&quot;&gt;north of US$ 4 billion&lt;&#x2F;a&gt;, including large SaaS products like Prisma and Wiz to open source solutions like Cloud Custodian.&lt;&#x2F;p&gt;
&lt;p&gt;Most enterprises with a cloud presence will have some form of a CSPM.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m using CSPM as an example. There&#x27;s a lot of nuance in the market today, with tooling focusing on assets, relationships, remediations, workload coverage, etc. The principle applies to Cloud Workload Protection Platform (CWPP), or any other tech that works on the same basis.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re on AWS for example, your CSPM will either try to call &lt;code&gt;Describe*&lt;&#x2F;code&gt; every so often and potentially combine this with a CloudTrail event.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that if preventive controls aren&#x27;t possible, the CSPM will detect and even remediate or at least report the security event. According to the &lt;a href=&quot;https:&#x2F;&#x2F;www.ibm.com&#x2F;reports&#x2F;data-breach&quot;&gt;SANS cloud security survey&lt;&#x2F;a&gt;, misconfigurations of cloud services played a part in ~42% of all attacks. 
And through the power of &lt;em&gt;the cloud&lt;&#x2F;em&gt; we can automatically remediate these misconfigurations.&lt;&#x2F;p&gt;
&lt;p&gt;In AWS preventive controls, those described in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;whitepapers&#x2F;latest&#x2F;building-a-data-perimeter-on-aws&#x2F;building-a-data-perimeter-on-aws.html&quot;&gt;data perimeter&lt;&#x2F;a&gt; for example, are relatively new. Restructuring your organisation with a data perimeter in mind requires a significant effort. 
You&#x27;ll need to rebuild and rethink about foundational services. Which is why I believe CSPMs will continue to thrive and continue to fill a gap in the market.&lt;&#x2F;p&gt;
&lt;p&gt;The fist problem with detective and corrective controls is that they are bound to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Time-of-check_to_time-of-use&quot;&gt;TOCTOU&lt;&#x2F;a&gt; race conditions. The time that it takes for an event to be published in an audit log (detected) and then corrected, is enough for an adversary to exploit the misconfiguration. In reality this is due to delivery time gaps, for example &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cloudtrail&#x2F;faqs&#x2F;&quot;&gt;CloudTrail delivers an event within 5 minutes of the API call&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In reality it&#x27;s ~5 seconds, which is plenty of time to exploit a detective&#x2F;corrective control combo. I&#x27;m picking CloudTrail as an example, other Cloud Service Providers (CSP) are on the same level more or less.&lt;&#x2F;p&gt;
&lt;p&gt;The second problem with CSP&#x27;s APIs is that they fail all the time. Because that&#x27;s how computers work.
It could be throttling, it could be elevated error rates, a self-inflicted &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;compute&#x2F;detecting-and-stopping-recursive-loops-in-aws-lambda-functions&#x2F;&quot;&gt;recursive loop&lt;&#x2F;a&gt;, or an attacker DoSing your quota so that the CSPM won&#x27;t be able to query your account.
The outcome is the same. Your CSPM fails to get an accurate view of a resource. That &lt;code&gt;Describe*&lt;&#x2F;code&gt; call fails. The attacker can create a window of opportunity to elude the detection of your tooling.
Your CSPM doesn&#x27;t have a special partner&#x27;s API. We all use the same APIs.&lt;&#x2F;p&gt;
&lt;p&gt;In other words &lt;strong&gt;you shouldn&#x27;t lean exclusively on the capabilities of detective and corrective controls, despite their allure of automation.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Self-healing is great, preventing is better, understanding all failure modes is the best.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Here&#x27;s a typical scenario:&lt;&#x2F;p&gt;
&lt;p&gt;Application teams in your organisation have the power to manage their network with guardrails. App teams can create VPCs without public subnets and use PrivateLink. The most common service they reach out is S3, and they create an S3 VPC gateway endpoint, and modify its policy to reach their buckets.&lt;&#x2F;p&gt;
&lt;p&gt;The threat we&#x27;re trying to mitigate here is that an attacker inside the VPC - with app team privileges - can reach out to &lt;em&gt;any&lt;&#x2F;em&gt; bucket via this VPC endpoint. You can use &lt;code&gt;aws:PrincipalAccount&lt;&#x2F;code&gt;, to stop the attacker from bringing their own credentials, but that&#x27;s about it. You can treat this as a non-malicious misconfiguration as well, but we&#x27;ll stick with our attacker persona. &lt;&#x2F;p&gt;
&lt;p&gt;You can&#x27;t use an SCP on all identities like &lt;code&gt;aws:ResourceAccount&lt;&#x2F;code&gt; and co. because there are legitimate usecases for reaching out to S3 buckets that sit outside your AWS org. For example &lt;code&gt;arn:aws:s3:::repo.*.amazonaws.com&lt;&#x2F;code&gt; used for building your Amazon Linux 2 golden AMIs.&lt;&#x2F;p&gt;
&lt;p&gt;You decide to lean against your CSPM. You have an allowlist of buckets and when an app team creates an VPC Endpoint the CSPM &lt;em&gt;detects&lt;&#x2F;em&gt; the event, checks the endpoint policy, and provides a &lt;em&gt;corrective&lt;&#x2F;em&gt; action by applying a stricter endpoint policy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;race-conditions-in-cspm&#x2F;cspm-good-sequence.png&quot; alt=&quot;cspm-good-sequence.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The app team creates an S3 endpoint, CSPM picks up the event from CloudTrail, and applies the default restricted policy.
When they try to &lt;code&gt;GetObject&lt;&#x2F;code&gt; the VPC endpoint applied by the CSPM enforces the bucket allowlist.&lt;&#x2F;p&gt;
&lt;p&gt;This is the happy path for the CSPM. The remediation action takes place before the &amp;quot;exfiltration&amp;quot; event. However, &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cloudtrail&#x2F;faqs&#x2F;&quot;&gt;typically CloudTrail delivers an event within 5 minutes of the API call&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;The race condition is on the last two steps. 
If the attacker manages to &lt;code&gt;GetObject&lt;&#x2F;code&gt; before the restrictive policy is applied - and sometimes they get 5 minutes - they could establish a connection to their S3 bucket.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;race-conditions-in-cspm&#x2F;cspm-critical-bad-sequence.png&quot; alt=&quot;cspm-critical-bad-sequence.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Once a connection has been authenticated and authorised via the endpoint, the policy change on the endpoint &lt;em&gt;will not&lt;&#x2F;em&gt; reset the connection.
You might be thinking, &amp;quot;the attacker needs to recreate the endpoint until they win the race condition&amp;quot; and that&#x27;s slow and noisy. Unless the app team can also &lt;code&gt;ModifyVPCEndpoint&lt;&#x2F;code&gt;, in which case the attack becomes trivial.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what the happy path for the attacker looks like in that case.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;race-conditions-in-cspm&#x2F;cspm-spam-modify.png&quot; alt=&quot;cspm-spam-modify.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s noisy, and it will be detected after the fact with frequency analysis - if you do this sort of thing - on the CloudTrail events.&lt;&#x2F;p&gt;
&lt;p&gt;For our scenario - bar any preventive controls on the IAM Identities - that would be as good as it gets.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Examples where this type of race condition is applicable in AWS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;&#x2F;&gt;
All services with resource policies&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;&#x2F;&gt;
All VPC Endpoints with policies&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;&#x2F;&gt;
VPC Endpoint connections to external endpoint services and vice versa&lt;&#x2F;li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;&#x2F;&gt;
Role policy attachment enforcement&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Next time you revisit your controls and remediation strategy, review if you should follow a different strategy altogether.&lt;&#x2F;p&gt;
&lt;p&gt;You can read &lt;a href=&quot;&#x2F;articles&#x2F;race-conditions-in-cspm-part-2&#x2F;&quot;&gt;part 2&lt;&#x2F;a&gt; for follow up practical example.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>From Medium.com to Zola</title>
        <published>2023-07-18T00:00:00+00:00</published>
        <updated>2023-07-18T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/from-medium-com-to-zola/" type="text/html"/>
        <id>https://me.costaskou.com/articles/from-medium-com-to-zola/</id>
        
        <content type="html">&lt;p&gt;I like Medium. It&#x27;s where I started eponymously blogging. Medium publications are great and the workflow is pretty neat. 
Lots of good content and publications are still in Medium.&lt;&#x2F;p&gt;
&lt;p&gt;But I really like tables. Maybe it&#x27;s because I&#x27;ve spent a part of my life in spreadsheets. Tables are probably one of Markdown&#x27;s pain points.
There is no good way to style a table in Markdown. Not only because there are at least &lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#tables&quot;&gt;three different ways&lt;&#x2F;a&gt; to write a table, but because after 10 rows, no matter which Markdown extension I&#x27;m using, I stop liking working with tables.
I still prefer it over having no tables, or having to take a screenshot and embed and image of the table.&lt;&#x2F;p&gt;
&lt;p&gt;I also like syntax highlighting. Embedding gists from GitHub and going back and forth, is frustrating at times.
These are things that medium doesn&#x27;t do, and I like to do. &lt;&#x2F;p&gt;
&lt;p&gt;I wanted &lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Tables and code highlighting &lt;&#x2F;li&gt;
&lt;li&gt;Not to host or maintain anything&lt;&#x2F;li&gt;
&lt;li&gt;Write content in Markdown or HTML&lt;&#x2F;li&gt;
&lt;li&gt;Export content easily&lt;&#x2F;li&gt;
&lt;li&gt;Draft and publish using the same solution&lt;&#x2F;li&gt;
&lt;li&gt;Not break the bank&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Hosted CMS sounded good but I couldn&#x27;t find one that fulfilled all of the above.
The next step was to pick from one of the 2^10 static site generators out there and then pick the hosting which was probably going to be git based anyway.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zola&quot;&gt;Zola&lt;&#x2F;h2&gt;
&lt;p&gt;I picked &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;. It has a lot of themes, it&#x27;s easy to install, configurable, and it looks like I can work with &lt;a href=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;from-medium-com-to-zola&#x2F;tera.netflify.com&quot;&gt;Tera&lt;&#x2F;a&gt;, since it&#x27;s quite similar to Jinja2.&lt;&#x2F;p&gt;
&lt;p&gt;A great feature is the &amp;quot;live&amp;quot; view. You can run &lt;code&gt;zola serve&lt;&#x2F;code&gt;, and zola will setup a watcher under your content. Every time you save zola will build the content on the fly and serve it. This is a huge time saver, and makes writing a pleasant experience.&lt;&#x2F;p&gt;
&lt;p&gt;The difficult part was figuring out Zola&#x27;s content layout and then converting medium&#x27;s HTML to Markdown with frontmatter.
The docs are great, and there are multiple examples.&lt;&#x2F;p&gt;
&lt;p&gt;For the conversion &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;costasko&#x2F;medium2zola&quot;&gt;I wrote a script&lt;&#x2F;a&gt; to do the heavy lifting with &lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;pandoc&lt;&#x2F;a&gt; converting HTML to Markdown.&lt;&#x2F;p&gt;
&lt;p&gt;I looked at the deployment docs on Zola, and picked Cloudflare Pages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosting&quot;&gt;Hosting&lt;&#x2F;h2&gt;
&lt;p&gt;Make a repo in GitHub or GitLab, push your markdown. You can largely follow &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;deployment&#x2F;cloudflare-pages&#x2F;&quot;&gt;this guide&lt;&#x2F;a&gt; just beware that Clouflare pages &lt;a href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;pages&#x2F;platform&#x2F;language-support-and-tools&#x2F;&quot;&gt;v2 build system doesn&#x27;t support zola&lt;&#x2F;a&gt;, yet.&lt;&#x2F;p&gt;
&lt;p&gt;You can now setup a custom domain and you&#x27;re good to go.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The shared responsibility of credential stuffing</title>
        <published>2023-01-17T00:00:00+00:00</published>
        <updated>2023-01-17T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/the-shared-responsibility-of-credential-stuffing/" type="text/html"/>
        <id>https://me.costaskou.com/articles/the-shared-responsibility-of-credential-stuffing/</id>
        
        <content type="html">&lt;h3 id=&quot;9246&quot; class=&quot;graf graf--h3 graf--leading graf--title&quot;&gt;The shared responsibility of credential stuffing&lt;&#x2F;h3&gt;
&lt;p&gt;If your account falls victim to a credential stuffing attack, whose
responsibility is it ?&lt;&#x2F;p&gt;
&lt;p&gt;Drawing a parallel from the &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;compliance&#x2F;shared-responsibility-model&#x2F;&quot;&gt;shared responsibility model of cloud
service providers like
AWS&lt;&#x2F;a&gt;, credential stuffing attacks have a not
so well defined responsibility model. Whose responsibility is it if your
account on a hosted provider gets breached ?&lt;&#x2F;p&gt;
&lt;p&gt;Well if it was LastPass you know the answer. &lt;a href=&quot;https:&#x2F;&#x2F;blog.lastpass.com&#x2F;2022&#x2F;12&#x2F;notice-of-recent-security-incident&#x2F;&quot;&gt;LastPass was
compromised&lt;&#x2F;a&gt; and attackers got hold of credentials.
The responsibility for protecting your account data, is on LastPass.
LastPass was compromised, so the answer is simple, not your fault.&lt;&#x2F;p&gt;
&lt;p&gt;We conclude then: If you don&#x27;t host your data, and your account gets
compromised, then the responsibility is with the vendor that hosts your
data. This isn&#x27;t groundbreaking it happens already in the retail banking
system --- in the UK --- and with GDPR.&lt;&#x2F;p&gt;
&lt;p&gt;The responsibility the banks have when it comes to retail fraud, in the
UK is called &amp;quot;The Quincecare duty&amp;quot;. The Quincecare duty originated from
Barclays Bank plc v Quincecare, in which case the courts decided that
the bank has a duty of care to refrain from executing fraudulent
payments on the behalf of their customers. Here&#x27;s the definition from
&lt;a href=&quot;https:&#x2F;&#x2F;uk.practicallaw.thomsonreuters.com&#x2F;w-036-3691?transitionType=Default&amp;amp;contextData=%28sc.Default%29&amp;amp;firstPage=true#&quot;&gt;Thomson
Reuters&lt;&#x2F;a&gt;&#x27; practical law:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It essentially consists of an implied term and a co-extensive duty of
care owed by the bank to its customer to refrain from making or
executing a payment when the bank is put on inquiry that a payment
instruction from its customer may be a result of fraud.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We also have GDPR --- in the EU --- which introduces a duty on all
organisations to report certain personal data breaches to the relevant
supervisory authority, within 72 hours of becoming aware of the breach.&lt;&#x2F;p&gt;
&lt;p&gt;Our logic isn&#x27;t unfounded, and we have precedence. The vendor that hosts
my data is responsible for the security of the data.&lt;&#x2F;p&gt;
&lt;p&gt;Adversaries launched a credential stuffing attack to Norton Password
Manager, here&#x27;s their statement:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Our own systems were not compromised. However, we strongly believe
that an unauthorized third party knows and has utilized your username
and password for your account[...]&amp;quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Quote from &lt;a href=&quot;https:&#x2F;&#x2F;www.bleepingcomputer.com&#x2F;news&#x2F;security&#x2F;nortonlifelock-warns-that-hackers-breached-password-manager-accounts&#x2F;&quot;&gt;bleeping
computer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Your account was compromised, but it wasn&#x27;t the Norton Password Manager
systems that got breached, it was your account --- according to Norton.&lt;&#x2F;p&gt;
&lt;p&gt;GM has a similar stance, from &lt;a href=&quot;https:&#x2F;&#x2F;www.malwarebytes.com&#x2F;blog&#x2F;news&#x2F;2022&#x2F;05&#x2F;general-motors-suffers-credential-stuffing-attack&quot;&gt;malware
bytes&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Based on the investigation to date, there is no evidence that the log
in information was obtained from GM itself. We believe that
unauthorized parties gained access to customer login credentials that
were previously compromised on other non-GM sites and then reused
those credentials on the customer&#x27;s GM account.&amp;quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For what it&#x27;s worth, I&#x27;m using these incidents as examples. Companies
take this stance when it comes to credential stuffing attacks. Worse,
some of them don&#x27;t detect, warn or admit it.&lt;&#x2F;p&gt;
&lt;p&gt;Well let&#x27;s start with understanding what credential stuffing attacks are
and how they work. I&#x27;ve &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&#x2F;the-economics-of-credential-stuffing-attacks-c2dd5f77a48e&quot;&gt;written about credential stuffing attacks in
the
past&lt;&#x2F;a&gt; but let me recap.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*kM3XaQTHJgrCxk2b&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*kM3XaQTHJgrCxk2b&quot; data-width=&quot;4480&quot;
data-height=&quot;6720&quot; data-unsplash-photo-id=&quot;zn2M1iILVUk&quot;
data-is-featured=&quot;true&quot; alt=&quot;An open book with a pair of keys placed in the middle&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Photo by &lt;a
href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@sixteenmilesout?utm_source=medium&amp;amp;utm_medium=referral&quot;
class=&quot;markup--anchor markup--figure-anchor&quot;
data-href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@sixteenmilesout?utm_source=medium&amp;amp;utm_medium=referral&quot;
rel=&quot;photo-creator noopener&quot; target=&quot;_blank&quot;&gt;Sixteen Miles Out&lt;&#x2F;a&gt; on &lt;a
href=&quot;https:&#x2F;&#x2F;unsplash.com?utm_source=medium&amp;amp;utm_medium=referral&quot;
class=&quot;markup--anchor markup--figure-anchor&quot;
data-href=&quot;https:&#x2F;&#x2F;unsplash.com?utm_source=medium&amp;amp;utm_medium=referral&quot;
rel=&quot;photo-source noopener&quot; target=&quot;_blank&quot;&gt;Unsplash&lt;&#x2F;a&gt;&lt;&#x2F;figcaption&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If you are using the same password in more than one website you are most
likely going to fall victim to a credential stuffing attack.&lt;&#x2F;p&gt;
&lt;p&gt;Chances are someone is going to try and log in with these credentials on
the an insurance provider, a bank, or Netflix. A different service that
the one that your credentials --- username and password --- were
compromised. Once logged in, the attacker knows that these credentials
work for this website. That&#x27;s all it takes, a single login that can be
reused in other services.&lt;&#x2F;p&gt;
&lt;p&gt;The combination of your username and password --- credentials --- became
a commodity that will be sold in the equivalent of an underground
market. The price that your credentials will be sold is based on your
region, type of accounts, and markets where the credentials will be
listed. Your Netflix account for example might go for just over a a
dozen USD for a year.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s the same principle as having one key --- a skeleton key --- that
opens all doors. If a thief gets a hold of it, they can access your car,
and your house.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually your accounts can be sold separately, en masse, or bundled
with millions of other credentials. Sometimes the credentials are being
sold under the pretense of &amp;quot;account sharing&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s not always invite-only forums on the &amp;quot;dark web&amp;quot;. Go to your
favourite consumer-to-consumer marketplace and search for a
subscription. You&#x27;ll most likely find someone &amp;quot;sharing&amp;quot; one with you,
for a very low price. They just so happen to have about 50 more of
these.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*xk-ISiXGmIhUHKap&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*xk-ISiXGmIhUHKap&quot; data-width=&quot;4000&quot;
data-height=&quot;6000&quot; data-unsplash-photo-id=&quot;FLW5Saogvt8&quot; alt=&quot;Street view of food market with big a big red sign that reads public market center&quot;&#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Photo by &lt;a
href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@ishaankansal12?utm_source=medium&amp;amp;utm_medium=referral&quot;
class=&quot;markup--anchor markup--figure-anchor&quot;
data-href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@ishaankansal12?utm_source=medium&amp;amp;utm_medium=referral&quot;
rel=&quot;photo-creator noopener&quot; target=&quot;_blank&quot;&gt;Ishaan Kansal&lt;&#x2F;a&gt; on &lt;a
href=&quot;https:&#x2F;&#x2F;unsplash.com?utm_source=medium&amp;amp;utm_medium=referral&quot;
class=&quot;markup--anchor markup--figure-anchor&quot;
data-href=&quot;https:&#x2F;&#x2F;unsplash.com?utm_source=medium&amp;amp;utm_medium=referral&quot;
rel=&quot;photo-source noopener&quot; target=&quot;_blank&quot;&gt;Unsplash&lt;&#x2F;a&gt;&lt;&#x2F;figcaption&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Back to our original question.&lt;&#x2F;p&gt;
&lt;p&gt;The vendor that hosts our data notifies their customers that the account
they hold with them was breached, it was a credential stuffing attack.
Who is responsible?&lt;&#x2F;p&gt;
&lt;p&gt;Following with our key metaphor from earlier, it&#x27;s reasonable to think
of your credentials as your &amp;quot;property&amp;quot;. Your password is your data.&lt;&#x2F;p&gt;
&lt;p&gt;If your account gets compromised one way or the other, the
vendor --- should--- have a duty of care to protect, warn and deter you
from falling victim to a credential stuffing attack. It&#x27;s your data that
gets compromised. This isn&#x27;t different to a GDPR breach notification. **
We shouldn&#x27;t pass the blame to the user, en masse, and by default.**&lt;&#x2F;p&gt;
&lt;p&gt;And if you&#x27;re looking for a technology panacea to solve this problem,
maybe PassKey is the answer. Apple, Google, and others have now agreed
on a new and secure way of authenticating users to websites.&lt;&#x2F;p&gt;
&lt;p&gt;This is fundamentally a lot more secure as it stops attacks like
credential stuffing and phishing on their tracks. &amp;quot;Hosted&amp;quot; PassKey has
been built is such a way that even if your iCloud or a Google server
that has your PassKey gets compromised, the attacker wouldn&#x27;t be able to
access them.&lt;&#x2F;p&gt;
&lt;p&gt;By &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&quot;&gt;Costas Kourmpoglou&lt;&#x2F;a&gt;
on &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;p&#x2F;b35d9b9e535a&quot;&gt;January 17, 2023&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&#x2F;the-shared-responsibility-of-credential-stuffing-b35d9b9e535a&quot;&gt;Canonical
link&lt;&#x2F;a&gt;{.p-canonical}&lt;&#x2F;p&gt;
&lt;p&gt;Exported from &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&quot;&gt;Medium&lt;&#x2F;a&gt; on July 3, 2023.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Querying and Visualising OctoDNS records with Neo4j</title>
        <published>2020-09-19T00:00:00+00:00</published>
        <updated>2020-09-19T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/querying-and-visualising-octodns-records-with-neo4j/" type="text/html"/>
        <id>https://me.costaskou.com/articles/querying-and-visualising-octodns-records-with-neo4j/</id>
        
        <content type="html">&lt;h1 id=&quot;querying-and-visualising-octodns-records-with-neo4j&quot;&gt;Querying and Visualising OctoDNS records with Neo4j&lt;&#x2F;h1&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;visualising-dns-records-with-neo4j&quot;&gt;Visualising DNS records with Neo4j&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;octodns&quot;&gt;OctoDNS&lt;&#x2F;a&gt; provides a toolset for managing DNS
records across multiple providers. Built by Github and using a typical
YAML structure, to describe what a DNS zone should look like. The
example taken from the getting-started section of the repo, describes
what an A record at example.com looks like.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yml&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-yml &quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e8bf6a;&quot;&gt;ttl&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;60
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e8bf6a;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e8bf6a;&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;1.2.3.4
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;1.2.3.5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;neo4j.com&#x2F;&quot;&gt;Neo4j&lt;&#x2F;a&gt; is a
graph database platform, which focuses on the relationships between data
records. Using its own query language, cypher, Neo4j makes it easy to
visualise graphs and explore the relationships of your data.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why ?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
Declarative configuration is about treating infrastructure as data, which is more portable than code, and enables workflows that manipulate desired state based on policy, while serializing the results between each step of the pipeline.
&lt;p&gt;&lt;a
href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;kelseyhightower&#x2F;status&#x2F;1164194470436302848&quot;&gt;
From @kelseyhightower
&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The declarative nature of OctoDNS, allows us to treat the config as
data. We can then query our data and ask all sorts of questions about
the relationships in our DNS records. My preferred tool of choice here
is Neo4j as it provides a way to visualise these relationships out of
box.&lt;&#x2F;p&gt;
&lt;p&gt;We can explore patterns, relationships, and overall develop intuition.
From &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;ft-product-technology&#x2F;threat-modelling-at-the-ft-4d628ea3c5a4&quot;&gt;threat modelling
sessions&lt;&#x2F;a&gt;, as a starting point for intel gathering, finding
dangling domain records for bug bounties, or to understand the
components that engineers used in order to build the system.&lt;&#x2F;p&gt;
&lt;p&gt;In systems that make use of more than one platform or tech stack, the
question of &amp;quot;where does this thing point to &amp;quot;, comes up frequently.&lt;&#x2F;p&gt;
&lt;p&gt;E.g., &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;k8s.io&#x2F;blob&#x2F;master&#x2F;dns&#x2F;zone-configs&#x2F;k8s.io._0_base.yaml#L108&quot;&gt;where does this
run&lt;&#x2F;a&gt;[1] and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;k8s.io&#x2F;blob&#x2F;c6f52a12c132ac149895bc706dcaa22df1066e58&#x2F;dns&#x2F;zone-configs&#x2F;kubernetes.io._0_base.yaml#L63&quot;&gt;what is
this&lt;&#x2F;a&gt;[2] ?&lt;&#x2F;p&gt;
&lt;p&gt;Finally by visualising and having a picture might not always be worth a
thousand words, but it will definitely complement them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How ?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We will parse the zone config in YAML. As an example we will use the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;k8s.io&#x2F;tree&#x2F;master&#x2F;dns&#x2F;zone-configs&quot;&gt;zone
config&lt;&#x2F;a&gt; of k8s.io, and extract the zone records,
and values. For the purposes of this, I only care about A and CNAME
records. We will then try and enrich the data. Specifically, I&#x27;m
matching IP ranges to vendors. This way I can identify if an A record
belongs to Google or some other vendor. These IP ranges are published by
GCP, AWS, etc. For example, these are the IP ranges for GCP.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Results&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is what the whole graph for k8s.io zones looks like. The nodes in
yellow are the zone records, the nodes in pink are the values. There is
only one relationship type &amp;quot;POINTS_TO&amp;quot;. In other words a node in yellow
will be &amp;quot;k8s.io&amp;quot; and the node in pink will be &amp;quot;34.107.204.206&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*VFq3LqwWzTUAIE85&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*VFq3LqwWzTUAIE85&quot; data-width=&quot;1592&quot;
data-height=&quot;1600&quot; data-is-featured=&quot;true&quot;
alt=&quot;Connected zone and value nodes with small and a large cluster&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;If you graph any system, patterns emerge — Pi, 1998,
paraphrased&lt;&#x2F;figcaption&gt;
&lt;p&gt;Most nodes come in triplets. This is because the canary release and the
live release point to the same value.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span&gt; +short k8s.io
&lt;&#x2F;span&gt;&lt;span&gt;34.107.204.206 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;dig&lt;&#x2F;span&gt;&lt;span&gt; +short canary.k8s.io
&lt;&#x2F;span&gt;&lt;span&gt;34.107.204.206
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*rcZGYE2_tTxSVuJa&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*rcZGYE2_tTxSVuJa&quot; data-width=&quot;880&quot;
data-height=&quot;497&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Owner&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;querying-and-visualising-octodns-records-with-neo4j&#x2F;7b58f296-1bcd-4781-9c86-c0ee68b45790.jpeg&quot; alt=&quot;K8s.io&#x2F;kubernets.io is almost equally hosted on Netlify and GCP&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;K8s.io&#x2F;kubernets.io is almost equally hosted on Netlify
and GCP&lt;&#x2F;figcaption&gt;
&lt;p&gt;The data enrich helps us identify the owner of the zone record. Doing a
summary, 38 of k8s.io&#x27;s records point to Netlify domains.&lt;&#x2F;p&gt;
&lt;p&gt;Finally the large cluster in the middle points to redirect.k8s.io .&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*c2P_lf85H1Vie_ZX&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*c2P_lf85H1Vie_ZX&quot; data-width=&quot;878&quot;
data-height=&quot;494&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;The Unknown Owner of redirect.k8s.io&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;strong&gt;Where do we go now?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This pattern, of treating configuration as data, is already being used
in kubernetes clusters, see
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;spekt8&#x2F;spekt8&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;spekt8&#x2F;spekt8&lt;&#x2F;a&gt;. But we can extend it further to DNS
records,terraform resources, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Visualising structures helps in making sense of higher order concepts.
We can even take it a step further and try to visualise every
relationship of our infrastructure from DNS record to kubernetes pod.&lt;&#x2F;p&gt;
&lt;p&gt;By treating config as data, we can query it in all sorts of ways. Going
back to questions [1] and [2], we know that this isn&#x27;t running in
GCP but we unfortunately still don&#x27;t know what [2] is!&lt;&#x2F;p&gt;
&lt;p&gt;Try it on your data and &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;costasmko&quot;&gt;let me
know&lt;&#x2F;a&gt; what that looks like.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;costasko&#x2F;octodns2neo4j&quot;&gt;You can find the
repo&lt;&#x2F;a&gt; to try the above on your own here.&lt;&#x2F;p&gt;
&lt;p&gt;By &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&quot;&gt;Costas Kourmpoglou&lt;&#x2F;a&gt;{.p-author .h-card}
on &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;p&#x2F;f4f72ab2d474&quot;&gt;September 19, 2020&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&#x2F;querying-and-visualising-octodns-records-with-neo4j-f4f72ab2d474&quot;&gt;Canonical
link&lt;&#x2F;a&gt;{.p-canonical}&lt;&#x2F;p&gt;
&lt;p&gt;Exported from &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&quot;&gt;Medium&lt;&#x2F;a&gt; on July 3, 2023.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The economics of credential stuffing attacks</title>
        <published>2020-06-04T00:00:00+00:00</published>
        <updated>2020-06-04T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/the-economics-of-credential-stuffing-attacks/" type="text/html"/>
        <id>https://me.costaskou.com/articles/the-economics-of-credential-stuffing-attacks/</id>
        
        <content type="html">&lt;h1 id=&quot;the-economics-of-credential-stuffing-attacks&quot;&gt;The economics of credential stuffing attacks&lt;&#x2F;h1&gt;
&lt;p&gt;If you run a website with a login form, you have either experienced a
credential stuffing attack or it has gone undetected.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;the-economics-of-credential-stuffing-attacks-1&quot;&gt;The economics of credential stuffing attacks&lt;&#x2F;h3&gt;
&lt;p&gt;If you run a website with a login form, you have either experienced a
credential stuffing attack or it has &lt;a href=&quot;https:&#x2F;&#x2F;www.akamai.com&#x2F;us&#x2F;en&#x2F;multimedia&#x2F;documents&#x2F;state-of-the-internet&#x2F;soti-security-credential-stuffing-attacks-and-economies-report-2019.pdf&quot;&gt;gone
undetected&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Briefly a credential stuffing attack is when someone, automatically
(most of the time) is trying to check for credential reuse against your
assets.&lt;&#x2F;p&gt;
&lt;p&gt;Why ? Because the credentials increase in value depending on which
websites they&#x27;ve got access.&lt;&#x2F;p&gt;
&lt;p&gt;The attacker tooling out there caters for everyone. From All In One
applications that you can get started with 2 clicks, with &lt;a href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;forbestechcouncil&#x2F;2019&#x2F;12&#x2F;27&#x2F;2020-the-year-of-combolist-as-a-service&#x2F;&quot;&gt;Combolist As
A
Service&lt;&#x2F;a&gt;, to full blown SaaS models.&lt;&#x2F;p&gt;
&lt;p&gt;Jarrod Overson&#x27;s talk at
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9F_3EhNrM-0&quot;&gt;PasswordsCon&lt;&#x2F;a&gt; gives an in-depth look around the evolution and return
on investment on credential stuffing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-logical-adversary&quot;&gt;The logical adversary&lt;&#x2F;h3&gt;
&lt;p&gt;A homo adversarius, like homo economicus, a perfectly rational attacker
will want to maximise their utility. If an adversary can mount an attack
against a valuable asset that has no defences, for relatively minimum
cost, they will.&lt;&#x2F;p&gt;
&lt;p&gt;If the cost of bypassing your defences exceeds the value of your assets,
they will not waste their resources on trying to defeat your defences.
Unless your assets are worth it.&lt;&#x2F;p&gt;
&lt;p&gt;This is not saying that you&#x27;ll have a single adversary and that you need
to go down the adversary-based threat modelling rabbit hole. But
credential stuffing is a numbers game, all sorts of actors will drive
by.&lt;&#x2F;p&gt;
&lt;p&gt;And the path is well known. It&#x27;s your login form.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;attacker-economics&quot;&gt;Attacker economics&lt;&#x2F;h3&gt;
&lt;p&gt;We are going to use data on the average value of valid compromised
credentials from
&lt;a href=&quot;https:&#x2F;&#x2F;www.keepersecurity.com&#x2F;en_GB&#x2F;how-much-is-my-information-worth-to-hacker-dark-web.html&quot;&gt;keepersecurity&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;www.trendmicro.com&#x2F;vinfo&#x2F;us&#x2F;security&#x2F;special-report&#x2F;cybercriminal-underground-economy-series&#x2F;global-black-market-for-stolen-data&#x2F;&quot;&gt;trendmicro&lt;&#x2F;a&gt;, and the Akamai paper referenced above.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s assume that credentials on your website are worth $2.50 and you
have 10000 accounts. You&#x27;ve decided to implement reCAPTCHA v2. The
solved reCAPTCHA rate is 1000 for ~$3.00 and you can integrate with an
API as well.&lt;&#x2F;p&gt;
&lt;p&gt;Assume no extra infrastructure costs and a success rate of 1%, that&#x27;s
100 takeovers and a ROI for the adversary of $235. With a rate of 1
attempt per second, that&#x27;s ~$79 an hour.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*SpLyyvES3vCK5OX_&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*SpLyyvES3vCK5OX_&quot; data-width=&quot;800&quot;
data-height=&quot;795&quot; data-is-featured=&quot;true&quot;
alt=&quot;Statistics from 2captcha a captcha solving service, showing the running price and waiting times&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;2captcha public stats&lt;&#x2F;figcaption&gt;
&lt;p&gt;For a lower success rate, e.g. 0.1% , the attack becomes uneconomical.
The astute mental mathematicians might have noticed that this is true,
until the value of each verified compromised account is over $3. Then
the attack becomes profitable again.&lt;&#x2F;p&gt;
&lt;p&gt;Of note is that most of these websites offering CAPTCHA solvers, have
reCAPTCHA on their registration forms.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-common-pitfall&quot;&gt;The common pitfall&lt;&#x2F;h3&gt;
&lt;p&gt;People will jump in to solve a problem, without having a clear
definition of the problem .&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hbr.org&#x2F;2017&#x2F;01&#x2F;are-you-solving-the-right-problems&quot;&gt;Organisational teams speed toward a solution, fearing that if they
spend too much time defining the problem, their superiors will punish
them for taking so long to get to the starting
line.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And security is not exempt, especially considering the sense of urgency
once an attack has taken place. In a &lt;a href=&quot;https:&#x2F;&#x2F;www.sciencedirect.com&#x2F;science&#x2F;article&#x2F;pii&#x2F;S0963868717304353&quot;&gt;recent
study&lt;&#x2F;a&gt; as part of a simulation, when it came to
making cybersecurity decisions, the experienced players under certain
scenarios, did not make better decisions to develop cybersecurity
capabilities than the inexperienced players.&lt;&#x2F;p&gt;
&lt;p&gt;From the paper:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The decision-making literature suggests that there are two reasons for
this poor performance: individuals&#x27; reliance on satisfactory results;
and their limitations in optimization searches. The decision-making
process for individuals does not involve any systematic attempt to
optimize choice; instead, they tend to choose an action with
satisfying results. Optimization requires a thorough search of all
logical possibilities, but due to the brain&#x27;s limited information
processing capacity, it proves to be unsuccessful (Evans et al.,2003).
These limitations can make individuals prone to reasoning bias, human
error, and fluctuating emotions (Keren et al., 2003).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And by now you might already know that &lt;a href=&quot;https:&#x2F;&#x2F;www.mckinsey.com&#x2F;~&#x2F;media&#x2F;McKinsey&#x2F;McKinsey%20Solutions&#x2F;Cyber%20Solutions&#x2F;Perspectives%20on%20transforming%20cybersecurity&#x2F;Transforming%20cybersecurity_March2019.ashx&quot;&gt;&amp;quot;companies&#x27; spending on
cybersecurity does not necessarily correlate with level of
protection&amp;quot;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For credential stuffing attacks this means: Look at the login trends,
identify your users, figure out their login flows. Instead of applying a
new control and mitigating or eliminating the attack, there&#x27;s an
opportunity to do better.&lt;&#x2F;p&gt;
&lt;p&gt;Adjust the login journey so that it provides a better customer
experience whilst increasing your resilience against these attacks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-do-you-do-about-it&quot;&gt;What do you do about it&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m going to provide you with with a high-level model you can apply.
Further down I also include a a non-exhaustive, in no particular order,
list of defences. Use the model to identify which defences, will make
sense for you.&lt;&#x2F;p&gt;
&lt;p&gt;As always all models are wrong, this is hopefully useful as well.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;[Calculate how much each of these solutions will cost for your
assets to implement. All of them. No mental maths. Write it
down.]{#646e}&lt;&#x2F;li&gt;
&lt;li&gt;[Some of these controls can be detrimental to your customer
experience or highly beneficial you need to consider&lt;br &#x2F;&gt;
a. You customer base&lt;br &#x2F;&gt;
b. &lt;a href=&quot;https:&#x2F;&#x2F;help.github.com&#x2F;en&#x2F;github&#x2F;authenticating-to-github&#x2F;sudo-mode&quot;&gt;Where you apply
them&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
c. How often you&#x27;ll make your customers go through them.&lt;br &#x2F;&gt;
d. If the controls are going to apply on all your customers&lt;br &#x2F;&gt;
e. Know the number of customers, understand the effect on your
product, test it.]{#b630}&lt;&#x2F;li&gt;
&lt;li&gt;[Based on what you have implemented so far understand how much it
will cost you to implement. You now have Total Cost of Ownership,
TCO = Cost of control +- customer churn&#x2F;gain]{#83c0}&lt;&#x2F;li&gt;
&lt;li&gt;[Use your favourite risk assessment methodology or incident tracker
to get the cost for the set of users susceptible to credential
stuffing. That&#x27;s your Annual Loss Expectancy(ALE).]{#0eeb}&lt;&#x2F;li&gt;
&lt;li&gt;[If you&#x27;ve had past incidents, there&#x27;s no point addressing them with
irrelevant controls. Don&#x27;t throw money to the problem.]{#60c3}&lt;&#x2F;li&gt;
&lt;li&gt;[Pick the solution with the highest positive Return On
Investment]{#1ce5}&lt;&#x2F;li&gt;
&lt;li&gt;[Repeat as necessary.]{#b2c4}&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Note the last step, repeat as necessary, defence in depth.&lt;&#x2F;p&gt;
&lt;p&gt;And here&#x27;s the list of defences, I promised earlier.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;a-simple-and-historical-approach-honeypot-fields&quot;&gt;A simple and historical approach --- Honeypot fields&lt;&#x2F;h4&gt;
&lt;p&gt;A field in a form that only a robot would submit or change its value.
This field is for robots only. &lt;a href=&quot;https:&#x2F;&#x2F;haacked.com&#x2F;archive&#x2F;2007&#x2F;09&#x2F;11&#x2F;honeypot-captcha.aspx&#x2F;&quot;&gt;Please leave
blank&lt;&#x2F;a&gt;. In the current environment this won&#x27;t
be very effective, if at all.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;the-best-known-re-captcha&quot;&gt;The best known --- (re)CAPTCHA&lt;&#x2F;h4&gt;
&lt;blockquote&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MarciRobin&#x2F;status&#x2F;998030243981033472&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;blockquote&gt;
&lt;figcaption&gt;Real life reCAPTCHA&lt;&#x2F;figcaption&gt;
&lt;p&gt;Completely Automated Public &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Turing_test&quot; title=&quot;Turing test&quot;&gt;Turing
test&lt;&#x2F;a&gt; to tell computers and humans Apart, or
CAPTCHA, invented in 1997.&lt;&#x2F;p&gt;
&lt;p&gt;It looks like since &lt;a href=&quot;https:&#x2F;&#x2F;www.cs.uic.edu&#x2F;pub&#x2F;Kanich&#x2F;Publications&#x2F;re.captchas.pdf&quot;&gt;~2009 the economics of solving
recaptchas&lt;&#x2F;a&gt; haven&#x27;t changed much. About ~$1-$1.5
per 1000 solved. However CAPTCHA is problematic because of &lt;a href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;UNDERSTANDING-WCAG20&#x2F;text-equiv-all.html&quot;&gt;its
accessibility&lt;&#x2F;a&gt;. For this reason alone, &lt;a href=&quot;https:&#x2F;&#x2F;a11y-guidelines.orange.com&#x2F;web_EN&#x2F;captcha.html&quot;&gt;orange for
example&lt;&#x2F;a&gt; are not big fans.&lt;&#x2F;p&gt;
&lt;p&gt;Notably &lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;recaptcha&#x2F;docs&#x2F;v3&quot;&gt;reCAPTCHA
v3&lt;&#x2F;a&gt;, returns a confidence interval of how
likely someone is to be a person. No clicking traffic lights.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;the-kraken-waf&quot;&gt;The kraken --- WAF&lt;&#x2F;h4&gt;
&lt;p&gt;Web Application Firewall. If you expect that rolling out the latest
version of the core ruleset and all your problems are going to go away,
you&#x27;re going to have a bad time.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re with $CLOUD_PROVIDER look at what they offer. E.g. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5AH7ISqyF4M&quot;&gt;AWS
WAF&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;do-you-run-javascript-browser-os-fingerprinting&quot;&gt;Do you run javascript --- Browser&#x2F;OS fingerprinting&lt;&#x2F;h4&gt;
&lt;p&gt;Your browser and each interaction with a website can reveal valuable
information. Give it a try with
&lt;a href=&quot;https:&#x2F;&#x2F;panopticlick.eff.org&#x2F;&quot;&gt;panopticlick&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Valve&#x2F;fingerprintjs2&quot;&gt;Fingerprinting&lt;&#x2F;a&gt; techniques will try to identify via
various methods your browser, OS, history, add-ons, location, and other
information to identify bots. Fingerprinting-based detection is fairly
complex as &lt;a href=&quot;https:&#x2F;&#x2F;datadome.co&#x2F;bot-detection&#x2F;the-state-of-the-art-of-bot-detection-black-hat-usa-2019-recap&#x2F;&quot;&gt;&amp;quot;bots are now using (almost) the exact same technologies as
humans&amp;quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Depending on how you go about it, privacy matters and more importantly
you are most likely going to be processing &lt;a href=&quot;https:&#x2F;&#x2F;www.eff.org&#x2F;deeplinks&#x2F;2018&#x2F;06&#x2F;gdpr-and-browser-fingerprinting-how-it-changes-game-sneakiest-web-trackers&quot;&gt;more personal
data&lt;&#x2F;a&gt;. You can even go to such extremes such
as &lt;a href=&quot;https:&#x2F;&#x2F;www.theregister.com&#x2F;2020&#x2F;05&#x2F;26&#x2F;ebay_port_scans_your_pc&#x2F;&quot;&gt;port
scanning&lt;&#x2F;a&gt; your customers.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;prevention-check-with-hibp-or-other-sources&quot;&gt;Prevention --- Check with HIBP or other sources&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;max&#x2F;800&#x2F;0*pUhSzunOZzq-3Kf2&quot;
class=&quot;graf-image&quot; data-image-id=&quot;0*pUhSzunOZzq-3Kf2&quot; data-width=&quot;1047&quot;
data-height=&quot;345&quot; alt=&quot;HaveIBeenPwned.com Screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Check your customers&#x27; passwords against passwords that have been part of
a known breach. It&#x27;s part of &lt;a href=&quot;https:&#x2F;&#x2F;pages.nist.gov&#x2F;800-63-3&#x2F;sp800-63b.html#-5112-memorized-secret-verifiers&quot;&gt;NIST
guidance&lt;&#x2F;a&gt; as well. Pay HaveIbeenPwned to use the
&lt;a href=&quot;https:&#x2F;&#x2F;haveibeenpwned.com&#x2F;API&#x2F;Consumers&quot;&gt;API&lt;&#x2F;a&gt; or download the hashes and build an API
of your own. . Going down this route you also have an opportunity to
inform your users and improve their overall security.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;a-new-hope-passwordless-and-webauthn&quot;&gt;A new hope --- Passwordless and WebAuthn&lt;&#x2F;h4&gt;
&lt;p&gt;Depending on the maturity of your login flow and user base, WebAuthn is
great for a low-friction passwordless login. Alternatively a well
controlled email verification style passwordless flow.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;two-factor-authentication&quot;&gt;Two-Factor Authentication&lt;&#x2F;h4&gt;
&lt;p&gt;Something you have. Even though the &lt;a href=&quot;https:&#x2F;&#x2F;www.ncsc.gov.uk&#x2F;guidance&#x2F;setting-two-factor-authentication-2fa&quot;&gt;NCSC might
suggest&lt;&#x2F;a&gt; that if a service doesn&#x27;t do 2FA you
should consider changing it, customer experience opinions vary. A longer
session length makes for a better experience.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;exotic-solutions&quot;&gt;Exotic solutions&lt;&#x2F;h4&gt;
&lt;p&gt;Proof of work, or make your users mine cryptocurrency. Contrary to
CAPTCHA you don&#x27;t want to identify if someone is human, you just want to
make them work for it.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;adaptive-solutions&quot;&gt;Adaptive Solutions&lt;&#x2F;h4&gt;
&lt;p&gt;Build behaviour models of your users. Have they logged in from a
different country across the world, maybe it&#x27;s time to send them an
email to make sure it&#x27;s them before letting them in. Can be combined
with other solutions mentioned above.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;let-credentials-be-someone-else-s-problem&quot;&gt;Let credentials be someone else&#x27;s problem&lt;&#x2F;h4&gt;
&lt;p&gt;Social login. If all your users&#x27; email addresses end with @gmail.com,
maybe it&#x27;s worth considering adding a Google Sign-in.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;where-do-we-go-now&quot;&gt;Where do we go now&lt;&#x2F;h3&gt;
&lt;p&gt;Attacker economics are fascinating and are constantly evolving. They can
give you useful insight on how adversaries evolve against your assets
and indicators on what you should do about it.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the list, you shouldn&#x27;t be thinking, &amp;quot;oh I know X will work
forever&amp;quot;. You have an opportunity to improve your customers experience
as well. Get the data and design for change.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Build your own  keyboard</title>
        <published>2018-11-04T00:00:00+00:00</published>
        <updated>2018-11-04T00:00:00+00:00</updated>
        <author>
          <name>Unknown</name>
        </author>
        <link rel="alternate" href="https://me.costaskou.com/articles/build-your-own-keyboard/" type="text/html"/>
        <id>https://me.costaskou.com/articles/build-your-own-keyboard/</id>
        
        <content type="html">&lt;h1 id=&quot;build-your-own-keyboard&quot;&gt;Build your own keyboard&lt;&#x2F;h1&gt;
&lt;p&gt;Out of all the peripherals out there, I like keyboards the most.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;assemble-your-own-keyboard&quot;&gt;Assemble your own keyboard&lt;&#x2F;h3&gt;
&lt;p&gt;Out of all the
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Peripheral&quot;&gt;peripherals&lt;&#x2F;a&gt; out there, I like keyboards the most.&lt;&#x2F;p&gt;
&lt;p&gt;I like split keyboards and I like building keyboards. This is a guide on
how you too, can build a keyboard. Specifically I&#x27;m going to walk you
through how to build a redox, split keyboard.&lt;&#x2F;p&gt;
&lt;p&gt;You will need to know how to solder and have the necessary equipment.&lt;&#x2F;p&gt;
&lt;p&gt;Check out &lt;a href=&quot;https:&#x2F;&#x2F;falba.tech&quot;&gt;https:&#x2F;&#x2F;falba.tech&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mattdibi&#x2F;redox-keyboard&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;mattdibi&#x2F;redox-keyboard&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;class=&amp;quot;graf graf--figure graf--layoutOutsetCenter graf-after--p graf--trailing&amp;quot;&amp;gt;
&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;2b385659-ec46-4257-b3aa-87b9f5d9c204.jpeg&quot; alt=&quot;Final Product&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Final Product&lt;&#x2F;figcaption&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Get all the components out! With your index finder bend the diodes in a
Π position. Then remove them from the paper holding them together.&lt;&#x2F;p&gt;
&lt;p&gt;The two PCB boards are identical. All the components will be soldered on
one side, except from the switches. Pick a PCB and start putting the
diodes through the holes. The diodes go in in the circle and square
holes. &lt;strong&gt;Orientation in diodes matters.&lt;&#x2F;strong&gt; Black end = square. This is
important!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;f7b16dd1-0ae8-4514-af7b-e1c46c1d3fd9.jpeg&quot; alt=&quot;This side will become the right side of your keyboard&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;This side will become the right side of
your keyboard&lt;&#x2F;figcaption&gt;
&lt;p&gt;As you put the diodes through the holes, you want to open the diode legs
enough so that they can hold on their own. The reason why although the
PCB clearly has LEFT written , the switches are going to be soldered on
the other side.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;7e2f11eb-d3c5-41f4-9244-b9de0304733c.jpeg&quot; alt=&quot;The back should look like this&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;The back should look like this&lt;&#x2F;figcaption&gt;
&lt;p&gt;The other PCB should look like this&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;55661fe4-33d9-4932-8796-a600606ea7d1.jpeg&quot; alt=&quot;That’s the left hand side of the keyboard&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;That’s the left hand side of the keyboard&lt;&#x2F;figcaption&gt;
&lt;p&gt;Now it&#x27;s time for the TRRS jack and the reset button. The reset button
will help you reset your keyboard&#x27;s keymap. I used capton tape to hold
them in place. Place the components in the areas marked by the PCB. The
reset button cannot be inserted any other way. Orientation of resistors
doesn&#x27;t matter&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;70ef09b1-d800-45e2-9415-d06a8ddaf1e3.jpeg&quot; alt=&quot;On this side you can optionally solder the 2 resistors.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;On this side you can optionally solder the 2
resistors.&lt;&#x2F;figcaption&gt;
&lt;p&gt;Then do the same trick for the pins that will hold together the arduino&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;fe023c2e-1f02-4998-8e89-17d0fab70713.jpeg&quot; alt=&quot;The longer side should show here&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;The longer side should show here&lt;&#x2F;figcaption&gt;
&lt;p&gt;From another angle&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;21e442f5-39fd-4be8-a1af-2c82267e3b3c.jpeg&quot; alt=&quot;21e442f5-39fd-4be8-a1af-2c82267e3b3c.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do this on both PCB. If for any reason they are not straight or at the
wrong angle, try to insert the arduino in place. Now is the time to do
it. Feel free to try and desolder or slightly adjust the pins so that
the arduino can fit. However &lt;strong&gt;do not&lt;&#x2F;strong&gt; solder the arduino just yet.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s first time to make sure that it&#x27;s working and to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qmk&#x2F;qmk_firmware&quot;&gt;flash with
QMK&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re running linux it might be as simple as&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;git clone
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qmk&#x2F;qmk_firmware&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;qmk&#x2F;qmk_firmware&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;cd qmk_firmware&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;sudo make redox:default:avrdude&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Plug your arduino to your computer , and then short GND and RST like so.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;e4428223-16e4-4a70-9723-296c35cea4cb.jpeg&quot; alt=&quot;e4428223-16e4-4a70-9723-296c35cea4cb.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you are successful you should see something like.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;avrdude: verifying ...&lt;br &#x2F;&gt;
avrdude: 24128 bytes of flash verified&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;avrdude: safemode: Fuses OK (E:FB, H:D8, L:FF)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;avrdude done. Thank you.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Repeat the same on the other arduino as well.&lt;&#x2F;p&gt;
&lt;p&gt;Good you have working , flashed arduinos.&lt;&#x2F;p&gt;
&lt;p&gt;Now before you solder the arduino, you need to solder some switches in
place. Otherwise you won&#x27;t be able to in the future.&lt;&#x2F;p&gt;
&lt;p&gt;But before we start soldering the switches , check if the case is right.
Some 3D printed cases might have minor imperfections&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;e651f72b-7619-46e3-bcf5-77b71df11096.jpeg&quot; alt=&quot;I had to cut a couple mm off the case&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;I had to cut a couple mm off the case&lt;&#x2F;figcaption&gt;
&lt;p&gt;Now once you make sure that the TRRS jack is accessible it&#x27;s time to
mount the switches on the case and solder them&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;4e279812-bfb7-47b3-a3bd-fe4aafef672f.jpeg&quot; alt=&quot;4e279812-bfb7-47b3-a3bd-fe4aafef672f.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Make sure to mount and solder these switches! I prefer to solder a
couple of switches around the board as well.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;ab44c81c-811e-4665-91dd-d5a91dcc3f06.jpeg&quot; alt=&quot;Switches should look like this on the other side&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Switches should look like this on the
other side&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;9834ef61-7b8f-41ad-9f96-53fe7f2078e9.jpeg&quot; alt=&quot;Start with these and definitely do the ones under the arduino&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;Start with these and definitely do the ones under
the arduino&lt;&#x2F;figcaption&gt;
&lt;p&gt;Now orientation of the arduino matters as well. Make sure that the
labels in the arduino match the labels in the PCB (duh!) .&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;fcdaa17e-7ad0-4a0a-a655-7e48932e9d7f.jpeg&quot; alt=&quot;fcdaa17e-7ad0-4a0a-a655-7e48932e9d7f.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On the other PCB, the arduino will go the other way (The LEDs and the
die will be facing you)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;me.costaskou.com&#x2F;articles&#x2F;build-your-own-keyboard&#x2F;79f85941-5e72-4ea6-8003-49b1adddaee9.jpeg&quot; alt=&quot;79f85941-5e72-4ea6-8003-49b1adddaee9.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The switches should look like this on the other end.&lt;&#x2F;p&gt;
&lt;p&gt;The moment of truth has arrived. Plug your usb cable to your keyboard
and start typing with those keys that you&#x27;ve soldered. Congratulations!&lt;&#x2F;p&gt;
&lt;p&gt;Keep mounting, and soldering these switches. Finally don&#x27;t forget the
keycaps.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;There are a lot of kit keyboards out there. Admittedly I do like the
split kind because, anecdotally , they are more ergonomic and make me
hunch less.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;keeb.io&#x2F;collections&#x2F;split-keyboard-parts&quot; title=&quot;https:&#x2F;&#x2F;keeb.io&#x2F;collections&#x2F;split-keyboard-parts&quot;&gt;&lt;strong&gt;Split Keyboard Parts&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
*Parts for building split keyboards like the Nyquist, Viterbi, Levinson,
and
Iris.*keeb.io&lt;&#x2F;a&gt;&lt;a href=&quot;https:&#x2F;&#x2F;keeb.io&#x2F;collections&#x2F;split-keyboard-parts&quot;&gt;&lt;&#x2F;a&gt;{.js-mixtapeImage
.mixtapeImage .u-ignoreBlock media-id=&amp;quot;478050e1c67c59cf9dec14e6fcfaae8e&amp;quot;
thumbnail-img-id=&amp;quot;0&lt;em&gt;js7SRoQKd36Fdo5c&amp;quot;
style=&amp;quot;background-image: url(https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;fit&#x2F;c&#x2F;160&#x2F;160&#x2F;0&lt;&#x2F;em&gt;js7SRoQKd36Fdo5c);&amp;quot;}&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mechboards.co.uk&#x2F;product-category&#x2F;kits&#x2F;&quot; title=&quot;https:&#x2F;&#x2F;mechboards.co.uk&#x2F;product-category&#x2F;kits&#x2F;&quot;&gt;&lt;strong&gt;Kits Archives | MechBoardsUK&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
&lt;em&gt;Edit
description&lt;&#x2F;em&gt;mechboards.co.uk&lt;&#x2F;a&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mechboards.co.uk&#x2F;product-category&#x2F;kits&#x2F;&quot;&gt;&lt;&#x2F;a&gt;{.js-mixtapeImage
.mixtapeImage .u-ignoreBlock media-id=&amp;quot;e2edc76f9aed0c7f4566bc244041aae9&amp;quot;
thumbnail-img-id=&amp;quot;0&lt;em&gt;xJ2KH6TQSQQGXcLO&amp;quot;
style=&amp;quot;background-image: url(https:&#x2F;&#x2F;cdn-images-1.medium.com&#x2F;fit&#x2F;c&#x2F;160&#x2F;160&#x2F;0&lt;&#x2F;em&gt;xJ2KH6TQSQQGXcLO);&amp;quot;}&lt;&#x2F;p&gt;
&lt;p&gt;and of course a whole subreddit dedicated to it.
&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;MechanicalKeyboards&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;MechanicalKeyboard&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Happy typing.&lt;&#x2F;p&gt;
&lt;p&gt;By &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&quot;&gt;Costas Kourmpoglou&lt;&#x2F;a&gt;
on &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;p&#x2F;5df65cb68839&quot;&gt;November 4, 2018&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@costask&#x2F;build-your-own-keyboard-5df65cb68839&quot;&gt;Canonical
link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
