Created
August 14, 2024 22:42
-
-
Save RoseSecurity/5fc65f37fafc182568fa0dbdc9953db8 to your computer and use it in GitHub Desktop.
Aqueduct is a honeypot designed to simulate city water control systems, allowing users to monitor and record unauthorized interactions with virtual alternators and wells.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, request, render_template, redirect, url_for, jsonify | |
from pydantic import BaseModel, ValidationError | |
from gevent.pywsgi import WSGIServer | |
import json | |
import datetime | |
app = Flask(__name__) | |
# Model for metadata of the control request | |
class ControlRequest(BaseModel): | |
control: str | |
action: str | |
timestamp: str = datetime.datetime.now().isoformat() | |
ip_address: str | |
def record_request(data): | |
with open('logs.json', 'a') as f: | |
json.dump(data, f) | |
f.write('\n') | |
# Render the water control home page | |
@app.route('/') | |
def index(): | |
return render_template('index.html') | |
@app.route('/lift-station-details.html', methods=['GET', 'POST']) | |
def lift_station_details(): | |
if request.method == 'POST': | |
control_request_data = { | |
"control": request.form.get('station'), | |
"action": request.form.get('action'), | |
"ip_address": request.remote_addr | |
} | |
try: | |
data = ControlRequest(**control_request_data) | |
record_request(data.dict()) | |
return jsonify({"status": "success"}), 200 | |
except ValidationError as e: | |
return jsonify({"status": "error", "errors": e.errors()}), 400 | |
return render_template('lift-station-details.html') | |
@app.route('/well-details.html', methods=['GET', 'POST']) | |
def well_details(): | |
if request.method == 'POST': | |
control_request_data = { | |
"control": request.form.get('control'), | |
"action": request.form.get('action'), | |
"ip_address": request.remote_addr | |
} | |
try: | |
data = ControlRequest(**control_request_data) | |
record_request(data.dict()) | |
return jsonify({"status": "success"}), 200 | |
except ValidationError as e: | |
return jsonify({"status": "error", "errors": e.errors()}), 400 | |
return render_template('well-details.html') | |
if __name__ == '__main__': | |
http_server = WSGIServer(('', 80), app) | |
http_server.serve_forever() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>City Water System</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
background-color: #c0c0c0; | |
margin: 0; | |
padding: 20px; | |
} | |
.container { | |
background-color: #d4d0c8; | |
border: 2px outset #fff; | |
padding: 10px; | |
} | |
h1 { | |
text-align: center; | |
margin-top: 0; | |
} | |
.header { | |
display: flex; | |
justify-content: flex-end; | |
margin-bottom: 20px; | |
} | |
.using-tower { | |
border: 1px inset #fff; | |
padding: 5px; | |
background-color: #fff; | |
} | |
.main-content { | |
display: grid; | |
grid-template-columns: 1fr 2fr 1fr; | |
gap: 20px; | |
} | |
.ground-storage, .tower { | |
border: 1px solid #000; | |
padding: 10px; | |
text-align: center; | |
} | |
.storage-level, .tower-level { | |
height: 200px; | |
width: 100px; | |
border: 1px solid #000; | |
margin: 10px auto; | |
position: relative; | |
} | |
.storage-fill, .tower-fill { | |
background-color: blue; | |
position: absolute; | |
bottom: 0; | |
width: 100%; | |
} | |
.boosters { | |
display: grid; | |
gap: 10px; | |
} | |
.booster { | |
border: 1px solid #000; | |
padding: 10px; | |
} | |
.booster-status { | |
display: inline-block; | |
padding: 2px 5px; | |
color: #fff; | |
} | |
.lead { background-color: green; } | |
.lag { background-color: gray; } | |
.standby { background-color: orange; } | |
.pump { | |
width: 50px; | |
height: 30px; | |
background-color: #ccc; | |
margin: 10px auto; | |
} | |
.well-details, .buttons { | |
display: grid; | |
gap: 10px; | |
} | |
.well, .button { | |
border: 1px outset #fff; | |
padding: 5px; | |
text-align: left; | |
} | |
.well-status { | |
display: inline-block; | |
width: 10px; | |
height: 10px; | |
border-radius: 50%; | |
margin-right: 5px; | |
} | |
.active { background-color: green; } | |
.inactive { background-color: red; } | |
.button { | |
background-color: #d4d0c8; | |
cursor: pointer; | |
text-decoration: none; | |
color: black; | |
} | |
.button:active { | |
border-style: inset; | |
} | |
.alarms { | |
background-color: red; | |
color: white; | |
padding: 5px; | |
text-align: center; | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>CITY WATER SYSTEM</h1> | |
<div class="header"> | |
<div class="using-tower">USING TOWER FOR PUMPS</div> | |
</div> | |
<div class="main-content"> | |
<div class="left-column"> | |
<div class="ground-storage"> | |
<h3>GROUND STORAGE</h3> | |
<div class="storage-level"> | |
<div class="storage-fill" style="height: 69.1%;"></div> | |
</div> | |
<div>8.3 FT</div> | |
<div>69.1 %</div> | |
</div> | |
<div class="well-details"> | |
<h3>WELL DETAILS</h3> | |
<div class="well"><span class="well-status inactive"></span>#1 FLOW: 0</div> | |
<div class="well"><span class="well-status active"></span>#8 FLOW: 39</div> | |
<div class="well"><span class="well-status inactive"></span>#4 FLOW: 0</div> | |
<div class="well"><span class="well-status active"></span>#5 FLOW: 341</div> | |
<div class="well"><span class="well-status active"></span>#6 FLOW: 235</div> | |
<div class="well"><span class="well-status inactive"></span>#7 FLOW: 0</div> | |
</div> | |
</div> | |
<div class="middle-column"> | |
<div class="switch-lead">SWITCH LEAD PUMPS</div> | |
<div class="boosters"> | |
<div class="booster"> | |
<span class="booster-status lag">LAG</span> | |
WEST BOOSTER | |
<div class="pump"></div> | |
<div>FLOW: 0</div> | |
<div>RUN HOURS: 0.0</div> | |
</div> | |
<div class="booster"> | |
<span class="booster-status lead">LEAD</span> | |
MIDDLE BOOSTER | |
<div class="pump"></div> | |
<div>FLOW: 0</div> | |
<div>RUN HOURS: 0.0</div> | |
</div> | |
<div class="booster"> | |
<span class="booster-status standby">STANDBY</span> | |
EAST BOOSTER | |
<div class="pump"></div> | |
<div>FLOW: 0</div> | |
<div>RUN HOURS: 0.0</div> | |
</div> | |
</div> | |
</div> | |
<div class="right-column"> | |
<div class="tower"> | |
<h3>TOWER LEVEL</h3> | |
<div class="tower-level"> | |
<div class="tower-fill" style="height: 95%;"></div> | |
</div> | |
<div>114.8 FT</div> | |
<div>TOWER PRESSURE: 49.7</div> | |
</div> | |
<div>CITY HALL PRESSURE: 46.9</div> | |
<div class="buttons"> | |
<a href="well-details.html" class="button">WELL DETAILS</a> | |
<a href="lift-station-details.html" class="button">LIFT STATIONS</a> | |
<div class="button">CHLORINE</div> | |
<div class="button">COMMUNICATION STATISTICS</div> | |
<div class="alarms">ALARMS ACTIVE</div> | |
<div class="button">WELL SETPOINTS</div> | |
<div class="button">BOOSTER SETPOINTS</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>City Water System - Lift Station Details</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
background-color: #c0c0c0; | |
margin: 0; | |
padding: 20px; | |
} | |
.container { | |
background-color: #d4d0c8; | |
border: 2px outset #fff; | |
padding: 20px; | |
} | |
h1, h2 { | |
text-align: center; | |
margin-top: 0; | |
} | |
.lift-stations { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
gap: 20px; | |
} | |
.station { | |
border: 1px solid #000; | |
padding: 15px; | |
background-color: #fff; | |
} | |
.station-header { | |
font-weight: bold; | |
margin-bottom: 10px; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.station-status { | |
display: inline-block; | |
width: 15px; | |
height: 15px; | |
border-radius: 50%; | |
} | |
.operational { background-color: green; } | |
.warning { background-color: yellow; } | |
.alarm { background-color: red; } | |
.pump-details { | |
display: grid; | |
grid-template-columns: 1fr 1fr; | |
gap: 10px; | |
} | |
.pump { | |
border: 1px outset #d4d0c8; | |
padding: 10px; | |
background-color: #f0f0f0; | |
} | |
.button { | |
display: block; | |
width: 200px; | |
margin: 20px auto; | |
padding: 10px; | |
text-align: center; | |
background-color: #d4d0c8; | |
border: 1px outset #fff; | |
text-decoration: none; | |
color: black; | |
cursor: pointer; | |
} | |
.button:active { | |
border-style: inset; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>CITY WATER SYSTEM</h1> | |
<h2>Lift Station Details</h2> | |
<div class="lift-stations"> | |
<div class="station"> | |
<div class="station-header"> | |
<span>Lift Station #1</span> | |
<span class="station-status operational"></span> | |
</div> | |
<div>Level: 5.2 ft</div> | |
<div>Flow: 150 GPM</div> | |
<div class="pump-details"> | |
<div class="pump"> | |
<div>Pump 1</div> | |
<div>Status: Running</div> | |
<div>Runtime: 3.5 hrs</div> | |
</div> | |
<div class="pump"> | |
<div>Pump 2</div> | |
<div>Status: Standby</div> | |
<div>Runtime: 0 hrs</div> | |
</div> | |
</div> | |
</div> | |
<div class="station"> | |
<div class="station-header"> | |
<span>Lift Station #2</span> | |
<span class="station-status warning"></span> | |
</div> | |
<div>Level: 7.8 ft</div> | |
<div>Flow: 200 GPM</div> | |
<div class="pump-details"> | |
<div class="pump"> | |
<div>Pump 1</div> | |
<div>Status: Running</div> | |
<div>Runtime: 5.2 hrs</div> | |
</div> | |
<div class="pump"> | |
<div>Pump 2</div> | |
<div>Status: Running</div> | |
<div>Runtime: 4.8 hrs</div> | |
</div> | |
</div> | |
</div> | |
<div class="station"> | |
<div class="station-header"> | |
<span>Lift Station #3</span> | |
<span class="station-status alarm"></span> | |
</div> | |
<div>Level: 9.5 ft</div> | |
<div>Flow: 50 GPM</div> | |
<div class="pump-details"> | |
<div class="pump"> | |
<div>Pump 1</div> | |
<div>Status: Fault</div> | |
<div>Runtime: 1.2 hrs</div> | |
</div> | |
<div class="pump"> | |
<div>Pump 2</div> | |
<div>Status: Running</div> | |
<div>Runtime: 7.5 hrs</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<a href="/" class="button">Back to Main Dashboard</a> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
flask | |
jsonify | |
requests | |
pydantic | |
gevent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>City Water Control System</title> | |
<style> | |
body { | |
font-family: 'MS Sans Serif', Arial, sans-serif; | |
background-color: #c0c0c0; | |
color: #000; | |
margin: 0; | |
padding: 20px; | |
} | |
h1 { | |
text-align: center; | |
background-color: #000080; | |
color: #fff; | |
padding: 10px; | |
margin-top: 0; | |
} | |
.main-container { | |
display: flex; | |
justify-content: space-around; | |
margin-top: 20px; | |
} | |
.group-box { | |
background-color: #d4d0c8; | |
border: 2px outset #fff; | |
padding: 10px; | |
width: 45%; | |
} | |
.group-box h2 { | |
background-color: #000080; | |
color: #fff; | |
margin: -10px -10px 10px -10px; | |
padding: 5px; | |
font-size: 1.2em; | |
} | |
.control-box { | |
background-color: #d4d0c8; | |
border: 1px solid #888; | |
padding: 10px; | |
margin-bottom: 10px; | |
} | |
.control-box h3 { | |
margin-top: 0; | |
font-size: 1em; | |
} | |
label { | |
display: inline-block; | |
width: 80px; | |
margin-bottom: 5px; | |
} | |
select, button { | |
width: 120px; | |
background-color: #fff; | |
color: #000; | |
border: 1px inset #888; | |
padding: 2px; | |
} | |
button { | |
background-color: #d4d0c8; | |
border: 2px outset #fff; | |
padding: 5px; | |
margin-top: 5px; | |
cursor: pointer; | |
} | |
button:active { | |
border-style: inset; | |
} | |
form { | |
display: inline; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>City Water Control System</h1> | |
<div class="main-container"> | |
<div class="group-box"> | |
<h2>Well Controls</h2> | |
<div class="control-box"> | |
<h3>Well 1</h3> | |
<form action="/well-details.html" method="post"> | |
<input type="hidden" name="control" value="Well 1"> | |
<label for="well1_status">Status:</label> | |
<select name="action" id="well1_status"> | |
<option value="lead">Lead</option> | |
<option value="standby">Standby</option> | |
<option value="off">Off</option> | |
</select><br> | |
<button type="submit">Set Well 1</button> | |
</form> | |
</div> | |
<div class="control-box"> | |
<h3>Well 2</h3> | |
<form action="/well-details.html" method="post"> | |
<input type="hidden" name="control" value="Well 2"> | |
<label for="well2_status">Status:</label> | |
<select name="action" id="well2_status"> | |
<option value="lead">Lead</option> | |
<option value="standby">Standby</option> | |
<option value="off">Off</option> | |
</select><br> | |
<button type="submit">Set Well 2</button> | |
</form> | |
</div> | |
<div class="control-box"> | |
<h3>Well 3</h3> | |
<form action="/well-details.html" method="post"> | |
<input type="hidden" name="control" value="Well 3"> | |
<label for="well3_status">Status:</label> | |
<select name="action" id="well3_status"> | |
<option value="lead">Lead</option> | |
<option value="standby">Standby</option> | |
<option value="off">Off</option> | |
</select><br> | |
<button type="submit">Set Well 3</button> | |
</form> | |
</div> | |
</div> | |
<div class="group-box"> | |
<h2>Alternator Controls</h2> | |
<div class="control-box"> | |
<h3>Alternator 1</h3> | |
<form action="/well-details.html" method="post"> | |
<input type="hidden" name="control" value="Alternator 1"> | |
<label for="alt1_status">Status:</label> | |
<select name="action" id="alt1_status"> | |
<option value="on">On</option> | |
<option value="off">Off</option> | |
</select><br> | |
<button type="submit">Set Alternator 1</button> | |
</form> | |
</div> | |
<div class="control-box"> | |
<h3>Alternator 2</h3> | |
<form action="/well-details.html" method="post"> | |
<input type="hidden" name="control" value="Alternator 2"> | |
<label for="alt2_status">Status:</label> | |
<select name="action" id="alt2_status"> | |
<option value="on">On</option> | |
<option value="off">Off</option> | |
</select><br> | |
<button type="submit">Set Alternator 2</button> | |
</form> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment