Skip to content

Commit

Permalink
[2.4.2] Hardening code and report
Browse files Browse the repository at this point in the history
 - add hardening rule for script timeout
 - change hardening level
 - re-make hardening python code
 - hardening report (text)
 - auto-delete process for real time output
 - MANIFEST.in exclude audit files
 - Fix: request multiline
 - Fix: request first output
 - Fix: csv databases (NUL characters)
 - Fix: Windows config files
  • Loading branch information
mauricelambert authored Dec 3, 2021
1 parent 20d66e7 commit 3bf4082
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 33 deletions.
77 changes: 63 additions & 14 deletions WebScripts/modules/error_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@

from typing import Tuple, Dict, List, TypeVar
from email.message import EmailMessage
from collections.abc import Iterator
from smtplib import SMTP, SMTP_SSL
from collections import namedtuple
from os import _Environ, path
from threading import Thread
from string import Template
Expand All @@ -40,6 +42,21 @@
ServerConfiguration = TypeVar("ServerConfiguration")
User = TypeVar("User")

_Request = namedtuple(
"_Request",
[
"ID",
"Time",
"UserName",
"ErrorCode",
"Page",
"UserAgent",
"Subject",
"Reason",
"Name",
],
)

__version__ = "0.0.4"
__author__ = "Maurice Lambert"
__author_email__ = "[email protected]"
Expand Down Expand Up @@ -198,7 +215,8 @@
</div>
<div id="submit_row" class="row">
<input type="hidden" id="code" name="code" value="${code}">
<input type="hidden" id="error" name="error" \
value="${code}">
<input type="hidden" name="csrf_token" id="csrf_token" \
value="{csrf}">
<div class="submit_position">
Expand Down Expand Up @@ -426,7 +444,7 @@
},
{
"input": false,
"name": "code"
"name": "error"
}
]
};
Expand Down Expand Up @@ -541,7 +559,9 @@ def send_mail(
configuration: ServerConfiguration, notification: str
) -> None:

"""This function send a notification mail."""
"""
This function send a notification mail.
"""

server_name = getattr(configuration, "smtp_server", None)
starttls = getattr(configuration, "smtp_starttls", None)
Expand Down Expand Up @@ -588,19 +608,35 @@ def save(
reason: str,
) -> None:

"""This function save the report/request to a CSV file."""
"""
This function save the report/request to a CSV file.
"""

filename = path.join(
path.dirname(__file__), "..", "data", "requests.csv"
)

with open(filename) as file:
id_ = 0
line = file.readline() # First line is columns
line = file.readline()
while line:
id_ = int(line.split(",")[0][1:-1]) + 1
line = file.readline()
def get_requests() -> Iterator[_Request]:

"""
This function build Request from database.
"""

yield from map(
_Request._make,
csv.reader(
open(filename, "r", newline=""),
quoting=csv.QUOTE_ALL,
),
)

id_ = 0
first = True
for request in get_requests():
if first: # columns
first = False
continue
id_ = int(request.ID) + 1

with open(filename, "a", newline="") as file:
csvfile = csv.writer(file, quoting=csv.QUOTE_ALL)
Expand Down Expand Up @@ -628,7 +664,9 @@ def send(
csrf_token: str = None,
) -> Tuple[str, Dict[str, str], str]:

"""This function save and send request or report."""
"""
This function save and send request or report.
"""

