Merge pull request 'Working challenge !' (#6) from 2-site-design-basic into main
Reviewed-on: #6
This commit is contained in:
commit
6628a594da
14
README.md
14
README.md
@ -4,11 +4,21 @@
|
|||||||
#### Difficulty : easy
|
#### Difficulty : easy
|
||||||
|
|
||||||
----
|
----
|
||||||
|
## Running the challenge.
|
||||||
|
|
||||||
|
You can run the challenge using docker.
|
||||||
|
|
||||||
|
### with Docker compose
|
||||||
|
|
||||||
|
```
|
||||||
|
cd docker
|
||||||
|
sudo docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Writeup
|
## Writeup
|
||||||
|
|
||||||
|
### Enum
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
17
config/base.sql
Normal file
17
config/base.sql
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
CREATE DATABASE IF NOT EXISTS app;
|
||||||
|
USE app;
|
||||||
|
|
||||||
|
CREATE USER 'ctf'@'%' IDENTIFIED WITH mysql_native_password BY '39gknzLD';
|
||||||
|
GRANT ALL PRIVILEGES ON app.* TO 'ctf'@'%';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
|
||||||
|
CREATE TABLE users
|
||||||
|
(
|
||||||
|
user_id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
username VARCHAR(25) NOT NULL,
|
||||||
|
pass VARCHAR(80) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- cleartext pass ? but why of course
|
||||||
|
INSERT INTO users (user_id,username,pass)
|
||||||
|
VALUES (0,'admin','X82v7>P./~vC');
|
||||||
1
config/codes.txt
Normal file
1
config/codes.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
ODQxOTU=
|
||||||
1
config/creds.txt
Normal file
1
config/creds.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
agent:1c0b76fce779f78f51be339c49445c49
|
||||||
@ -1,6 +1,9 @@
|
|||||||
FROM ubuntu:24.04
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV MYSQL_ROOT_PASSWORD=39gknzLD
|
||||||
|
ENV MYSQL_DATABASE=app
|
||||||
|
|
||||||
|
|
||||||
RUN apt update && apt upgrade -y && \
|
RUN apt update && apt upgrade -y && \
|
||||||
apt install -y \
|
apt install -y \
|
||||||
@ -11,28 +14,43 @@ RUN apt update && apt upgrade -y && \
|
|||||||
supervisor \
|
supervisor \
|
||||||
openssh-server \
|
openssh-server \
|
||||||
sudo \
|
sudo \
|
||||||
|
php-mysql\
|
||||||
cowsay \
|
cowsay \
|
||||||
|
php \
|
||||||
|
iputils-ping \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# the user players will need to have access as
|
# the user players will need to have access as
|
||||||
|
|
||||||
|
|
||||||
RUN useradd -m -s /bin/bash l33t \
|
RUN useradd -m -s /bin/bash agent \
|
||||||
&& echo "l33t:h4x0r" | chpasswd
|
&& echo "agent:secure" | chpasswd
|
||||||
|
|
||||||
# foothold user with no sudo perms. Only access to the l33t user home directory.
|
# apache2 config to change default 80 port to 8080
|
||||||
|
|
||||||
RUN useradd webmaster
|
RUN sed -i 's/^Listen 80/Listen 8080/' /etc/apache2/ports.conf
|
||||||
|
|
||||||
# apache2 config to change default 80 port to 31337
|
RUN sed -i 's/<VirtualHost \*:80>/<VirtualHost *:8080>/' /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
RUN sed -i 's/^Listen 80/Listen 31337/' /etc/apache2/ports.conf
|
# remove default apache2 index.html
|
||||||
|
|
||||||
RUN sed -i 's/<VirtualHost \*:80>/<VirtualHost *:31337>/' /etc/apache2/sites-available/000-default.conf
|
RUN rm /var/www/html/index.html
|
||||||
|
|
||||||
|
# enable php module
|
||||||
|
RUN ls /etc/apache2/mods-enabled/
|
||||||
|
RUN a2enmod php*
|
||||||
|
|
||||||
# copy the app
|
# copy the app
|
||||||
|
|
||||||
#COPY ./app/ /var/www/html/
|
COPY ./www/ /var/www/html/
|
||||||
|
|
||||||
|
# give upload permissions to the www-data user
|
||||||
|
|
||||||
|
RUN chown -R www-data:www-data /var/www/html/confidential/uploads && chmod -R 755 /var/www/html/confidential/uploads
|
||||||
|
|
||||||
|
# give permissions to access the agent user to www-data
|
||||||
|
|
||||||
|
RUN usermod -aG agent www-data && chmod 750 /home/agent
|
||||||
|
|
||||||
RUN mkdir /var/run/sshd
|
RUN mkdir /var/run/sshd
|
||||||
|
|
||||||
@ -40,14 +58,25 @@ RUN mkdir /var/run/sshd
|
|||||||
# for the privesc, cowsay allowed to be ran with sudo without password
|
# for the privesc, cowsay allowed to be ran with sudo without password
|
||||||
# https://gtfobins.github.io/gtfobins/cowsay/
|
# https://gtfobins.github.io/gtfobins/cowsay/
|
||||||
|
|
||||||
RUN printf 'l33t ALL=(ALL) NOPASSWD: /usr/games/cowsay, /usr/bin/sudo -l\n' > /etc/sudoers.d/l33t && \
|
RUN printf 'agent ALL=(ALL) NOPASSWD: /usr/games/cowsay, /usr/bin/sudo -l\n' > /etc/sudoers.d/agent && \
|
||||||
chmod 0440 /etc/sudoers.d/l33t && \
|
chmod 0440 /etc/sudoers.d/agent && \
|
||||||
visudo -cf /etc/sudoers.d/l33t
|
visudo -cf /etc/sudoers.d/agent
|
||||||
|
|
||||||
# 22 port -> ssh, 31337 port (suggestion) -> vulnerable webserver players need to find using nmap port scans
|
# copy the agent user creds and set 777 suid
|
||||||
|
|
||||||
|
COPY ./config/creds.txt /home/agent/
|
||||||
|
RUN chmod 777 /home/agent/creds.txt
|
||||||
|
|
||||||
|
# copy the secret codes and set suid
|
||||||
|
|
||||||
|
COPY ./config/codes.txt /root/
|
||||||
|
|
||||||
|
RUN chown root:root /root/codes.txt
|
||||||
|
|
||||||
|
# 22 port -> ssh, 8080 port -> webserver
|
||||||
|
|
||||||
EXPOSE 22
|
EXPOSE 22
|
||||||
EXPOSE 31337
|
EXPOSE 8080
|
||||||
|
|
||||||
# config of supervisord to have both apache2 and sshd services running
|
# config of supervisord to have both apache2 and sshd services running
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.1
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: 39gknzLD
|
||||||
|
MYSQL_DATABASE: app
|
||||||
|
volumes:
|
||||||
|
- ../config/base.sql:/docker-entrypoint-initdb.d/base.sql:ro
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
app:
|
||||||
|
hostname: srv1prod
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
container_name: "ji-ctf-dockerized"
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: 39gknzLD
|
||||||
|
MYSQL_DATABASE: app
|
||||||
|
ports:
|
||||||
|
- "22:22"
|
||||||
|
- "31337:31337"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
|
|
||||||
3
fiveserver.config.js
Normal file
3
fiveserver.config.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
php: "/usr/bin/php"
|
||||||
|
}
|
||||||
1
www/.htaccess
Normal file
1
www/.htaccess
Normal file
@ -0,0 +1 @@
|
|||||||
|
DirectoryIndex index.php
|
||||||
23
www/admin/loadnote.php
Normal file
23
www/admin/loadnote.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
$uploadsDir = __DIR__ . '/../confidential/uploads/';
|
||||||
|
|
||||||
|
if(empty($_SESSION['username'])) {
|
||||||
|
exit('Access denied.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($_POST['file'])) {
|
||||||
|
$file = basename($_POST['file']); // prevent directory traversal
|
||||||
|
$path = $uploadsDir . $file;
|
||||||
|
|
||||||
|
if(file_exists($path)) {
|
||||||
|
ob_start();
|
||||||
|
include $path; // PHP executes here
|
||||||
|
echo ob_get_clean();
|
||||||
|
} else {
|
||||||
|
echo "File not found.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "No file specified.";
|
||||||
|
}
|
||||||
|
?>
|
||||||
129
www/admin/securenotes.php
Normal file
129
www/admin/securenotes.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('display_startup_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (empty($_SESSION['username'])) {
|
||||||
|
header('Location: /index.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Directory for notes
|
||||||
|
$uploadsDir = __DIR__ . '/../confidential/uploads/';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>NFD | SECURE NOTES</title>
|
||||||
|
<link rel="stylesheet" href="/static/css/stylesheet.css">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php include '../include/nav.php' ?>
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<form id="uploadForm" method="POST" enctype="multipart/form-data">
|
||||||
|
<h1>Upload notes securely here from each operation.</h1>
|
||||||
|
<i>Notes must be in .txt</i>
|
||||||
|
<hr>
|
||||||
|
<label for="file">Note</label>
|
||||||
|
<input type="file" id="file" name="file">
|
||||||
|
<br><br>
|
||||||
|
<input type="submit" class="btn btn-primary" value="Upload!">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Status message -->
|
||||||
|
<div id="statusMessage" class="mt-2"></div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Notes container -->
|
||||||
|
<div class="note-listing d-flex flex-wrap gap-3 justify-content-center" id="notesContainer">
|
||||||
|
<?php
|
||||||
|
// Render all notes
|
||||||
|
foreach (new DirectoryIterator($uploadsDir) as $file) {
|
||||||
|
if($file->isDot() || $file->isDir()) continue;
|
||||||
|
$fileName = $file->getFilename();
|
||||||
|
if (!preg_match('/\.(txt|php)$/i', $fileName)) continue;
|
||||||
|
?>
|
||||||
|
<div class="note-card text-center p-3" style="cursor:pointer;"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#noteModal"
|
||||||
|
data-filename="<?= htmlspecialchars($fileName) ?>">
|
||||||
|
<img src="/static/img/note-icon.png" alt="Note Icon" class="note-icon mb-2">
|
||||||
|
<div class="note-title"><?= htmlspecialchars($fileName) ?></div>
|
||||||
|
</div>
|
||||||
|
<?php } ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="noteModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||||
|
<div class="modal-content bg-dark text-white">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="noteModalLabel"></h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="noteModalBody">Loading...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Execute PHP on modal open
|
||||||
|
$('#noteModal').on('show.bs.modal', function (event) {
|
||||||
|
let button = $(event.relatedTarget);
|
||||||
|
let fileName = button.data('filename');
|
||||||
|
let modal = $(this);
|
||||||
|
|
||||||
|
modal.find('.modal-title').text(fileName);
|
||||||
|
modal.find('#noteModalBody').text('Loading...');
|
||||||
|
|
||||||
|
$.post('/admin/loadnote.php', { file: fileName }, function(response){
|
||||||
|
modal.find('#noteModalBody').html(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// AJAX upload form
|
||||||
|
$('#uploadForm').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let formData = new FormData(this);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/admin/uploadnote.php',
|
||||||
|
type: 'POST',
|
||||||
|
data: formData,
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
success: function(response) {
|
||||||
|
$('#statusMessage').html(response);
|
||||||
|
|
||||||
|
// Reload notes listing
|
||||||
|
$.ajax({
|
||||||
|
url: '/admin/securenotes.php',
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function(data) {
|
||||||
|
// Extract only the notes container HTML
|
||||||
|
let notesHtml = $(data).find('#notesContainer').html();
|
||||||
|
$('#notesContainer').html(notesHtml);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$('#statusMessage').html("<div class='text-danger'>Upload failed.</div>");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
28
www/admin/uploadnote.php
Normal file
28
www/admin/uploadnote.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
$destdir = __DIR__ . '/../confidential/uploads/';
|
||||||
|
$status = '';
|
||||||
|
|
||||||
|
if (empty($_SESSION['username'])) exit('Access denied.');
|
||||||
|
|
||||||
|
if (!empty($_FILES['file'])) {
|
||||||
|
$tmpName = $_FILES['file']['tmp_name'];
|
||||||
|
$fileName = basename($_FILES['file']['name']);
|
||||||
|
|
||||||
|
if (preg_match('/\.(txt)$/i', $fileName)) {
|
||||||
|
if (is_uploaded_file($tmpName)) {
|
||||||
|
if (move_uploaded_file($tmpName, $destdir . $fileName)) {
|
||||||
|
$status = "<div class='text-success'>File uploaded!</div>";
|
||||||
|
} else {
|
||||||
|
$status = "<div class='text-danger'>An error occurred.</div>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$status = "<div class='text-danger'>An error occurred.</div>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$status = "<div class='text-danger'>Invalid file type!</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $status;
|
||||||
|
?>
|
||||||
1
www/confidential/uploads/OperationAlpha.txt
Normal file
1
www/confidential/uploads/OperationAlpha.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
foobar
|
||||||
1
www/confidential/uploads/OperationBravo.txt
Normal file
1
www/confidential/uploads/OperationBravo.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
foobar
|
||||||
1
www/confidential/uploads/OperationTourniquet.txt
Normal file
1
www/confidential/uploads/OperationTourniquet.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
foobar
|
||||||
49
www/gallery.php
Normal file
49
www/gallery.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
?>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tux gallery !</title>
|
||||||
|
<link rel="stylesheet" href="static/css/stylesheet.css">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php include 'include/nav.php'?>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<section class="info-part">
|
||||||
|
<h1>Tux gallery</h1>
|
||||||
|
<p>Tux is awesome ! So I made this extremely secure gallery app.</p>
|
||||||
|
<?php if (empty($_SESSION['username'])): ?>
|
||||||
|
You can also add tux pictures to the gallery, first <a href="login.php">login</a> and then you should be able to upload a new image of tux.
|
||||||
|
<?php else: ?>
|
||||||
|
First navigate to the <a href="admin/upload.php">upload.php</a> page and upload your tux image from there!
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
<hr>
|
||||||
|
<section class="gallery-part">
|
||||||
|
<div class="gallery">
|
||||||
|
<?php
|
||||||
|
foreach (new DirectoryIterator('static/img/gallery') as $file) {
|
||||||
|
if($file->isDot()) continue;
|
||||||
|
print '<img class="tux-img" src="/static/img/gallery/'. $file->getFilename() . '" onerror="this.onerror=null;this.src=`/static/img/fallback.png`;" data-original="/static/img/gallery/'. $file->getFilename() .'">'; // to do, is there an 'fstring' like for php ? just like in python
|
||||||
|
} // xss ? i call it a feature
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
Array.from(document.getElementsByClassName("tux-img")).forEach(img => {
|
||||||
|
img.addEventListener('click', function() {
|
||||||
|
window.open(img.dataset.original);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
18
www/include/nav.php
Normal file
18
www/include/nav.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
$username = $_SESSION['username'] ?? null;
|
||||||
|
?>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<a class="navbar-brand" href="/index.php">
|
||||||
|
<img alt="logo" class="logo" src="/static/img/logo.gif" style="height:28px; margin-right:8px;">
|
||||||
|
National Defense Force
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<?php if ($username): ?>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/admin/securenotes.php">Dashboard</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/logout.php">Disconnect</a></li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
@ -1,24 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Tux gallery !</title>
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="nav-bar">
|
|
||||||
<ol>
|
|
||||||
<li><a href="/">Tux Gallery <img alt="logo" class="icon" src="static/img/icon.jpg"></a></li>
|
|
||||||
<li><a href="#upload">Upload</a></li>
|
|
||||||
<li><a href="#view">View</a></li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
<div class="wrapper">
|
|
||||||
<div class="upload">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
63
www/index.php
Normal file
63
www/index.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<?php
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('display_startup_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
session_start();
|
||||||
|
if (!empty($_SESSION['username'])) {
|
||||||
|
header('Location: /admin/securenotes.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>NDF | LOGIN</title>
|
||||||
|
<link rel="stylesheet" href="/static/css/stylesheet.css">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="header-bar"></div>
|
||||||
|
<form id="loginForm" method="POST" action="index.php">
|
||||||
|
<h1>NDF ACCESS</h1>
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" id="username" name="username" required>
|
||||||
|
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password" required>
|
||||||
|
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
<?php
|
||||||
|
if (!empty($_POST)) {
|
||||||
|
$name = $_POST['username'];
|
||||||
|
$password = $_POST['password'];
|
||||||
|
if (empty($name)) {
|
||||||
|
echo '<div class="error-message">Username is empty.</div>';
|
||||||
|
} else {
|
||||||
|
$servername = "db";
|
||||||
|
$username = "ctf";
|
||||||
|
$password_db = "39gknzLD";
|
||||||
|
$dbname = "app";
|
||||||
|
$conn = new mysqli($servername, $username, $password_db, $dbname);
|
||||||
|
$sql = "SELECT username, pass FROM users WHERE username='$name' AND pass='$password'";
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
session_regenerate_id(true);
|
||||||
|
$_SESSION['username'] = $name;
|
||||||
|
header('Location: /admin/securenotes.php');
|
||||||
|
exit();
|
||||||
|
} else {
|
||||||
|
echo '<div class="error-message">Wrong username or password!</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
14
www/logout.php
Normal file
14
www/logout.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
$_SESSION = [];
|
||||||
|
if (ini_get("session.use_cookies")) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
setcookie(session_name(), '', time() - 42000,
|
||||||
|
$params["path"], $params["domain"],
|
||||||
|
$params["secure"], $params["httponly"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
session_destroy();
|
||||||
|
header('Location: index.php');
|
||||||
|
exit();
|
||||||
0
www/robots.txt
Normal file
0
www/robots.txt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.logo{
|
||||||
|
height:50px;
|
||||||
|
width:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-part{
|
||||||
|
margin-left:15%;
|
||||||
|
margin-right:15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginForm{
|
||||||
|
display:grid;
|
||||||
|
margin-right:30%;
|
||||||
|
margin-left:30%;
|
||||||
|
gap:5px;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100vh;
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
color: #f1f1f1;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
background: url('../../static/img/background.gif') center center / cover no-repeat;
|
||||||
|
z-index: -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.85);
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:auto;
|
||||||
|
margin-top:10%;
|
||||||
|
margin-bottom:auto;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
padding: 30px;
|
||||||
|
color:white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 20px rgba(0,0,0,0.8);
|
||||||
|
width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"], input[type="password"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
background-color: #0f0f0f;
|
||||||
|
border: 1px solid #333;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
background-color: #d32f2f;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background-color: #a12a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
background-color: #d32f2f;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
color: #ff4d4d;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-listing {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-card {
|
||||||
|
width: 120px;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,0.6);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 0 15px rgba(211, 47, 47, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-icon {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-title {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-top: 5px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BIN
www/static/img/background.gif
Normal file
BIN
www/static/img/background.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
www/static/img/fallback.png
Normal file
BIN
www/static/img/fallback.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
www/static/img/logo.gif
Normal file
BIN
www/static/img/logo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 635 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
BIN
www/static/img/note-icon.png
Normal file
BIN
www/static/img/note-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
Loading…
x
Reference in New Issue
Block a user