Skip to content

Commit

Permalink
Merge pull request #28 from CzechCyberTeam/feature-qol
Browse files Browse the repository at this point in the history
Czech QOL changes
  • Loading branch information
RickdeJager authored Nov 5, 2023
2 parents 4f955f8 + 5ca75b0 commit c812aee
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 46 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/traffic
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ TICK_START="2018-06-27T13:00+02:00"
# Tick length in ms
TICK_LENGTH=180000

# PCAP-over-IP connection
PCAP_OVER_IP=
#PCAP_OVER_IP=127.0.0.1:4242
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,4 @@ venv.bak/
workspace.xml


traffic
/traffic
7 changes: 5 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ services:
context: frontend
dockerfile: Dockerfile-frontend
image: tulip-frontend:latest
restart: unless-stopped
ports:
- "3000:3000"
depends_on:
Expand All @@ -27,8 +28,7 @@ services:
context: .
dockerfile: Dockerfile-python
image: tulip-api:latest
ports:
- "127.0.0.1:5000:5000"
restart: unless-stopped
depends_on:
- mongo
networks:
Expand All @@ -47,6 +47,7 @@ services:
context: services/go-importer
dockerfile: Dockerfile-assembler
image: tulip-assembler:latest
restart: unless-stopped
depends_on:
- mongo
networks:
Expand All @@ -57,12 +58,14 @@ services:
environment:
TULIP_MONGO: ${TULIP_MONGO}
FLAG_REGEX: ${FLAG_REGEX}
PCAP_OVER_IP: ${PCAP_OVER_IP}

enricher:
build:
context: services/go-importer
dockerfile: Dockerfile-enricher
image: tulip-enricher:latest
restart: unless-stopped
depends_on:
- mongo
networks:
Expand Down
14 changes: 9 additions & 5 deletions services/data2req.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
# Copyright ©2018 Brunello Simone
# Copyright ©2018 Alessio Marotta
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# Flower is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# Flower is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Expand All @@ -36,7 +36,11 @@ def __init__(self, raw_http_request):
self.error_code = self.error_message = None
self.parse_request()

self.headers = dict(self.headers)
try:
self.headers = dict(self.headers)
except AttributeError:
self.headers = {}

# Data
try:
self.body = raw_http_request.split(b"\r\n\r\n", 1)[1].rstrip()
Expand Down Expand Up @@ -96,7 +100,7 @@ def decode_http_request(raw_request, tokenize):

# tokenize used for automatically fill data param of request
def convert_single_http_requests(raw_request, flow, tokenize=True, use_requests_session=False):

request, data, data_param_name, headers = decode_http_request(raw_request, tokenize)
if not request.path.startswith('/'):
raise Exception('request path must start with / to be a valid HTTP request')
Expand Down Expand Up @@ -151,7 +155,7 @@ def convert_flow_to_http_requests(flow, tokenize=True, use_requests_session=True
if not request.path.startswith('/'):
raise Exception('request path must start with / to be a valid HTTP request')
request_path_repr = repr(request.path)

script += render("""
{% if use_requests_session %}
s.headers = {{headers}}
Expand Down
54 changes: 32 additions & 22 deletions services/go-importer/cmd/assembler/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,33 @@ func ParseHttpFlow(flow *db.FlowEntry) {
if flowItem.From == "c" {
// HTTP Request
req, err := http.ReadRequest(reader)
if err != nil {
if *experimental {
// Parse cookie and grab fingerprints
AddFingerprints(req.Cookies(), fingerprintsSet)
}
if err != nil || req == nil {
continue
//TODO; replace the HTTP data.
// Remember to use a `LimitReader` when implementing this to prevent
// decompressions bombs / DOS!
}

if !containsTag(flow.Tags, "http") {
flow.Tags = append(flow.Tags, "http")
}

if *experimental {
// Parse cookie and grab fingerprints
AddFingerprints(req.Cookies(), fingerprintsSet)
}

//TODO; replace the HTTP data.
// Remember to use a `LimitReader` when implementing this to prevent
// decompressions bombs / DOS!
} else if flowItem.From == "s" {
// Parse HTTP Response
res, err := http.ReadResponse(reader, nil)
if err != nil {
if err != nil || res == nil {
continue
}

if !containsTag(flow.Tags, "http") {
flow.Tags = append(flow.Tags, "http")
}

if *experimental {
// Parse cookie and grab fingerprints
AddFingerprints(res.Cookies(), fingerprintsSet)
Expand All @@ -79,20 +88,21 @@ func ParseHttpFlow(flow *db.FlowEntry) {
// Failed to fully read the body. Bail out here
continue
}

switch encoding[0] {
case "gzip":
newReader, err = handleGzip(res.Body)
break
case "br":
newReader, err = handleBrotili(res.Body)
break
case "deflate":
//TODO; verify this is correct
newReader, err = handleGzip(res.Body)
break
default:
// Skipped, unknown or identity encoding
continue
case "gzip":
newReader, err = handleGzip(res.Body)
break
case "br":
newReader, err = handleBrotili(res.Body)
break
case "deflate":
//TODO; verify this is correct
newReader, err = handleGzip(res.Body)
break
default:
// Skipped, unknown or identity encoding
continue
}

// Replace the reader to allow for in-place decompression
Expand Down
15 changes: 5 additions & 10 deletions services/go-importer/cmd/enricher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,16 @@ func main() {
}

func watchEve(eve_file string) {
stat, err := os.Stat(eve_file)
if err != nil {
log.Fatal("Failed to open the eve file with error: ", err)
}

if stat.IsDir() {
log.Fatal("eve file is not a file")
}

// Do the initial scan
log.Println("Parsing initial eve contents...")
ratchet := updateEve(eve_file, 0)

log.Println("Monitoring eve file: ", eve_file)
prevSize := stat.Size()
stat, err := os.Stat(eve_file)
prevSize := int64(0)
if err == nil {
prevSize = stat.Size()
}

for {
time.Sleep(time.Duration(*rescan_period) * time.Second)
Expand Down
13 changes: 7 additions & 6 deletions services/webservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
# Copyright ©2018 Brunello Simone
# Copyright ©2018 Alessio Marotta
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# Flower is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# Flower is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Expand All @@ -22,6 +22,7 @@
# You should have received a copy of the GNU General Public License
# along with Flower. If not, see <https://www.gnu.org/licenses/>.

import traceback
from flask import Flask, Response, send_file

from configurations import services, traffic_dir, start_date, tick_length
Expand Down Expand Up @@ -107,7 +108,7 @@ def convertToSingleRequest():
try:
converted = convert_single_http_requests(data, flow, tokenize, use_requests_session)
except Exception as ex:
return return_text_response("There was an error while converting the request:\n{}: {}".format(type(ex).__name__, ex))
return return_text_response("There was an error while converting the request:\n{}: {}".format(type(ex).__name__, traceback.format_exc()))
return return_text_response(converted)

@application.route('/to_python_request/<id>')
Expand All @@ -121,7 +122,7 @@ def convertToRequests(id):
try:
converted = convert_flow_to_http_requests(flow, tokenize, use_requests_session)
except Exception as ex:
return return_text_response("There was an error while converting the request:\n{}: {}".format(type(ex).__name__, ex))
return return_text_response("There was an error while converting the request:\n{}: {}".format(type(ex).__name__, traceback.format_exc()))
return return_text_response(converted)

@application.route('/to_pwn/<id>')
Expand All @@ -136,13 +137,13 @@ def downloadFile():
if filepath is None:
return return_text_response("There was an error while downloading the requested file:\n{}: {}".format("Invalid 'file'", "No 'file' given"))
filepath = Path(filepath)

# Check for path traversal by resolving the file first.
filepath = filepath.resolve()
if not traffic_dir in filepath.parents:
return return_text_response("There was an error while downloading the requested file:\n{}: {}".format("Invalid 'file'", "'file' was not in a subdirectory of traffic_dir"))

try:
try:
return send_file(filepath, as_attachment=True)
except FileNotFoundError:
return return_text_response("There was an error while downloading the requested file:\n{}: {}".format("Invalid 'file'", "'file' not found"))
Expand Down

0 comments on commit c812aee

Please sign in to comment.