diff --git a/.gitignore b/.gitignore
index d58c97f..447b2d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
+references_for_redisign
src/main/resources/static/*
+!src/main/resources/static/fake
+!src/main/resources/static/fake/**
*.pcap
data
diff --git a/README.md b/README.md
index 5b92747..cf72393 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
-# Packmate
+# 0xb00b5 team Packmate
### [[EN](README_EN.md) | RU]
-Утилита перехвата и анализа трафика для CTF.
+Утилита перехвата и анализа трафика для CTF, переосмысленная в пиксельном неоне.
#### Фичи:
* Поддерживает перехват живого трафика и обработку pcap файлов
@@ -23,14 +23,18 @@
* Разархивирует GZIP в HTTP на лету
* Разархивирует сжатые WebSockets
* Расшифровывает TLS на RSA при наличии приватного ключа
+* Обманка для входа `admin:admin` с режимами `fun` и `fake_packets`, чтобы любопытные так и не добрались до настоящих пакетов

+### Обманка admin:admin
+Для входа с кредами `admin:admin` добавлена обманка (включена по умолчанию). Управляется через переменные `PACKMATE_FAKE_ADMIN_ENABLED` и `PACKMATE_FAKE_ADMIN_MODE` (`fun` или `fake_packets`) и не дает добраться до настоящего интерфейса.
+
## Быстрый запуск
-Для быстрого запуска Packmate следует использовать [этот стартер](https://gitlab.com/packmate/starter/-/blob/master/README.md).
+Для быстрого запуска 0xb00b5 team Packmate следует использовать [этот стартер](https://gitlab.com/packmate/starter/-/blob/master/README.md).
## Полный запуск
-Ниже следует инструкция для тех, кто хочет собрать Packmate самостоятельно.
+Ниже следует инструкция для тех, кто хочет собрать 0xb00b5 team Packmate самостоятельно.
### Клонирование
Поскольку этот репозиторий содержит фронтенд как git submodule, его необходимо клонировать так:
@@ -56,7 +60,7 @@ git submodule update --init --recursive
sudo docker compose up --build -d
```
-При успешном запуске Packmate будет видно с любого хоста на порту `65000`.
+При успешном запуске 0xb00b5 team Packmate будет видно с любого хоста на порту `65000`.
БД будет слушать на порту 65001, но будет разрешать подключения только с localhost.
## Использование
@@ -64,5 +68,5 @@ sudo docker compose up --build -d
-*desu~*
+*@danosito*
diff --git a/README_EN.md b/README_EN.md
index 6384dde..3505f19 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -1,10 +1,10 @@
-# Packmate
+# 0xb00b5 team Packmate
### [EN | [RU](README.md)]
-Advanced network traffic flow analyzer for A/D CTFs.
+Advanced network traffic flow analyzer for A/D CTFs with a pixel-neon twist.
#### Features:
* Can monitor live traffic or analyze pcap files
@@ -23,14 +23,18 @@ Advanced network traffic flow analyzer for A/D CTFs.
* Can automatically decompress GZIPed HTTP
* Can automatically deflate WebSockets with permessages-deflate extension
* Can automatically decrypt TLS with RSA using given private key (like Wireshark)
+* Decoy login for `admin:admin` with `fun` and `fake_packets` modes so snoopers never see the real data

+### Admin:admin decoy
+The admin:admin credentials now trigger a decoy (enabled by default). Configure it via `PACKMATE_FAKE_ADMIN_ENABLED` and `PACKMATE_FAKE_ADMIN_MODE` (`fun` or `fake_packets`) to keep everyone away from the real interface.
+
## Quick Start
-To quickly start using Packmate, use [this starter](https://gitlab.com/packmate/starter/-/blob/master/README_EN.md).
+To quickly start using 0xb00b5 team Packmate, use [this starter](https://gitlab.com/packmate/starter/-/blob/master/README_EN.md).
## Full Build
-Below are the instructions for those who want to build Packmate on their own.
+Below are the instructions for those who want to build 0xb00b5 team Packmate on their own.
### Cloning
As this repository contains frontend part as a git submodule, it has to be cloned like this:
@@ -56,7 +60,7 @@ After filling in env file you can launch the app:
sudo docker-compose up --build -d
```
-If everything went fine, Packmate will be available on port `65000` from any host.
+If everything went fine, 0xb00b5 team Packmate will be available on port `65000` from any host.
Database with listen on port 65001, but will only accept connections from localhost.
## Usage
diff --git a/docker-compose.yml b/docker-compose.yml
index cb42a90..ce7b484 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -8,6 +8,8 @@ services:
PCAP_FILE: ${PACKMATE_PCAP_FILE:-}
WEB_LOGIN: ${PACKMATE_WEB_LOGIN:-BinaryBears}
WEB_PASSWORD: ${PACKMATE_WEB_PASSWORD:-123456}
+ FAKE_ADMIN_AUTH_ENABLED: ${PACKMATE_FAKE_ADMIN_ENABLED:-true}
+ FAKE_ADMIN_MODE: ${PACKMATE_FAKE_ADMIN_MODE:-fun}
OLD_STREAMS_CLEANUP_ENABLED: ${PACKMATE_OLD_STREAMS_CLEANUP_ENABLED:-false}
OLD_STREAMS_CLEANUP_INTERVAL: ${PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL:-5}
OLD_STREAMS_CLEANUP_THRESHOLD: ${PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD:-240}
@@ -43,4 +45,4 @@ services:
test: [ "CMD-SHELL", "pg_isready -U packmate -p 65001" ]
interval: 2s
timeout: 5s
- retries: 15
\ No newline at end of file
+ retries: 15
diff --git a/docker/Dockerfile_app b/docker/Dockerfile_app
index e35243e..dcf2c97 100644
--- a/docker/Dockerfile_app
+++ b/docker/Dockerfile_app
@@ -20,10 +20,12 @@ CMD [ "java", "-Djava.net.preferIPv4Stack=true", "-Djava.net.preferIPv4Addresses
"--packmate.capture-mode=${MODE}", "--packmate.pcap-file=${PCAP_FILE}", \
"--packmate.interface-name=${INTERFACE}", "--packmate.local-ip=${LOCAL_IP}", \
"--packmate.web.account-login=${WEB_LOGIN}", "--packmate.web.account-password=${WEB_PASSWORD}", \
+ "--packmate.web.fake-admin.enabled=${FAKE_ADMIN_AUTH_ENABLED}", \
+ "--packmate.web.fake-admin.mode=${FAKE_ADMIN_MODE}", \
"--packmate.cleanup.enabled=${OLD_STREAMS_CLEANUP_ENABLED}", \
"--packmate.cleanup.interval=${OLD_STREAMS_CLEANUP_INTERVAL}", \
"--packmate.cleanup.threshold=${OLD_STREAMS_CLEANUP_THRESHOLD}", \
"--server.port=65000", "--server.address=0.0.0.0" \
]
-EXPOSE 65000
\ No newline at end of file
+EXPOSE 65000
diff --git a/docs/SETUP.md b/docs/SETUP.md
index d7c67ff..93c59e2 100644
--- a/docs/SETUP.md
+++ b/docs/SETUP.md
@@ -1,6 +1,6 @@
## Настройка
-Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
+0xb00b5 team Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
### Основные настройки
```dotenv
@@ -10,13 +10,17 @@ PACKMATE_LOCAL_IP=10.20.1.1
PACKMATE_WEB_LOGIN=SomeUser
# Пароль для web-авторизации
PACKMATE_WEB_PASSWORD=SomeSecurePassword
+# Включает обманку при вводе admin:admin
+PACKMATE_FAKE_ADMIN_ENABLED=true
+# fun или fake_packets - варианты обманки
+PACKMATE_FAKE_ADMIN_MODE=fun
```
### Режим работы
-Packmate поддерживает три основных режима работы: `LIVE`, `FILE` и `VIEW`.
-1. `LIVE` - это основной режим работы во время CTF. Packmate обрабатывает живой трафик и сразу выводит результаты.
-2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен Packmate, или тех, где невозможно запустить его на вулнбоксе.
-3. `VIEW` - Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
+0xb00b5 team Packmate поддерживает три основных режима работы: `LIVE`, `FILE` и `VIEW`.
+1. `LIVE` - это основной режим работы во время CTF. 0xb00b5 team Packmate обрабатывает живой трафик и сразу выводит результаты.
+2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен 0xb00b5 team Packmate, или тех, где невозможно запустить его на вулнбоксе.
+3. `VIEW` - 0xb00b5 team Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
Настройка LIVE
@@ -62,7 +66,7 @@ PACKMATE_MODE=VIEW
### Очистка БД
-На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу Packmate и занимает много места на диске.
+На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу 0xb00b5 team Packmate и занимает много места на диске.
Для оптимизации работы, рекомендуется включить регулярную очистку БД от старых стримов. Это будет работать только в режиме `LIVE`.
```dotenv
@@ -79,11 +83,11 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
```dotenv
# Пароль от БД. Из-за того, что БД принимает подключения только с localhost, менять его необязательно, но можно, для дополнительной безопасности.
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
-# Версия Packmate. Можно изменить, если нужно использовать другой образ из docker registry.
+# Версия 0xb00b5 team Packmate. Можно изменить, если нужно использовать другой образ из docker registry.
BUILD_TAG=latest
```
Чтобы использовать расшифровку TLS (с RSA), нужно положить соответствующий приватный ключ, который
использовался для генерации сертификата, в папку `rsa_keys`.
-Файлы БД сохраняются в ./data, поэтому для обнуления базы нужно удалить эту папку.
\ No newline at end of file
+Файлы БД сохраняются в ./data, поэтому для обнуления базы нужно удалить эту папку.
diff --git a/docs/SETUP_EN.md b/docs/SETUP_EN.md
index 6b12da6..ad5f48c 100644
--- a/docs/SETUP_EN.md
+++ b/docs/SETUP_EN.md
@@ -1,6 +1,6 @@
## Setup
-Packmate uses properties from the `.env` file (in the same directory as `docker-compose.yml`)
+0xb00b5 team Packmate uses properties from the `.env` file (in the same directory as `docker-compose.yml`)
### Primary settings
```dotenv
@@ -10,13 +10,17 @@ PACKMATE_LOCAL_IP=10.20.1.1
PACKMATE_WEB_LOGIN=SomeUser
# Password for the web interface
PACKMATE_WEB_PASSWORD=SomeSecurePassword
+# Enable decoy flow for admin:admin login
+PACKMATE_FAKE_ADMIN_ENABLED=true
+# fun or fake_packets - pick the decoy flavor
+PACKMATE_FAKE_ADMIN_MODE=fun
```
### Modes of operation
-Packmate supports 3 modes of operation: `LIVE`, `FILE` и `VIEW`.
-1. `LIVE` - the usual mode during a CTF. Packmate processes live traffic and instantly displays the results.
-2. `FILE` - processes traffic from pcap files. Useful to analyze traffic from past CTFs where Packmate wasn't launched, or CTFs where it's impossible to use it on the vulnbox.
-3. `VIEW` - Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
+0xb00b5 team Packmate supports 3 modes of operation: `LIVE`, `FILE` и `VIEW`.
+1. `LIVE` - the usual mode during a CTF. 0xb00b5 team Packmate processes live traffic and instantly displays the results.
+2. `FILE` - processes traffic from pcap files. Useful to analyze traffic from past CTFs where 0xb00b5 team Packmate wasn't launched, or CTFs where it's impossible to use it on the vulnbox.
+3. `VIEW` - 0xb00b5 team Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
LIVE setup
@@ -62,7 +66,7 @@ PACKMATE_MODE=VIEW
### Database cleanup
-On large CTFsб after some time a lot of traffic will pile up. This can slow Packmate down and take a lot of drive space.
+On large CTFsб after some time a lot of traffic will pile up. This can slow 0xb00b5 team Packmate down and take a lot of drive space.
To optimize the workflow, it is recommended to enable periodical database cleanup of old streams. It will only work in the `LIVE` mode.
```dotenv
@@ -79,10 +83,10 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
```dotenv
# Database password. Considering it only listens on localhost, it's not mandatory to change it, but you can do it for additional security.
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
-# Packmate version. Change it if you want to use a different version from the docker registry.
+# 0xb00b5 team Packmate version. Change it if you want to use a different version from the docker registry.
BUILD_TAG=latest
```
To use the TLS decryption, you have to put the matching private key in the `rsa_keys` directory.
-Database files are being saved in `./data`, so to reset the database, you need to delete this directory.
\ No newline at end of file
+Database files are being saved in `./data`, so to reset the database, you need to delete this directory.
diff --git a/frontend b/frontend
index 8f23d97..f90217c 160000
--- a/frontend
+++ b/frontend
@@ -1 +1 @@
-Subproject commit 8f23d97100f11cd6671bb62aca5ce9b6a898b865
+Subproject commit f90217cd6cb03dfafcec6476d4f862784b4a8184
diff --git a/src/main/java/ru/serega6531/packmate/configuration/SecurityConfiguration.java b/src/main/java/ru/serega6531/packmate/configuration/SecurityConfiguration.java
index f24f32d..f200e90 100644
--- a/src/main/java/ru/serega6531/packmate/configuration/SecurityConfiguration.java
+++ b/src/main/java/ru/serega6531/packmate/configuration/SecurityConfiguration.java
@@ -7,13 +7,20 @@ import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import ru.serega6531.packmate.properties.PackmateProperties;
+import ru.serega6531.packmate.security.FakeAdminAuthFilter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
@Configuration
@EnableWebSecurity
@@ -22,31 +29,46 @@ public class SecurityConfiguration {
@Bean
public InMemoryUserDetailsManager userDetailsService(PackmateProperties properties, PasswordEncoder passwordEncoder) {
- UserDetails user = User.builder()
+ List users = new ArrayList<>();
+
+ users.add(User.builder()
.username(properties.web().accountLogin())
.password(passwordEncoder.encode(properties.web().accountPassword()))
.roles("USER")
- .build();
+ .build());
- return new InMemoryUserDetailsManager(user);
+ Optional.ofNullable(properties.web().fakeAdmin())
+ .filter(PackmateProperties.FakeAdminProperties::enabled)
+ .ifPresent(fakeAdmin -> users.add(User.builder()
+ .username("admin")
+ .password(passwordEncoder.encode("admin"))
+ .roles("FAKE")
+ .build()));
+
+ return new InMemoryUserDetailsManager(users);
}
@Bean
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ public SecurityFilterChain filterChain(HttpSecurity http, FakeAdminAuthFilter fakeAdminAuthFilter) throws Exception {
return http.csrf()
.disable()
.authorizeHttpRequests((auth) ->
- auth.requestMatchers("/site.webmanifest")
+ auth.requestMatchers("/site.webmanifest", "/fake-admin/**", "/fake/**", "/api/fake/**")
.permitAll()
+ .requestMatchers("/api/**", "/ws/**")
+ .hasRole("USER")
.anyRequest()
.authenticated()
)
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
.httpBasic()
.and()
.headers()
.frameOptions()
.sameOrigin()
.and()
+ .addFilterAfter(fakeAdminAuthFilter, BasicAuthenticationFilter.class)
.build();
}
diff --git a/src/main/java/ru/serega6531/packmate/controller/FakeAdminController.java b/src/main/java/ru/serega6531/packmate/controller/FakeAdminController.java
new file mode 100644
index 0000000..c4b8861
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/controller/FakeAdminController.java
@@ -0,0 +1,27 @@
+package ru.serega6531.packmate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.serega6531.packmate.security.FakeAdminResponder;
+
+@RestController
+@RequestMapping("/fake-admin")
+@RequiredArgsConstructor
+public class FakeAdminController {
+
+ private final FakeAdminResponder responder;
+
+ @GetMapping(value = "/fun", produces = MediaType.TEXT_HTML_VALUE)
+ public ResponseEntity fun() {
+ return ResponseEntity.ok(responder.funPageHtml());
+ }
+
+ @GetMapping(value = "/fakePackets", produces = MediaType.TEXT_HTML_VALUE)
+ public ResponseEntity fakePackets() {
+ return ResponseEntity.ok(responder.fakePacketsHtml());
+ }
+}
diff --git a/src/main/java/ru/serega6531/packmate/controller/FakeFacadeController.java b/src/main/java/ru/serega6531/packmate/controller/FakeFacadeController.java
new file mode 100644
index 0000000..5d66262
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/controller/FakeFacadeController.java
@@ -0,0 +1,23 @@
+package ru.serega6531.packmate.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.serega6531.packmate.model.pojo.FakeServiceDto;
+import ru.serega6531.packmate.service.ServicesService;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/fake/")
+@RequiredArgsConstructor
+public class FakeFacadeController {
+
+ private final ServicesService servicesService;
+
+ @GetMapping("services")
+ public List getServices() {
+ return servicesService.findAllForFakeFacade();
+ }
+}
diff --git a/src/main/java/ru/serega6531/packmate/model/enums/FakeAdminMode.java b/src/main/java/ru/serega6531/packmate/model/enums/FakeAdminMode.java
new file mode 100644
index 0000000..e84d388
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/model/enums/FakeAdminMode.java
@@ -0,0 +1,6 @@
+package ru.serega6531.packmate.model.enums;
+
+public enum FakeAdminMode {
+ FUN,
+ FAKE_PACKETS
+}
diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/FakeServiceDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/FakeServiceDto.java
new file mode 100644
index 0000000..7ab4f7d
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/model/pojo/FakeServiceDto.java
@@ -0,0 +1,12 @@
+package ru.serega6531.packmate.model.pojo;
+
+import lombok.Builder;
+import lombok.Value;
+
+@Value
+@Builder
+public class FakeServiceDto {
+ int port;
+ String name;
+ String packetKind;
+}
diff --git a/src/main/java/ru/serega6531/packmate/properties/PackmateProperties.java b/src/main/java/ru/serega6531/packmate/properties/PackmateProperties.java
index 90fafc9..27ca9d3 100644
--- a/src/main/java/ru/serega6531/packmate/properties/PackmateProperties.java
+++ b/src/main/java/ru/serega6531/packmate/properties/PackmateProperties.java
@@ -3,6 +3,7 @@ package ru.serega6531.packmate.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import ru.serega6531.packmate.model.enums.CaptureMode;
+import ru.serega6531.packmate.model.enums.FakeAdminMode;
import java.net.InetAddress;
@@ -20,7 +21,13 @@ public record PackmateProperties(
public record WebProperties(
String accountLogin,
- String accountPassword
+ String accountPassword,
+ FakeAdminProperties fakeAdmin
+ ) {}
+
+ public record FakeAdminProperties(
+ boolean enabled,
+ FakeAdminMode mode
) {}
public record TimeoutProperties(
diff --git a/src/main/java/ru/serega6531/packmate/security/FakeAdminAuthFilter.java b/src/main/java/ru/serega6531/packmate/security/FakeAdminAuthFilter.java
new file mode 100644
index 0000000..0f1a02a
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/security/FakeAdminAuthFilter.java
@@ -0,0 +1,77 @@
+package ru.serega6531.packmate.security;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import ru.serega6531.packmate.model.enums.FakeAdminMode;
+import ru.serega6531.packmate.properties.PackmateProperties;
+
+import java.io.IOException;
+import java.util.Optional;
+
+@Slf4j
+@RequiredArgsConstructor
+@Component
+public class FakeAdminAuthFilter extends OncePerRequestFilter {
+
+ private final PackmateProperties properties;
+
+ @Override
+ protected boolean shouldNotFilter(HttpServletRequest request) {
+ if (!isFakeEnabled()) {
+ return true;
+ }
+
+ String path = request.getRequestURI();
+ return path.startsWith("/fake-admin")
+ || path.startsWith("/api/fake")
+ || path.startsWith("/fake/")
+ || path.equals("/favicon.ico");
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+ if (!isFakeEnabled()) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ boolean isFakeAdmin = authentication != null && authentication.isAuthenticated()
+ && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_FAKE"));
+
+ if (isFakeAdmin) {
+ FakeAdminMode mode = Optional.ofNullable(properties.web().fakeAdmin())
+ .map(PackmateProperties.FakeAdminProperties::mode)
+ .orElse(FakeAdminMode.FUN);
+ String target = "/fake-admin/" + resolvePath(mode);
+ log.info("Redirecting fake admin to {}", target);
+ response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
+ response.setHeader(HttpHeaders.LOCATION, target);
+ return;
+ }
+
+ filterChain.doFilter(request, response);
+ }
+
+ private boolean isFakeEnabled() {
+ return Optional.ofNullable(properties.web().fakeAdmin())
+ .map(PackmateProperties.FakeAdminProperties::enabled)
+ .orElse(false);
+ }
+
+ private String resolvePath(FakeAdminMode mode) {
+ return switch (mode) {
+ case FAKE_PACKETS -> "fakePackets";
+ case FUN -> "fun";
+ };
+ }
+}
diff --git a/src/main/java/ru/serega6531/packmate/security/FakeAdminResponder.java b/src/main/java/ru/serega6531/packmate/security/FakeAdminResponder.java
new file mode 100644
index 0000000..43b9512
--- /dev/null
+++ b/src/main/java/ru/serega6531/packmate/security/FakeAdminResponder.java
@@ -0,0 +1,469 @@
+package ru.serega6531.packmate.security;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StreamUtils;
+
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Component
+public class FakeAdminResponder {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final List encodedImages;
+
+ public FakeAdminResponder() {
+ this.encodedImages = loadImages();
+ }
+
+ private List loadImages() {
+ try {
+ Resource[] resources = new PathMatchingResourcePatternResolver()
+ .getResources("classpath:/static/fake/images/*");
+
+ List images = Arrays.stream(resources)
+ .map(resource -> {
+ try {
+ String contentType = URLConnection.guessContentTypeFromName(resource.getFilename());
+ if (contentType == null) {
+ contentType = "image/jpeg";
+ }
+ byte[] raw = StreamUtils.copyToByteArray(resource.getInputStream());
+ return "data:%s;base64,%s".formatted(
+ contentType,
+ Base64.getEncoder().encodeToString(raw));
+ } catch (IOException e) {
+ log.warn("Failed to load fake admin image {}", resource.getFilename(), e);
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .toList();
+
+ if (images.isEmpty()) {
+ log.warn("No images found for fake admin fun mode");
+ }
+
+ return images;
+ } catch (IOException e) {
+ log.warn("Failed to load fake admin images", e);
+ return Collections.emptyList();
+ }
+ }
+
+ public String funPageHtml() {
+ String phrases = toJson(getFunPhrases());
+ String images = toJson(encodedImages);
+ return """
+
+
+
+
+ 0xb00b5 team Packmate // fake funwall
+
+
+
+
+
+
0xb00b5 team Packmate | admin:admin illusion
+
mode: FUN // @danosito
+
+
+
+
+
+
+
+
+
+ """.formatted(phrases, images);
+ }
+
+ public String fakePacketsHtml() {
+ return """
+
+
+
+
+ 0xb00b5 team Packmate // fake packets
+
+
+
+ 0xb00b5 team Packmate // decoy panel
+
+
+
+ You're stupid:)
+
+
+
+ """;
+ }
+
+ private List getFunPhrases() {
+ return List.of(
+ "Here's the flag. Are you ready? here it goes... Wait, no.",
+ "Wanna see the flag? send yours to @danosito:)",
+ "Hey, why are you here? go pentest our services",
+ "Hmmm i think might work..",
+ "Bip, boop, here was packet but codex ate it",
+ "Our LLM tockens ran out. Maybe you could give us some:)?",
+ ":(){ :|:& };:",
+ "i think creds are admin:admin but i'm not sure...",
+ "Try eternalBlue, i think it would work",
+ "I think i defended this page well enough, here is flag: LLMDELETEDTHEFLAG=",
+ "Go open ida pro and reverse this text",
+ "I would give you our flags for free, but you are a bad person:(",
+ "b00b5 is not a fresh meat:(",
+ "marcus, send your packmate credits pls",
+ "Marcus, fuck off",
+ "Your special guide to get flag!"
+ );
+ }
+
+ private String toJson(List data) {
+ try {
+ return mapper.writeValueAsString(data);
+ } catch (JsonProcessingException e) {
+ log.warn("Failed to convert data to json for fake admin", e);
+ return "[]";
+ }
+ }
+}
diff --git a/src/main/java/ru/serega6531/packmate/service/ServicesService.java b/src/main/java/ru/serega6531/packmate/service/ServicesService.java
index 2fb7358..a643f2e 100644
--- a/src/main/java/ru/serega6531/packmate/service/ServicesService.java
+++ b/src/main/java/ru/serega6531/packmate/service/ServicesService.java
@@ -14,6 +14,7 @@ import ru.serega6531.packmate.model.pojo.ServiceCreateDto;
import ru.serega6531.packmate.model.pojo.ServiceDto;
import ru.serega6531.packmate.model.pojo.ServiceUpdateDto;
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
+import ru.serega6531.packmate.model.pojo.FakeServiceDto;
import ru.serega6531.packmate.repository.ServiceRepository;
import java.net.InetAddress;
@@ -79,6 +80,17 @@ public class ServicesService {
.toList();
}
+ public List findAllForFakeFacade() {
+ return services.values()
+ .stream()
+ .map(s -> FakeServiceDto.builder()
+ .port(s.getPort())
+ .name(s.getName())
+ .packetKind(s.isHttp() || s.isParseWebSockets() ? "tcp/http" : "tcp")
+ .build())
+ .toList();
+ }
+
public void deleteByPort(int port) {
log.info("Removed service at port {}", port);
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 274a3a3..45d7f12 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -27,6 +27,9 @@ packmate:
web:
account-login: BinaryBears
account-password: 123456
+ fake-admin:
+ enabled: true
+ mode: fun # fun, fake_packets
timeout:
udp-stream-timeout: 20 # seconds
tcp-stream-timeout: 40 # seconds
@@ -35,4 +38,4 @@ packmate:
enabled: true
threshold: 240 # minutes
interval: 5 # minutes
- ignore-empty-packets: true
\ No newline at end of file
+ ignore-empty-packets: true
diff --git a/src/main/resources/static/fake/images/adminAdminMeme.jpg b/src/main/resources/static/fake/images/adminAdminMeme.jpg
new file mode 100644
index 0000000..944615b
Binary files /dev/null and b/src/main/resources/static/fake/images/adminAdminMeme.jpg differ
diff --git a/src/main/resources/static/fake/images/anotherAdminAdminMeme.jpg b/src/main/resources/static/fake/images/anotherAdminAdminMeme.jpg
new file mode 100644
index 0000000..a9ce107
Binary files /dev/null and b/src/main/resources/static/fake/images/anotherAdminAdminMeme.jpg differ
diff --git a/src/main/resources/static/fake/images/pudge.jpg b/src/main/resources/static/fake/images/pudge.jpg
new file mode 100644
index 0000000..565bbcc
Binary files /dev/null and b/src/main/resources/static/fake/images/pudge.jpg differ
diff --git a/src/main/resources/static/fake/images/sorokin.jpg b/src/main/resources/static/fake/images/sorokin.jpg
new file mode 100644
index 0000000..86af6b8
Binary files /dev/null and b/src/main/resources/static/fake/images/sorokin.jpg differ
diff --git a/src/main/resources/static/fake/images/typicalInfosec.jpg b/src/main/resources/static/fake/images/typicalInfosec.jpg
new file mode 100644
index 0000000..affd133
Binary files /dev/null and b/src/main/resources/static/fake/images/typicalInfosec.jpg differ