summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--web-tools/bin/index.html1
-rwxr-xr-xweb-tools/bin/tools.py10
-rw-r--r--web-tools/web/totp/index.html177
-rwxr-xr-xweb-tools/web/totp/oauthtool.py268
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> &nbsp;&nbsp;&nbsp; <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">&uarr;</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 &amp; 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>
+ &nbsp; &nbsp;
+ <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>
+ &nbsp; &nbsp;
+ <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()