Compare commits
10 Commits
9ba2db7aa1
...
730cc5703b
| Author | SHA1 | Date |
|---|---|---|
|
|
730cc5703b | |
|
|
86d96c93ea | |
|
|
c6ee558407 | |
|
|
8933d72f95 | |
|
|
11c68e8155 | |
|
|
dc3ddfb925 | |
|
|
5b65798b60 | |
|
|
db033367fb | |
|
|
63a836b995 | |
|
|
ee0e95cfd0 |
|
|
@ -2,6 +2,32 @@
|
||||||
|
|
||||||
domain=hackhpi23.timo.one
|
domain=hackhpi23.timo.one
|
||||||
|
|
||||||
curl -L https://${domain}/api/red -X POST -H "Content-Type: application/json" -d "{\"data\": \"Start of post-exploitation\", \"timestamp\": \"$(date +%s)\"}"
|
if [ -n "${1}" ]; then
|
||||||
|
domain="${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
curl -L https://${domain}/api/blue -X POST -H "Content-Type: application/json" -d "{\"data\": \"<b style='color: yellow'>Snort: Intrusion Detected! Blue team should now be aware</b>\", \"timestamp\": \"$(date +%s)\"}"
|
curl -sL https://${domain}/api/red -X POST -H "Content-Type: application/json" -d "{\"data\": \"start of attack\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep .5
|
||||||
|
|
||||||
|
curl -sL https://${domain}/api/red -X POST -H "Content-Type: application/json" -d "{\"data\": \"nmap scanning\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
curl -L https://${domain}/api/blue -X POST -H "Content-Type: application/json" -d "{\"data\": \"<b style='color: yellow'>IDS: Malicious Activity was detected</b>\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep .5
|
||||||
|
|
||||||
|
curl -L https://${domain}/api/blue -X POST -H "Content-Type: application/json" -d "{\"data\": \"<b style='color: red'>Malicious IP: 141.89.221.182</b>\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep .5
|
||||||
|
|
||||||
|
curl -sL https://${domain}/api/red -X POST -H "Content-Type: application/json" -d "{\"data\": \"ssh bruteforce\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
curl -sL https://${domain}/api/red -X POST -H "Content-Type: application/json" -d "{\"data\": \"lateral scanning\", \"timestamp\": \"$(date +%s)\"}"
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
curl -sL https://${domain}/api/blue -X POST -H "Content-Type: application/json" -d "{\"data\": \"ubuntu@192.168.0.17: ssh -p1337 -A -L80:localhost:8080 mainframe3.localdomain\", \"timestamp\": \"$(( $(date +%s) + 360 ))\"}"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
[]
|
[{"data": "<b style='color: yellow'>IDS: Malicious Activity was detected</b>", "timestamp": "1681466116"}, {"data": "<b style='color: red'>Malicious IP: 141.89.221.182</b>", "timestamp": "1681466116"}, {"data": "ubuntu@192.168.0.17: ssh -p1337 -A -L80:localhost:8080 mainframe3.localdomain", "timestamp": "1681466482"}]
|
||||||
|
|
@ -1 +1 @@
|
||||||
[]
|
[{"data": "141.89.221.182: start of attack", "timestamp": "1681466111"}, {"data": "141.89.221.182: nmap scanning", "timestamp": "1681466115"}, {"data": "141.89.221.182: ssh bruteforce", "timestamp": "1681466117"}, {"data": "141.89.221.182: lateral scanning", "timestamp": "1681466119"}]
|
||||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
||||||
|
1681466111
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
True
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1681466098
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os, datetime, requests, random, json, time, string
|
import os, datetime, requests, random, json, time, string, re
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from flask import Flask, request, render_template, redirect, send_file, url_for, jsonify, session, flash, after_this_request
|
from flask import Flask, request, render_template, redirect, send_file, url_for, jsonify, session, flash, after_this_request
|
||||||
|
|
@ -8,6 +8,7 @@ from flask_login import current_user, login_user, LoginManager, UserMixin, login
|
||||||
from flask_mobility import Mobility
|
from flask_mobility import Mobility
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
from flask_ipban import IpBan
|
from flask_ipban import IpBan
|
||||||
|
from fpdf import FPDF
|
||||||
from device_detector import DeviceDetector
|
from device_detector import DeviceDetector
|
||||||
from flask_sslify import SSLify
|
from flask_sslify import SSLify
|
||||||
from requests_oauthlib import OAuth2Session
|
from requests_oauthlib import OAuth2Session
|
||||||
|
|
@ -245,7 +246,6 @@ def cpdashy_startsim():
|
||||||
f.write(str(int(time.time())))
|
f.write(str(int(time.time())))
|
||||||
with open('./database/temp/sim_running.txt', 'w') as f:
|
with open('./database/temp/sim_running.txt', 'w') as f:
|
||||||
f.write('True')
|
f.write('True')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
clear_session_full()
|
clear_session_full()
|
||||||
with open('./database/temp/sim_start.txt', 'w') as f:
|
with open('./database/temp/sim_start.txt', 'w') as f:
|
||||||
|
|
@ -256,6 +256,110 @@ def cpdashy_startsim():
|
||||||
else:
|
else:
|
||||||
return redirect('/login')
|
return redirect('/login')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/d3", methods=['GET']) #victim specs
|
||||||
|
def cpdashy_3_main():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
userid = str(current_user.name).replace("user","").replace("User","").replace("USER","")
|
||||||
|
with open(f'database/users/{userid}/user.json','r') as f:
|
||||||
|
user_data = json.load(f)
|
||||||
|
|
||||||
|
if not os.path.exists("database/temp/attack_start.txt"):
|
||||||
|
attack_start_timestamp = "0"
|
||||||
|
else:
|
||||||
|
with open("database/temp/attack_start.txt","r") as f:
|
||||||
|
attack_start_timestamp = int(f.read().split(".")[0])
|
||||||
|
|
||||||
|
min, sec = divmod(time.time() - int(attack_start_timestamp),60)
|
||||||
|
attack_start_timestamp = str(int(min)) + "m " + str(int(round(sec,0))) + "s"
|
||||||
|
|
||||||
|
if attack_start_timestamp == "0":
|
||||||
|
reachable = "<b style='color: green'>True</b>"
|
||||||
|
cpu_percentage = random.choice(["7%","8%","9%","10%","11%"])
|
||||||
|
ram_percentage = random.choice(["7%","8%","9%","10%","11%"])
|
||||||
|
ports_open = ["80","443"]
|
||||||
|
else:
|
||||||
|
reachable = "<b style='color: green'>True</b>"
|
||||||
|
cpu_percentage = random.choice(["67%","48%","90%","17%","81%"])
|
||||||
|
ram_percentage = random.choice(["19%","8%","9%","10%","11%"])
|
||||||
|
ports_open = ["80","443"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return render_template("main/dashboard_main3.html",reachable=reachable,cpu_percentage=cpu_percentage,ram_percentage=ram_percentage,ports_open=ports_open,attack_start_timestamp=attack_start_timestamp,sidebar_html_insert=cpdash_get_sidebar().replace("active_state_class3","is-active"), profile_picture=user_data["picture"],profile_username=user_data["username"],profile_userid=user_data["userid"],profile_email=user_data["email"])
|
||||||
|
else:
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_proof_pdf():
|
||||||
|
with open('./database/logs/blue.json') as f:
|
||||||
|
blue_logs_list_ori = json.load(f)
|
||||||
|
blue_logs_list = []
|
||||||
|
for blue_log_now in blue_logs_list_ori:
|
||||||
|
blue_log_now['timestamp'] = datetime.datetime.fromtimestamp(int(blue_log_now['timestamp'])).strftime("%H:%M:%S")
|
||||||
|
blue_log_now['origin'] = 'blue'
|
||||||
|
blue_log_now['timeline_class'] = 'container_time_right'
|
||||||
|
blue_log_now['timeline_side'] = 'right'
|
||||||
|
blue_logs_list.append(blue_log_now)
|
||||||
|
|
||||||
|
with open('./database/logs/red.json') as f:
|
||||||
|
red_logs_list_ori = json.load(f)
|
||||||
|
red_logs_list = []
|
||||||
|
for red_log_now in red_logs_list_ori:
|
||||||
|
red_log_now['timestamp'] = datetime.datetime.fromtimestamp(int(red_log_now['timestamp'])).strftime("%H:%M:%S")
|
||||||
|
red_log_now['origin'] = 'red'
|
||||||
|
red_log_now['timeline_class'] = 'container_time'
|
||||||
|
red_log_now['timeline_side'] = 'left'
|
||||||
|
red_logs_list.append(red_log_now)
|
||||||
|
|
||||||
|
total_logs_list = []
|
||||||
|
total_logs_list.extend(blue_logs_list)
|
||||||
|
total_logs_list.extend(red_logs_list)
|
||||||
|
total_logs_list.sort(key=extract_time, reverse=True)
|
||||||
|
|
||||||
|
pdf = FPDF()
|
||||||
|
pdf.add_page()
|
||||||
|
|
||||||
|
pdf.image("static/icon/main_free.png", x=175, y=13, w=25, h=25, type='png', link='https://hackhpi.kyudev.xyz')
|
||||||
|
|
||||||
|
pdf.ln(h=8) #br
|
||||||
|
pdf.set_font("arial", size=28)
|
||||||
|
pdf.cell(0, 10, txt="CyberRange Export", ln=1, align='L')
|
||||||
|
pdf.set_font("arial", size=12)
|
||||||
|
pdf.ln() #br
|
||||||
|
pdf.cell(0, 10, txt="Log export of ", ln=1, align='L')
|
||||||
|
|
||||||
|
pdf.set_font("arial", size=15, style="b")
|
||||||
|
pdf.cell(0, 8, txt=datetime.datetime.now().strftime("%d.%m.%Y, %H:%M:%S"), ln=2, align='L') #name_entered
|
||||||
|
pdf.set_font("arial", size=10)
|
||||||
|
pdf.cell(0, 0, txt="Employee 2982373", ln=0) #userid
|
||||||
|
|
||||||
|
pdf.ln() #br
|
||||||
|
pdf.ln(h=10) #br
|
||||||
|
pdf.set_font("arial", size=12)
|
||||||
|
|
||||||
|
for log_now in total_logs_list:
|
||||||
|
data = re.sub('(<[a-z].*?>)|(</[a-z].*?>)', '', log_now["data"])
|
||||||
|
if log_now["origin"] == "red":
|
||||||
|
pdf.cell(0, 12, txt=f'{log_now["timestamp"]} | Attacker: {data}', ln=2, align='L')
|
||||||
|
else:
|
||||||
|
pdf.cell(0, 12, txt=f'{log_now["timestamp"]} | Defender: {data}', ln=2, align='L')
|
||||||
|
|
||||||
|
|
||||||
|
pdf.output(f'database/pdfs/export.pdf')
|
||||||
|
|
||||||
|
@app.route("/d4", methods=['GET']) #pdf
|
||||||
|
def cpdashy_4_main():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
userid = str(current_user.name).replace("user","").replace("User","").replace("USER","")
|
||||||
|
with open(f'database/users/{userid}/user.json','r') as f:
|
||||||
|
user_data = json.load(f)
|
||||||
|
|
||||||
|
generate_proof_pdf()
|
||||||
|
return send_file(f'database/pdfs/export.pdf',as_attachment=True)
|
||||||
|
else:
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
# API
|
# API
|
||||||
def clear_session_full():
|
def clear_session_full():
|
||||||
for file_now in ['./database/temp/sim_start.txt', './database/temp/attack_start.txt', './database/temp/sim_running.txt', './database/temp/attack_running.txt']:
|
for file_now in ['./database/temp/sim_start.txt', './database/temp/attack_start.txt', './database/temp/sim_running.txt', './database/temp/attack_running.txt']:
|
||||||
|
|
@ -294,7 +398,7 @@ def api_red_logs():
|
||||||
temp_json_n['data'] = remote_addr + ': ' + temp_json_n['data']
|
temp_json_n['data'] = remote_addr + ': ' + temp_json_n['data']
|
||||||
|
|
||||||
if STARTED:
|
if STARTED:
|
||||||
if temp_json_n['data'].lower() == 'start of attack':
|
if 'start of attack' in temp_json_n['data'].lower():
|
||||||
with open('./database/temp/attack_start.txt', 'w') as f:
|
with open('./database/temp/attack_start.txt', 'w') as f:
|
||||||
f.write(str(temp_json_n['timestamp']))
|
f.write(str(temp_json_n['timestamp']))
|
||||||
|
|
||||||
|
|
@ -337,3 +441,4 @@ clear_session_full()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', threaded=True, use_reloader=True, port=8088)
|
app.run(host='0.0.0.0', threaded=True, use_reloader=True, port=8088)
|
||||||
|
# app.run(host='185.78.255.231', threaded=True,use_reloader=True, port=443, ssl_context=('/etc/letsencrypt/live/network.kyudev.xyz/fullchain.pem', '/etc/letsencrypt/live/network.kyudev.xyz/privkey.pem'))
|
||||||
|
|
|
||||||
|
|
@ -1326,7 +1326,7 @@
|
||||||
<div class="video anim" style="--delay: .55s">
|
<div class="video anim" style="--delay: .55s">
|
||||||
<a href="#" style="text-decoration: none;color: #ff66d9;">
|
<a href="#" style="text-decoration: none;color: #ff66d9;">
|
||||||
<div class="video-by" title="xxx">Blue team status</div>
|
<div class="video-by" title="xxx">Blue team status</div>
|
||||||
<div class="video-name padding_stat_n">👍</div>
|
<div id="bluestatus" class="video-name padding_stat_n">👍</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div><br><br><br>
|
</div><br><br><br>
|
||||||
|
|
@ -1555,15 +1555,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_info(blue) {
|
function add_info(blue) {
|
||||||
|
let idx = 2;
|
||||||
blue.sort(timestamp_sort);
|
blue.sort(timestamp_sort);
|
||||||
let blue_count = blue.length;
|
let blue_count = blue.length;
|
||||||
if (blue_count > 1 && document.getElementById('attackstart').getAttribute('data-start') !== '-1') {
|
if (blue_count > idx && document.getElementById('attackstart').getAttribute('data-start') !== '-1') {
|
||||||
let t = to_min_s(document.getElementById('attackstart').getAttribute('data-start'), blue[1].timestamp);
|
let t = to_min_s(document.getElementById('attackstart').getAttribute('data-start'), blue[idx].timestamp);
|
||||||
blue.splice(1, 0, {data: `Time to respond: ${t}`, timestamp: parseInt(blue[1].timestamp)})
|
if (parseInt(t.split('m')[0]) > 5) {
|
||||||
|
blue.splice(idx, 0, {data: `<b style='color: red'>Time to respond: ${t}</b>`, timestamp: parseInt(blue[idx].timestamp)})
|
||||||
|
document.getElementById("bluestatus").textContent = "👎";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
blue.splice(idx, 0, {data: `Time to respond: ${t}`, timestamp: parseInt(blue[idx].timestamp)})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCounters(data) {
|
||||||
|
data.red.forEach(el => {
|
||||||
|
if (document.getElementById('simstart').getAttribute('data-start') !== '-1' && el.data.toLowerCase().includes("start of attack"))
|
||||||
|
document.getElementById('attackstart').setAttribute('data-start', el.timestamp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function populateTimeline(data) {
|
function populateTimeline(data) {
|
||||||
|
updateCounters(data);
|
||||||
add_info(data.blue);
|
add_info(data.blue);
|
||||||
data = flatten_dict(data);
|
data = flatten_dict(data);
|
||||||
data.sort(timestamp_sort);
|
data.sort(timestamp_sort);
|
||||||
|
|
@ -1609,10 +1624,11 @@
|
||||||
const iid = setInterval(() => {
|
const iid = setInterval(() => {
|
||||||
let start = parseInt(document.getElementById("simstart").getAttribute("data-start"));
|
let start = parseInt(document.getElementById("simstart").getAttribute("data-start"));
|
||||||
let end = ~~(Date.now()/1e3);
|
let end = ~~(Date.now()/1e3);
|
||||||
if (start === -1 || document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation' || document.getElementById("attackstart").getAttribute("data-start") === "-1") {
|
if (start === -1 || document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation') {
|
||||||
document.getElementById("simstart").innerHTML = "0";
|
document.getElementById("simstart").innerHTML = "0";
|
||||||
|
document.getElementById("bluestatus").textContent = "👍";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("simstart").innerHTML = end - start;
|
document.getElementById("simstart").innerHTML = to_min_s(start, end);
|
||||||
if (document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation')
|
if (document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation')
|
||||||
{
|
{
|
||||||
document.getElementById("simstart").setAttribute("data-start", "-1");
|
document.getElementById("simstart").setAttribute("data-start", "-1");
|
||||||
|
|
@ -1625,7 +1641,7 @@
|
||||||
if (start === -1 || document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation') {
|
if (start === -1 || document.getElementById('start_stop_sim_btn').innerHTML === 'Start Simulation') {
|
||||||
document.getElementById("attackstart").innerHTML = "0";
|
document.getElementById("attackstart").innerHTML = "0";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("attackstart").innerHTML = end - start;
|
document.getElementById("attackstart").innerHTML = to_min_s(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch('/api/logs')
|
fetch('/api/logs')
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
V16h7v0.82C24,19.869,22.305,22.611,19.578,23.975z"/> </svg>
|
V16h7v0.82C24,19.869,22.305,22.611,19.578,23.975z"/> </svg>
|
||||||
Victim
|
Victim
|
||||||
</a>
|
</a>
|
||||||
|
<a class="sidebar-link discover active_state_class4" href="/d4">
|
||||||
|
<svg class="svg-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M8.71,7.71,11,5.41V15a1,1,0,0,0,2,0V5.41l2.29,2.3a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-4-4a1,1,0,0,0-.33-.21,1,1,0,0,0-.76,0,1,1,0,0,0-.33.21l-4,4A1,1,0,1,0,8.71,7.71ZM21,14a1,1,0,0,0-1,1v4a1,1,0,0,1-1,1H5a1,1,0,0,1-1-1V15a1,1,0,0,0-2,0v4a3,3,0,0,0,3,3H19a3,3,0,0,0,3-3V15A1,1,0,0,0,21,14Z"/> </svg>
|
||||||
|
Export
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="side-wrapper">
|
<div class="side-wrapper">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue