diff --git a/README.md b/README.md index 34aba3f..4030f9f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ * Подстрока * Регулярное выражение * Бинарная подстрока +* Умеет автоматически удалять стримы с определенным контентом, которые не нужно отображать * Умеет сохранять стримы в избранное и отображать только избранные стримы * Работает с несколькими сервисами на разных портах, может отображать стримы для конкретных сервисов и паттернов * Поддерживает навигацию по стримам с помощью горячих клавиш @@ -95,8 +96,8 @@ sudo docker-compose up --build -d ### Начало работы При попытке зайти в web-интерфейс впервые, браузер спросит логин и пароль, который указывался в env-файле. -После успешного входа необходимо открыть настройки кликом по шестеренкам в правом -верхнем углу, затем ввести логин и пароль API, указанный при входе. +При необходимости можно настроить дополнительные параметры по кнопке с шестеренками в верхнем +правом углу экрана. ![Скриншот настроек](screenshots/Screenshot_Settings.png) @@ -109,7 +110,9 @@ sudo docker-compose up --build -d Для удобного отлова флагов в приложении существует система паттернов. Чтобы создать паттерн, нужно открыть выпадающее меню `Patterns` и нажать кнопку `+`, -затем указать нужный тип поиска, сам паттерн, цвет подсветки в тексте и прочее. +затем указать нужный тип поиска, сам паттерн, цвет подсветки в тексте и прочее. +Если выбрать тип паттерна IGNORE, то стримы, попадающие под шаблон, автоматически будут удаляться. +Это может пригодиться, чтобы не засорять БД трафиком с эксплоитами, которые уже были запатчены. В режиме LIVE система начнет автоматически захватывать стримы и отображать их в сайдбаре. В режиме FILE для начала обработки файла нужно нажать соответствующую кнопку в сайдбаре. diff --git a/README_EN.md b/README_EN.md index 29d49ed..37e39b1 100644 --- a/README_EN.md +++ b/README_EN.md @@ -13,6 +13,7 @@ Advanced network traffic flow analyzer for A/D CTFs. * Substring * Regular expression * Binary substring +* Can automatically delete streams with content that you don't need * Can make certain streams favorite and show only favorite streams * Supports several simultaneous services, can show streams for a specific service or pattern * Allows navigating streams using shortcuts @@ -89,7 +90,7 @@ If everything went fine, Packmate will be available on port `65000` from any hos When you open a web interface for the first time, you will be asked for a login and password you specified in the env file. After entering the credentials, open the settings by clicking the cogs -in the top right corner and enter the specified login and password again. +in the top right corner and modify additional parameters. ![Settings](screenshots/Screenshot_Settings.png) @@ -103,7 +104,9 @@ then fill in the service name, port, and optimizations to perform on streams. For a simple monitoring of flags, there is a system of patterns. To create a pattern, open `Patterns` dropdown menu, press `+`, then -specify the type of pattern, the pattern itself, highlight color and other things. +specify the type of pattern, the pattern itself, highlight color and other things. +If you choose IGNORE as the type of a pattern, all matching streams will be automatically deleted. +This can be useful to filter out exploits you have already patched against. In LIVE mode the system will automatically capture streams and show them in a sidebar. In FILE mode you'll have to press appropriate button in a sidebar to start processing a file. diff --git a/frontend b/frontend index fb3637a..a8e7576 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit fb3637a8b2d49e57d85d0388fb44a2953009cf85 +Subproject commit a8e75766a1c35171fc1c0c7d3a8f16eed5c5ae6c diff --git a/screenshots/Screenshot_Settings.png b/screenshots/Screenshot_Settings.png index 5f86ce7..0773e66 100644 Binary files a/screenshots/Screenshot_Settings.png and b/screenshots/Screenshot_Settings.png differ diff --git a/src/main/java/ru/serega6531/packmate/model/FoundPattern.java b/src/main/java/ru/serega6531/packmate/model/FoundPattern.java index 1c76e9a..4d54e33 100644 --- a/src/main/java/ru/serega6531/packmate/model/FoundPattern.java +++ b/src/main/java/ru/serega6531/packmate/model/FoundPattern.java @@ -3,9 +3,7 @@ package ru.serega6531.packmate.model; import lombok.*; import org.hibernate.annotations.GenericGenerator; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import javax.persistence.*; @Entity @GenericGenerator( @@ -22,13 +20,18 @@ import javax.persistence.Id; @Builder @Getter @ToString -@EqualsAndHashCode +@EqualsAndHashCode(exclude = "packet") public class FoundPattern { @Id @GeneratedValue(generator = "found_pattern_generator") private int id; + @ManyToOne + @JoinColumn(name = "packet_id", nullable = false) + @Setter + private Packet packet; + private int patternId; private int startPosition; diff --git a/src/main/java/ru/serega6531/packmate/model/Packet.java b/src/main/java/ru/serega6531/packmate/model/Packet.java index f8fe5a2..54a52b8 100644 --- a/src/main/java/ru/serega6531/packmate/model/Packet.java +++ b/src/main/java/ru/serega6531/packmate/model/Packet.java @@ -1,9 +1,6 @@ package ru.serega6531.packmate.model; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; @@ -24,6 +21,7 @@ import java.util.Set; @AllArgsConstructor @Builder @Table(indexes = { @Index(name = "stream_id_index", columnList = "stream_id") }) +@EqualsAndHashCode(exclude = "stream") public class Packet { @Id @@ -40,7 +38,7 @@ public class Packet { @JoinColumn(name = "stream_id", nullable = false) private Stream stream; - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @OneToMany(mappedBy = "packet", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private Set matches; private long timestamp; diff --git a/src/main/java/ru/serega6531/packmate/model/Pattern.java b/src/main/java/ru/serega6531/packmate/model/Pattern.java index e417ba5..26c6fcb 100644 --- a/src/main/java/ru/serega6531/packmate/model/Pattern.java +++ b/src/main/java/ru/serega6531/packmate/model/Pattern.java @@ -3,6 +3,7 @@ package ru.serega6531.packmate.model; import lombok.Data; import lombok.ToString; import org.hibernate.annotations.GenericGenerator; +import ru.serega6531.packmate.model.enums.PatternActionType; import ru.serega6531.packmate.model.enums.PatternDirectionType; import ru.serega6531.packmate.model.enums.PatternSearchType; @@ -39,6 +40,8 @@ public class Pattern { private PatternDirectionType directionType; + private PatternActionType actionType; + @ManyToMany(mappedBy = "foundPatterns", fetch = FetchType.LAZY) private List matchedStreams; diff --git a/src/main/java/ru/serega6531/packmate/model/enums/PatternActionType.java b/src/main/java/ru/serega6531/packmate/model/enums/PatternActionType.java new file mode 100644 index 0000000..fe6b5f7 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/enums/PatternActionType.java @@ -0,0 +1,5 @@ +package ru.serega6531.packmate.model.enums; + +public enum PatternActionType { + FIND, IGNORE +} diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java index b37a933..71969b4 100644 --- a/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java +++ b/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java @@ -1,6 +1,7 @@ package ru.serega6531.packmate.model.pojo; import lombok.Data; +import ru.serega6531.packmate.model.enums.PatternActionType; import ru.serega6531.packmate.model.enums.PatternDirectionType; import ru.serega6531.packmate.model.enums.PatternSearchType; @@ -11,8 +12,9 @@ public class PatternDto { private boolean enabled; private String name; private String value; - private String color; // для вставки в css + private String color; private PatternSearchType searchType; private PatternDirectionType directionType; + private PatternActionType actionType; } diff --git a/src/main/java/ru/serega6531/packmate/service/PatternService.java b/src/main/java/ru/serega6531/packmate/service/PatternService.java index bb702e7..1da14af 100644 --- a/src/main/java/ru/serega6531/packmate/service/PatternService.java +++ b/src/main/java/ru/serega6531/packmate/service/PatternService.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.serega6531.packmate.model.FoundPattern; import ru.serega6531.packmate.model.Pattern; +import ru.serega6531.packmate.model.enums.PatternActionType; import ru.serega6531.packmate.model.enums.PatternDirectionType; import ru.serega6531.packmate.model.enums.PatternSearchType; import ru.serega6531.packmate.model.enums.SubscriptionMessageType; @@ -45,11 +46,11 @@ public class PatternService { return patterns.values(); } - public Set findMatches(byte[] bytes, boolean incoming) { + public Set findMatches(byte[] bytes, PatternDirectionType directionType, PatternActionType actionType) { final List list = patterns.values().stream() .filter(Pattern::isEnabled) - .filter(p -> p.getDirectionType() == (incoming ? PatternDirectionType.INPUT : PatternDirectionType.OUTPUT) - || p.getDirectionType() == PatternDirectionType.BOTH) + .filter(p -> p.getActionType() == actionType) + .filter(p -> p.getDirectionType() == directionType || p.getDirectionType() == PatternDirectionType.BOTH) .collect(Collectors.toList()); return new PatternMatcher(bytes, list).findMatches(); } diff --git a/src/main/java/ru/serega6531/packmate/service/StreamService.java b/src/main/java/ru/serega6531/packmate/service/StreamService.java index b59121d..7115131 100644 --- a/src/main/java/ru/serega6531/packmate/service/StreamService.java +++ b/src/main/java/ru/serega6531/packmate/service/StreamService.java @@ -11,6 +11,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import ru.serega6531.packmate.model.*; +import ru.serega6531.packmate.model.enums.PatternActionType; +import ru.serega6531.packmate.model.enums.PatternDirectionType; import ru.serega6531.packmate.model.enums.SubscriptionMessageType; import ru.serega6531.packmate.model.pojo.*; import ru.serega6531.packmate.repository.StreamRepository; @@ -99,11 +101,20 @@ public class StreamService { countingService.countStream(service.getPort(), packets.size()); packets = new StreamOptimizer(keysHolder, service, packets).optimizeStream(); - processUserAgent(packets, stream); + if (isStreamIgnored(packets)) { + log.debug("New stream is ignored"); + return false; + } + + processUserAgent(packets, stream); Stream savedStream = save(stream); - Set foundPatterns = getFoundPatterns(packets, savedStream); + for (Packet packet : packets) { + packet.setStream(savedStream); + } + + Set foundPatterns = matchPatterns(packets); savedStream.setFoundPatterns(foundPatterns); savedStream.setPackets(packets); savedStream = save(savedStream); @@ -139,13 +150,16 @@ public class StreamService { return "" + alphabet[hash % l] + alphabet[(hash / l) % l] + alphabet[(hash / (l * l)) % l]; } - private Set getFoundPatterns(List packets, Stream savedStream) { + private Set matchPatterns(List packets) { Set foundPatterns = new HashSet<>(); for (Packet packet : packets) { - packet.setStream(savedStream); - final Set matches = patternService.findMatches(packet.getContent(), packet.isIncoming()); + PatternDirectionType direction = packet.isIncoming() ? PatternDirectionType.INPUT : PatternDirectionType.OUTPUT; + final Set matches = patternService.findMatches(packet.getContent(), direction, PatternActionType.FIND); + packet.setMatches(matches); + matches.forEach(m -> m.setPacket(packet)); + foundPatterns.addAll(matches.stream() .map(FoundPattern::getPatternId) .map(patternService::find) @@ -155,6 +169,18 @@ public class StreamService { return foundPatterns; } + private boolean isStreamIgnored(List packets) { + for (Packet packet : packets) { + PatternDirectionType direction = packet.isIncoming() ? PatternDirectionType.INPUT : PatternDirectionType.OUTPUT; + final Set matches = patternService.findMatches(packet.getContent(), direction, PatternActionType.IGNORE); + if (!matches.isEmpty()) { + return true; + } + } + + return false; + } + private Stream save(Stream stream) { Stream saved; if (stream.getId() == null) {