l1ackers

~/apparatus/the-known-entry.md

The known entry

These pages are props, not lessons. No tier, no order, and no exercise of their own. A lesson that names this page owes you the means, and this page pays.

The law travels with the props. Everything here runs against a machine you own, built to be broken, on a network that touches nothing real. If your lab note from lesson 031 is not written yet, that sentence is the appointment you are late for.

The box, stood up

The one command shape, on any machine with Docker:

$ docker run -d --rm --name dvwa -p 127.0.0.1:4280:80 vulnerables/web-dvwa

What each piece buys you. The -d runs it in the background. The --rm means the box forgets everything when it stops, which is what a practice target should do. The -p 127.0.0.1:4280:80 publishes the web port to your own loopback only, so the broken box is reachable from your machine and from nowhere else. The --name dvwa is not decoration: every later command on this page reaches inside the container by that name, and without it the container gets a random name and they all fail with No such container.

If your lab is the two virtual machines from lesson 031 instead, the box is the same idea without Docker. Use Metasploitable 2 the way that lesson described. The two shapes differ in exactly two kinds of line, so here is the whole translation once:

  • The web root. The Docker shape serves /var/www/html; the Metasploitable shape keeps the same files under /var/www/dvwa.
  • The way in. The Docker shape prefixes a command with docker exec dvwa to run it inside the container; on the Metasploitable shape you are already in the guest, and the prefix simply goes away.

Every command below is printed in the Docker shape. On the VM shape, strip the prefix and trade the root. Nothing else changes.

Success looks like an answer, any answer. Check it the way you check any web port:

$ curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://127.0.0.1:4280/
302 -> http://127.0.0.1:4280/login.php

A redirect to a login page is the box saying it is alive and guarded. That is the state every later step starts from.

The database, created

A fresh DVWA has no database, and it will not let you in until one exists. Point a browser at http://127.0.0.1:4280/setup.php and click the button that says Create / Reset Database. The page that comes back confirms creation and sends you to the login.

The button is a form post, and the form carries the same CSRF toll the login form does. The browser pays it without mentioning it. A scripted POST without the token gets the same cheerful redirect back to setup.php and creates nothing, and the box explains none of this: your next login attempt, credentials correct, token correct, bounces you to setup.php with no error at all. If you script this step, fetch the page, take user_token out of the form, and send it back with create_db. That is not a workaround. It is the second lesson this box teaches about what a browser does silently, one toll earlier than the first.

The default way in

The credentials the box ships with, because a deliberately vulnerable box is not trying to keep you out:

  • user admin
  • password password

The login form carries a CSRF token, so a raw POST with just the credentials is refused with CSRF token is incorrect, and a session that has not visited the login page first has no token to send. The browser pays this toll for you without mentioning it. If you script the login, you must fetch the page, take the token out of the form, and send it back with the credentials. Same toll, second booth.

After login the security cookie chooses the difficulty. low is the honest setting for the attack loop, and a fresh box defaults to it. In the browser the button lives on DVWA Security in the menu, and the same thing can be said with a cookie on the command line:

$ curl -s -b "PHPSESSID=your-sid;security=low" http://127.0.0.1:4280/vulnerabilities/xss_r/?name=test

Where the source lives

Every exercise in the tier that says find its line in the source starts here:

$ docker exec dvwa grep -rn '$_GET' /var/www/html/vulnerabilities | head

The docker exec is the door into the container's filesystem. /var/www/html is the web root this image serves. The source directory beside each exercise holds the same page at four difficulties, low.php, medium.php, high.php, impossible.php, and reading low.php next to impossible.php is seeing the bug and its fix in one glance. The impossible file is not there to be attacked. It is the answer key the box ships with.

One worked entry, end to end

The first flaw, the one lesson 033 walks, in four receipts. With a browser, paste <script>alert(1)</script> into the name field of vulnerabilities/xss_r.

The page greets you with your own script as your name, which is reflection. The same visit from the command line:

$ curl -s -b "PHPSESSID=your-sid;security=low" "http://127.0.0.1:4280/vulnerabilities/xss_r/?name=<script>alert(1)</script>" | grep script
<pre>Hello <script>alert(1)</script></pre>

No URL-encoding needed; leave the payload literal. The line that made it possible, in the container:

$ docker exec dvwa grep -n 'Hello' /var/www/html/vulnerabilities/xss_r/source/low.php
8:      $html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';

Line eight. The page concatenates the request straight into the HTML it sends back. The fix the answer key ships is one call, htmlspecialchars, wrapped around exactly that input, and you can read the key yourself:

$ docker exec dvwa grep -n 'htmlspecialchars' /var/www/html/vulnerabilities/xss_r/source/impossible.php
9:      $name = htmlspecialchars( $_GET[ 'name' ] );

Make that edit yourself in low.php, ask for the same page with the same script, and the greeting now reads as the literal string. The attack that worked a minute ago returns escaped characters, and nothing runs. That is a fix holding, and you watched it.

The five times

Lesson 033 asks for five flaws. The box has them. The walk above is the shape of each pass, and the other flaws live behind the same menu: SQL injection in sqli, command execution in exec, file upload in upload, and the reflected page's stored sibling in xss_s. Same loop, new line, new one call fix. The box forgets your fixes when the container stops, so breaking it again is one docker run away.

l1ackers · shell this is a way in, not a requirement
$