diff options
-rw-r--r-- | web-tools/bin/index.html | 1 | ||||
-rwxr-xr-x | web-tools/bin/tools.py | 10 | ||||
-rw-r--r-- | web-tools/web/totp/index.html | 177 | ||||
-rwxr-xr-x | web-tools/web/totp/oauthtool.py | 268 |
4 files changed, 455 insertions, 1 deletions
diff --git a/web-tools/bin/index.html b/web-tools/bin/index.html index c54f22f..3c2ac1d 100644 --- a/web-tools/bin/index.html +++ b/web-tools/bin/index.html @@ -141,6 +141,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. <b>Security</b><br /> <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=nmap">nmap</button> + <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=ssh-audit">ssh-audit</button> <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=testssl">testssl</button> <div style="height: 1em"></div> diff --git a/web-tools/bin/tools.py b/web-tools/bin/tools.py index bf1a067..3bb6a9e 100755 --- a/web-tools/bin/tools.py +++ b/web-tools/bin/tools.py @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # Dependencies: -# sudo apt install iputils-ping traceroute whois nmap testssl.sh geoip-bin geoip-database knot-dnsutils +# sudo apt install iputils-ping traceroute whois nmap ssh-audit testssl.sh geoip-bin geoip-database knot-dnsutils from cgi import FieldStorage from datetime import datetime @@ -214,6 +214,14 @@ def main(): else: options = ' ' #-O -T5 + elif Command == 'ssh-audit': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' --no-colors ' elif Command == 'testssl': options = ' --color 0 ' elif Command == 'whois': diff --git a/web-tools/web/totp/index.html b/web-tools/web/totp/index.html new file mode 100644 index 0000000..96f7e9f --- /dev/null +++ b/web-tools/web/totp/index.html @@ -0,0 +1,177 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <meta name="author" content="bfh.info"> + <meta name="description" content="tools.bfh.info"> + <meta name="generator" content="bfh-linux-sysadmin@lists.bfh.science"> + + <title>tools.bfh.info</title> + <link rel="canonical" href="https://bfh.info"> + + <!-- Bootstrap core CSS --> + <link href="/_static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="/_static/dejavu-fonts/dejavu-fonts.css" rel="stylesheet"> + <link href="/_static/fontawesome-pro/css/all.min.css" rel="stylesheet"> + + <link href="/_static/local/body.css" rel="stylesheet"> + <link href="/_static/local/font.css" rel="stylesheet"> + <link href="/_static/local/footer.css" rel="stylesheet"> + </head> + + <body> + <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> + <a class="navbar-brand" href="/"><b>tools.bfh.info</b></a> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsDefault" aria-controls="navbarsDefault" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + + <div class="collapse navbar-collapse" id="navbarsDefault"> + <ul class="navbar-nav mr-auto"> + </ul> + </div> + </nav> + + <main role="main" class="container"> + + <div class="content"> + +<!-- +Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> + +SPDX-License-Identifier: GPL-3.0+ + +This program 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. + +This program 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 +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +--> + +<a name="top"></a> +<h1><i class="fa-fw far fa-tools"></i> TOTP<sup><small>beta</small></sup> <small>(<a href="/api">API</a>)</small></h1> +<div style="height: 2em"></div> + +<script src="/_static/jquery/jquery.min.js"></script> + +<script> + $(document).ready(function(){ + $("[type=button]").click(function() { + var command = $(this).data("command"); + var protocol = $("input[name='protocol']:checked").val(); + var seed = document.getElementById("seed").value; + var cgi = command + "&protocol=" + protocol + "&seed=" + seed; + $.ajax({url: cgi, success: function(result){ + $("#output").text(result); + document.getElementById('output-hidden').style.display = 'block'; + $(document).scrollTop( $("#output").offset().top -125); + }}); + }); + + $("[type=reset]").click(function() { + $("#dual-stack").click(); + $('.btn-group').find('reset').removeClass('active') + .end().find('[type="reset"]').prop('checked', false); + document.getElementById('output-hidden').style.display = 'none'; + $("#seed").focus(); + $("#seed").prop('autofocus'); + }); + }); +</script> + +<style type="text/css"> + label, [type="button"], [type="reset"], [type="text"] { + margin-top: 0.5em; + } +</style> + +<div class="row"> + <div class="col-md-3"> + <form id="form"> + <div class="form-group"> + <b>Seed (base32)</b> + <input id="seed" placeholder="xyz..." style="width: 100%;" type="text" autofocus /> + + </div> + </form> + </div> + + <div class="col-md-6"> + <div id="output-hidden" style="display: none;"> + <a name="output"></a> + <a href="#top"><button type="button" class="btn btn-light btn-sm float-right">↑</button></a><br /> + <b>Output</b><br /> + <pre> + <textarea id="output" readonly rows="25" style="background: #f1f1f1; width: 100%;"></textarea> + </pre> + </div> + </div> +</div> + +<hr /> + + </main><!-- /.container --> + + <footer class="footer py-5"> + <div class="container"> + <div class="row"> + <div class="col-md-2"> + <a href="https://www.bfh.ch"><img src="/logo.svg" style="height: 112.5px" /></a><br /> + <br /> + </div> + <div class="col-md-3"> + <small> + <strong><i class="fa-fw fas fa-map-marker"></i> Address</strong><br /> + <a class="text-muted" href="https://www.openstreetmap.org/search?query=Dammweg 3%2C 3013 Bern">Berner Fachhochschule<br /> + IT-Services<br /> + Team Linux & Infrastructure Services<br /> + Dammweg 3, CH-3013 Bern</a><br /> + <br /> + </small> + </div> + <div class="col-md-3"> + <small> + <strong><i class="fa-fw fas fa-phone"></i> Phone</strong><br /> + <a class="text-muted" href="#">+41 31 848 48 48</a><br /> + <br /> + <strong><i class="fa-fw fas fa-envelope"></i> Email</strong><br /> + <a class="text-muted" href="mailto:bfh-linux-sysadmin@lists.bfh.science?subject=BFH.science:%20Feedback">bfh-linux-sysadmin@lists.bfh.science</a><br /> + <br /> + </small> + </div> + <div class="col-md-4"> + <small> + <br /> + <br /> + <br /> + <br /> + <i class="fa-fw fas fa-copyright"></i> <a class="text-muted" href="https://bfh.science/other/legal">2021</a> + + <a style="color: inherit;" href="https://bfh.science/other/legal" title="Legal Information"><i class="fa-fw fas fa-balance-scale"></i></a> <a class="text-muted" href="https://bfh.science/other/legal" title="Legal Information">Legal Information</a> + + <a class="a-hover-red" href="https://git.bfh.info" title="Made with Love and Git"><i class="fa-fw fas fa-heart"></i></a> <a class="text-muted" href="https://git.bfh.info" title="Made with Love and Git">Source Code</a><br /> + <br /> + </small> + </div> + </div> + </div> + </footer> + + <!-- Bootstrap core JS --> + <script src="/_static/popperjs/popper.min.js"></script> + <script src="/_static/bootstrap/js/bootstrap.min.js"></script> + + <!-- Custom scripts for this template --> + <script src="/_static/local/table.js"></script> + </body> +</html> diff --git a/web-tools/web/totp/oauthtool.py b/web-tools/web/totp/oauthtool.py new file mode 100755 index 0000000..3bb6a9e --- /dev/null +++ b/web-tools/web/totp/oauthtool.py @@ -0,0 +1,268 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program 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. +# +# This program 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Dependencies: +# sudo apt install iputils-ping traceroute whois nmap ssh-audit testssl.sh geoip-bin geoip-database knot-dnsutils + +from cgi import FieldStorage +from datetime import datetime +import ipaddress +from os import getenv +from subprocess import Popen, PIPE +from sys import exit + +def filter_nameservers(servers, protocol): + nameservers= [] + + for server in servers: + name = server.rstrip().rstrip('.') + + if protocol == 'ipv6-only': + command = 'kdig -6' + options = ' -t AAAA +short -q ' + elif protocol == 'ipv4-only': + command = 'kdig -4' + options = ' -t A +short -q ' + else: + command = 'kdig' + options = ' +short -q ' + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + address = kdig.stdout.readline() + + if address: + nameservers.append(name) + + return nameservers + +def get_nameserver(name, protocol): + nameservers = [] + + if protocol == 'ipv6-only': + command = 'kdig -6' + elif protocol == 'ipv4-only': + command = 'kdig -4' + else: + command = 'kdig' + + options = ' -t NS +short -q ' + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + servers = kdig.stdout.readlines() + + count = 0 + while not servers and count < 10: + name = name.split('.') + del name[0] + name = '.'.join(name) + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + servers = kdig.stdout.readlines() + + count += 1 + + names = [] + for server in servers: + name = server.rstrip().decode('utf-8').rstrip('.') + names.append(name) + + nameservers = filter_nameservers(names, protocol) + return nameservers + +def run_command(command): + process = Popen(command, stdout=PIPE) + empty_lines = 0 + while True: + line = process.stdout.readline().rstrip() + if not line: + empty_lines = empty_lines + 1 + if empty_lines > 2: + break + else: + print() + else: + empty_lines = 0 + yield line.decode('utf-8') + +def main(): + form = FieldStorage() + + if form.getvalue("command"): + Command = form.getvalue("command").split()[0] + + if "target" in form: + Target = form.getvalue("target").split()[0] + + if "protocol" in form: + Protocol = form.getvalue("protocol").split()[0] + + if "query" in form: + Query = form.getvalue("query").split()[0] + + if Command and Protocol and Target: + print('Content-Type: text/html\n') + + Date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + if Command == 'kdig': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + + if Query == 'PTR': + arpa = ipaddress.ip_address(Target).reverse_pointer + + nameserver = get_nameserver(arpa, Protocol) + + protocol_passed = False + + for server in nameserver: + check_options = options + ' @' + server + ' -t ' + Query + ' -q ' + + command_line = (Command + ' +short' + check_options + arpa).split() + kdig = Popen(command_line, stdout=PIPE) + protocol_check = kdig.stdout.readline() + + if protocol_check: + protocol_passed = True + break + + if not protocol_passed: + print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n') + print('--') + print('Run: ' + str(command_line)) + print('Date: ' + Date) + + exit(0) + + options = options + ' @' + server + ' -x ' + else: + nameserver = get_nameserver(Target, Protocol) + + protocol_passed = False + + for server in nameserver: + check_options = options + ' @' + server + ' -t ' + Query + ' -q ' + + command_line = (Command + ' +short' + check_options + Target).split() + kdig = Popen(command_line, stdout=PIPE) + protocol_check = kdig.stdout.readline() + + if protocol_check: + protocol_passed = True + break + + if not protocol_passed: + print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n') + print('--') + print('Run: ' + str(command_line)) + print('Date: ' + Date) + + exit(0) + + options = options + ' @' + server + ' -t ' + Query + ' -q ' + elif Command == 'ping': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' -c3 ' + elif Command == 'traceroute': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' ' + elif Command == 'tcptraceroute': + Command = 'traceroute' + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' -T ' + elif Command == 'nmap': + if Protocol == 'ipv6-only': + options = ' -6' + else: + options = ' ' + #-O -T5 + elif Command == 'ssh-audit': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' --no-colors ' + elif Command == 'testssl': + options = ' --color 0 ' + elif Command == 'whois': + options = ' -H ' + else: + options = ' ' + + if Command == 'my-ip': + command_line = '' + + ip_address = getenv('REMOTE_ADDR') + print('IP address: ' + ip_address) + + # TODO: show reverse DNS + + if ':' in ip_address: + print('IP version: IPv6') + process = Popen(['geoiplookup6', ip_address], stdout=PIPE) + else: + print('IP version: IPv4') + process = Popen(['geoiplookup', ip_address], stdout=PIPE) + + geoiplookup = process.stdout.readline().rstrip() + country = geoiplookup.decode('utf-8').split(':')[1] + print('Country:' + country + '\n\n') + elif Command == 'my-browser': + command_line = '' + print('User-Agent: ' + getenv('HTTP_USER_AGENT', 'n/a') + '\n\n') + else: + command_line = Command + options + Target + + for path in run_command(command_line.split()): + print(path) + + print('--') + print('Date: ' + Date) + + if command_line: + print('Run: ' + command_line) + + exit(0) + +if __name__ == '__main__': + main() |