referer = escape(environ.get("HTTP_REFERER"))
user_agent = escape(environ.get("HTTP_USER_AGENT"))
Expand All @@ -638,8 +676,19 @@ def send(
code = escape(code)
user.name = escape(user.name)

while len(arguments) < 4:
arguments.append(None)
for string in (
referer,
user_agent,
code,
user.name,
subject,
name,
reason,
):
if not string.isprintable():
raise ValueError(
f"Strings must be printable: '{string}' is not."
)

notification = (
f'The user named: "{user.name}" get a HTTP error '
Expand Down
58 changes: 50 additions & 8 deletions WebScripts/modules/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

sys.path = [
path.join(*base_path, "scripts", "uploads", "modules"),
path.join(*base_path),
] + sys.path

from uploads_management import (
Expand All @@ -71,8 +72,13 @@
check_permissions,
get_real_file_name,
get_file,
get_files,
Upload,
)
from Pages import Pages, check_right

sys.path.pop(0)
sys.path.pop(0)
ServerConfiguration = TypeVar("ServerConfiguration")


Expand Down Expand Up @@ -117,6 +123,19 @@ def filename(
if not file.no_compression:
headers["Content-Encoding"] = "gzip"

return (
"200 OK",
headers,
Download.get_data(file),
)

@staticmethod
def get_data(file: Upload) -> bytes:

"""
This function get file and manage the compression.
"""

with open(
get_real_file_name(file.name, float(file.timestamp)), "rb"
) as file_:
Expand All @@ -126,17 +145,13 @@ def filename(
else:
data = file_.read()

return (
"200 OK",
headers,
data,
)
return data

def id(
environ: _Environ,
user: User,
server_configuration: ServerConfiguration,
filename: str,
id_: str,
arguments: List[str],
inputs: List[str],
csrf_token: str = None,
Expand All @@ -146,8 +161,35 @@ def id(
This funtion download file by ID.
"""

raise NotImplementedError(
"This function is not yet implemented for permission reasons."
script = Pages.scripts.get("get_any_file.py")

if script is None:
return "404", {}, b""

if not check_right(user, script):
return "403", {}, b""

headers = {
"Content-Type": "application/octet-stream",
}

ask_file = None

for file in get_files():
if file.ID == id_:
ask_file = file
break

if ask_file is None:
return "404", {}, b""

if not ask_file.no_compression:
headers["Content-Encoding"] = "gzip"

return (
"200 OK",
headers,
Download.get_data(ask_file),
)


Expand Down
10 changes: 9 additions & 1 deletion WebScripts/scripts/account/modules/manage_defaults_databases.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
This file implement some functions to manage WebScript default databases."""

__version__ = "1.1.1"
__version__ = "1.2.0"
__author__ = "Maurice Lambert"
__author_email__ = "[email protected]"
__maintainer__ = "Maurice Lambert"
Expand Down Expand Up @@ -272,6 +272,10 @@ def add_user(
)
)

for string in user:
if not string.isprintable():
raise ValueError(f"Strings must be printable: '{string}' is not.")

with open(path.join(DIRECTORY, FILES[0]), "a", newline="") as csvfile:
csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
csv_writer.writerow(user)
Expand Down Expand Up @@ -345,6 +349,10 @@ def add_group(name: str, id_: int) -> Group:

group = anti_XSS(Group(id_, name))

for string in group:
if not string.isprintable():
raise ValueError(f"Strings must be printable: '{string}' is not.")

with open(path.join(DIRECTORY, FILES[1]), "a", newline="") as csvfile:
csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
csv_writer.writerow(group)
Expand Down
10 changes: 8 additions & 2 deletions WebScripts/scripts/passwords/new_password_share.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
This file can share a password securely."""

__version__ = "0.0.4"
__version__ = "0.1.0"
__author__ = "Maurice Lambert"
__author_email__ = "[email protected]"
__maintainer__ = "Maurice Lambert"
Expand Down Expand Up @@ -190,7 +190,13 @@ def main() -> None:
password, hash_, iteration, key = encrypt(password)
password, key = get_printable(password, key)

passwords.append([timestamp, password, views, hash_, iteration, id_])
password = [timestamp, password, views, hash_, iteration, id_]

for string in passwords:
if isinstance(string, str) and not string.isprintable():
raise ValueError(f"Strings must be printable: '{string}' is not.")

passwords.append()
save(passwords, id_)

print(
Expand Down
2 changes: 1 addition & 1 deletion WebScripts/scripts/request/modules/requests_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def anti_XSS(named_tuple: namedtuple) -> namedtuple:

def get_requests() -> Iterator[Request]:

"""This function build Uploads from database."""
"""This function build Request from database."""

yield from map(
Request._make,
Expand Down
2 changes: 1 addition & 1 deletion WebScripts/scripts/uploads/get_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
__all__ = []

from modules.uploads_management import (
read_file,
# read_file,
get_file,
check_permissions,
get_user,
Expand Down
8 changes: 7 additions & 1 deletion WebScripts/scripts/uploads/modules/uploads_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,13 @@ def delete_file(name: str) -> Upload:

def write_action(upload: Upload) -> None:

"""This function write a new line in CSV database."""
"""
This function write a new line in CSV database.
"""

for string in upload:
if not string.isprintable():
raise ValueError(f"Strings must be printable: '{string}' is not.")

with open(path.join(DIRECTORY, FILE), "a", newline="") as csvfile:
csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
Expand Down
2 changes: 1 addition & 1 deletion WebScripts/static/html/Pages.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#9286C2">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>Pages</strong></big></big> (version 1.0.0)</font></td
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>Pages</strong></big></big> (version 1.0.1)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="pages.py">pages.py</a></font></td></tr></table>
<p><tt>This&nbsp;tools&nbsp;run&nbsp;scripts&nbsp;and&nbsp;display&nbsp;the&nbsp;result&nbsp;in&nbsp;a&nbsp;Web&nbsp;Interface.<br>
Expand Down
14 changes: 13 additions & 1 deletion WebScripts/static/html/hardening.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#9286C2">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>hardening</strong></big></big> (version 0.2.0)</font></td
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>hardening</strong></big></big> (version 0.2.1)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="hardening.py">hardening.py</a></font></td></tr></table>
<p><tt>This&nbsp;tools&nbsp;run&nbsp;scripts&nbsp;and&nbsp;display&nbsp;the&nbsp;result&nbsp;in&nbsp;a&nbsp;Web&nbsp;Interface.<br>
Expand Down Expand Up @@ -110,6 +110,8 @@
<dl><dt><a name="Audit-audits_scripts_stderr_content_type"><strong>audits_scripts_stderr_content_type</strong></a>(server: ~Server) -&gt; collections.abc.Iterator</dt><dd><tt>This&nbsp;function&nbsp;check&nbsp;the&nbsp;configuration&nbsp;of&nbsp;the&nbsp;script&nbsp;stderr&nbsp;content<br>
type.</tt></dd></dl>

<dl><dt><a name="Audit-audits_timeout"><strong>audits_timeout</strong></a>(server: ~Server) -&gt; collections.abc.Iterator</dt><dd><tt>This&nbsp;function&nbsp;check&nbsp;scripts&nbsp;timeout.</tt></dd></dl>

<dl><dt><a name="Audit-check_for_updates"><strong>check_for_updates</strong></a>(configuration: ~ServerConfiguration, logs: ~Logs, send_mail: collections.abc.Callable) -&gt; None</dt><dd><tt>This&nbsp;function&nbsp;runs&nbsp;in&nbsp;a&nbsp;thread&nbsp;indefinitely,&nbsp;it&nbsp;checks&nbsp;the&nbsp;version<br>
and&nbsp;the&nbsp;latest&nbsp;published&nbsp;version&nbsp;of&nbsp;WebScripts&nbsp;every&nbsp;hour.<br>
If&nbsp;the&nbsp;version&nbsp;and&nbsp;the&nbsp;latest&nbsp;published&nbsp;version&nbsp;are&nbsp;different,<br>
Expand Down Expand Up @@ -155,9 +157,19 @@

<dl><dt><a name="Report-as_text"><strong>as_text</strong></a>(self) -&gt; str</dt><dd><tt>This&nbsp;function&nbsp;return&nbsp;a&nbsp;HTML&nbsp;string&nbsp;of&nbsp;audit&nbsp;results.</tt></dd></dl>

<dl><dt><a name="Report-get_pourcent"><strong>get_pourcent</strong></a>(self) -&gt; None</dt><dd><tt>This&nbsp;function&nbsp;calcul&nbsp;pourcent.</tt></dd></dl>

<dl><dt><a name="Report-notification"><strong>notification</strong></a>(self) -&gt; None</dt><dd><tt>This&nbsp;function&nbsp;send&nbsp;an&nbsp;email&nbsp;notification<br>
to&nbsp;administrator&nbsp;with&nbsp;the&nbsp;audit&nbsp;report.</tt></dd></dl>

<hr>
Static methods defined here:<br>
<dl><dt><a name="Report-get_HTML_table"><strong>get_HTML_table</strong></a>(headers: str, rules: List[hardening.Rule]) -&gt; str</dt><dd><tt>This&nbsp;function&nbsp;returns&nbsp;a&nbsp;HTML&nbsp;table&nbsp;with&nbsp;rule&nbsp;attributes&nbsp;as&nbsp;columns.</tt></dd></dl>

<dl><dt><a name="Report-get_text_table"><strong>get_text_table</strong></a>(headers: str, rules: List[hardening.Rule], joiner: str = ' ') -&gt; str</dt><dd><tt>This&nbsp;function&nbsp;return&nbsp;a&nbsp;text&nbsp;table&nbsp;with&nbsp;rule&nbsp;attributes&nbsp;as&nbsp;columns.</tt></dd></dl>

<dl><dt><a name="Report-truncate_string"><strong>truncate_string</strong></a>(string: str, length: int = 13, end: str = '...', separator: str = ',') -&gt; str</dt><dd><tt>This&nbsp;function&nbsp;truncate&nbsp;a&nbsp;string.</tt></dd></dl>

<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__dict__</strong></dt>
Expand Down
2 changes: 1 addition & 1 deletion WebScripts/static/html/manage_defaults_databases.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#9286C2">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>manage_defaults_databases</strong></big></big> (version 1.1.1)</font></td
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>manage_defaults_databases</strong></big></big> (version 1.2.0)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="manage_defaults_databases.py">manage_defaults_databases.py</a></font></td></tr></table>
<p><tt>This&nbsp;tools&nbsp;run&nbsp;scripts&nbsp;and&nbsp;display&nbsp;the&nbsp;result&nbsp;in&nbsp;a&nbsp;Web&nbsp;Interface.<br>
Expand Down
2 changes: 1 addition & 1 deletion WebScripts/static/html/requests_management.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
<tr><td bgcolor="#A57927"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-delete_request"><strong>delete_request</strong></a>(id_: str) -&gt; requests_management.Request</dt><dd><tt>This&nbsp;function&nbsp;rewrite&nbsp;the&nbsp;request&nbsp;database&nbsp;without&nbsp;the&nbsp;specified&nbsp;request.</tt></dd></dl>
<dl><dt><a name="-get_request"><strong>get_request</strong></a>(id_: str) -&gt; requests_management.Request</dt><dd><tt>This&nbsp;function&nbsp;return&nbsp;a&nbsp;specific&nbsp;request.</tt></dd></dl>
<dl><dt><a name="-get_requests"><strong>get_requests</strong></a>() -&gt; collections.abc.Iterator</dt><dd><tt>This&nbsp;function&nbsp;build&nbsp;Uploads&nbsp;from&nbsp;database.</tt></dd></dl>
<dl><dt><a name="-get_requests"><strong>get_requests</strong></a>() -&gt; collections.abc.Iterator</dt><dd><tt>This&nbsp;function&nbsp;build&nbsp;<a href="#Request">Request</a>&nbsp;from&nbsp;database.</tt></dd></dl>
</td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#18675F">
Expand Down
Loading

0 comments on commit 3bf4082

Please sign in to comment.