This commit is contained in:
brent s 2017-10-06 14:05:56 -04:00
parent 8aaf23cdac
commit a6c557097a
8 changed files with 184 additions and 27 deletions

1
net/addr/TODO Normal file
View File

@ -0,0 +1 @@
We can get more in-depth: https://danidee10.github.io/2016/09/24/flask-by-example-3.html

View File

@ -0,0 +1,8 @@
{% extends "base.html" %}{% block title %}r00t^2 Client Info Revealer || About{% endblock %}{% block body %}<div class="jumbotron">
<h1>About</h1></div>
<p>This is a tool to reveal certain information about your connection that the server sees. Note that all of this information you see is <i>sent by your client</i>; there was no probing/scanning or the like done from the server this site is hosted on.</p>
<p>If you don't like this info being available to server administrators of the websites you visit you may want to consider <a href="https://getfoxyproxy.org/">hiding your client IP address</a><sup><a href="#0">0</a></sup> and/or <a href="https://panopticlick.eff.org/self-defense">hiding your browser's metadata</a>, which can be done via browser plugins such as <a href="https://www.eff.org/privacybadger">Privacy Badger</a>, {{ '<a href="https://addons.mozilla.org/en-US/firefox/addon/modify-headers/">Modify Headers</a>, '|safe if request.user_agent.browser == 'firefox' else '' }}<a href="https://www.requestly.in/">Requestly</a>, and others.</p>
<p>If you would like to view the <i>server</i> headers, then you can use a service such as <a href="https://securityheaders.io">SecurityHeaders.io</a> (or use the <b><code>curl -i</code></b> command in *Nix operating systems).</p>
<br />
<p><a name="0"></a><b>[0]</b> Disclosure: I am an engineer for this company.</p>
{% endblock %}

View File

@ -1,31 +1,35 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>{% block title %}{% endblock %}</title>
<!-- Bootstrap core CSS -->
<!-- Thanks, https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xii-facelift and
https://scotch.io/tutorials/getting-started-with-flask-a-python-microframework -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">-->
<!-- Custom styles for this template -->
<link href="https://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
<!--<link href="https://getbootstrap.com/docs/4.0/examples/offcanvas/offcanvas.css" rel="stylesheet">-->
</head>

<body>
<div class="container">
<div class="header clearfix">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation"><a href="/">Home</a></li>
<li role="presentation"><a href="/about">About</a></li>
<li role="presentation"><a href="/usage">Usage</a></li>
<!-- the following opens in a new tab/window/whatever. the line after opens in the same tab/window/etc. -->
<!-- <li role="presentation"><a href="https://square-r00t.net/" target="_blank">r00t^2</a></li> -->
<li role="presentation"><a href="https://square-r00t.net/">r00t^2</a></li>
</ul>
</nav>
</div>
{% block body %} {% endblock %}
{% block body %}{% endblock %}
<footer class="footer">
<p><sub>The code for this page is released under the <a href="https://www.gnu.org/licenses/gpl-3.0.en.html#content">GPL 3.0 License</a>. It can be found <a href="https://git.square-r00t.net/OpTools/tree/net">here</a>.</sub></p>
</footer>
</div>
<!-- /container -->
</body>

</html>

View File

@ -0,0 +1,38 @@
<h2>Client/Browser Information</h2>
<p>This is information that your browser sends with its connection.</p>
<p>
<ul>
<li><b>Client IP:</b> <a href="https://ipinfo.io/{{ visitor['ip'] }}">{{ visitor['ip'] }}</a></li>
<li><b>Browser:</b> {{ '<a href="{0}">{1}</a>'.format(browsers[visitor['client']['browser']][0],
browsers[visitor['client']['browser']][1])|safe
if visitor['client']['browser'] in browsers.keys()
else visitor['client']['browser'].title()
if visitor['client']['browser'] is not none
else '(N/A)' }}</li>
<li><b>Language/Locale:</b> {{ visitor['client']['language'] or '(N/A)' }}</li>
{%- set alt_os = alts[visitor['client']['os']] if visitor['client']['os'] in alts.keys() else '' %}
<li><b>Operating System:</b> {{ '<a href="{0}">{1}</a>{2}'.format(os[visitor['client']['os']][0],
os[visitor['client']['os']][1],
alt_os)|safe
if visitor['client']['os'] in os.keys()
else visitor['client']['os'].title()
if visitor['client']['os'] is not none
else '(N/A)' }}</li>
<li><b>User Agent:</b> {{ visitor['client']['str'] }}</li>
<li><b>Version:</b> {{ visitor['client']['version'] or '(N/A)' }}</li>
</ul>
</p>
<h2>Request Headers</h2>
<p>These are headers sent along with the request your browser sends for the page's content.</p>
<p>
<table>
<tr>
<th>Field</th>
<th>Value</th>
</tr>{% for k in visitor['headers'].keys()|sort(case_sensitive = True) %}
<tr>
<td>{{ k }}</td>
<td>{{ visitor['headers'][k] if visitor['headers'][k] != '' else '(N/A)' }}</td>
</tr>{% endfor %}
</table>
</p>

View File

@ -1,7 +1,6 @@
{% extends "base.html" %} {% block title %}r00t^2 Client Info Revealer{% endblock %}{% block body %}
<div class="jumbotron">
<h1>What this is</h1>
<p class="lead">This is a tool to reveal certain information about your connection that the server sees.</p>
{% extends "base.html" %}{% block title %}r00t^2 Client Info Revealer{% endblock %}{% block body %}<div class="jumbotron">
<h1>Client Info Revealer</h1>
<p class="lead">A tool to reveal client-identifying data sent to webservers</p>
</div>
<p>PLACEHOLDER.</p>
{% endblock %}
{% include 'html.html' if not params['json'] else 'json.html' %}
{% endblock %}

View File

@ -0,0 +1 @@
<pre>{{ json }}</pre>

View File

@ -0,0 +1,51 @@
{% extends "base.html" %}{% block title %}r00t^2 Client Info Revealer || Usage{% endblock %}{% block body %}<div class="jumbotron">
<h1>Usage</h1></div>
<h2>Parameters</h2>
<p>You can control how this page displays/renders. By default it will try to "guess" what you want; e.g. if you access it in Chrome, it will display this page but if you fetch via Curl, you'll get raw JSON. The following parameters control this behavior.</p>
<p><i><b>Note:</b> "Enabled" parameter values can be one of <b>y</b>, <b>yes</b>, <b>1</b>, or <b>true</b>. "Disabled" parameter values can be one of <b>n</b>, <b>no</b>, <b>0</b>, or <b>false</b>. The parameter names are case-sensitive but the values are not.</i></p>
<p><ul>
<li><b>json:</b> Force rendering in JSON format
<ul>
<li>It will display it nicely if you're in a browser, otherwise it will return raw/plaintext JSON.</li>
<li>Use <b>raw</b> if you want to force raw plaintext JSON output.</li>
</ul></li>
<li><b>html:</b> Force rendering in HTML</li>
<ul>
<li>It will render HTML in clients that would normally render as JSON (e.g. curl, wget).</li>
</ul></li>
<li><b>raw:</b> Force output into a raw JSON string
<ul>
<li>Pure JSON instead of HTML or formatted JSON. This is suitable for API usages if your client is detected wrongly (or you just want to get the raw JSON).</li>
<li>Overrides all other tags.</li>
<li>Has no effect for clients that would normally render as JSON (curl, wget, etc.).</li>
</ul></li>
<li><b>tabs:</b> Indentation for JSON output
<ul>
<li>Accepts a positive integer.</li>
<li>Default is 4 for "desktop" browsers (if <b>json</b> is enabled), and no indentation otherwise.</li>
</ul></li>
</ul></p>
<h2>Examples</h2>
<p><table>
<tr>
<th>URL</th>
<th>Behavior</th>
</tr>
<tr>
<td><a href="{{ request.base_url }}">{{ request.base_url }}</a></td>
<td>Displays HTML and "Human" formatting if in a graphical browser, otherwise returns a raw, unformatted JSON string.</td>
</tr>
<tr>
<td><a href="{{ request.base_url }}?raw=1">{{ request.base_url }}?raw=1</a></td>
<td>Renders a raw, unformatted JSON string if in a graphical browser, otherwise no effect. All other parameters ignored (if in a graphical browser).</td>
</tr>
<tr>
<td><a href="{{ request.base_url }}?html=1">{{ request.base_url }}?html=1</a></td>
<td>Forces HTML rendering on non-graphical clients.</td>
</tr>
<tr>
<td><a href="{{ request.base_url }}?json=1&tabs=4">{{ request.base_url }}?json=1&tabs=4</a></td>
<td>Returns JSON indented by 4 spaces for each level (you can leave "json=1" off if it's in a non-graphical browser, unless you specified "html=1").</td>
</tr>
</table></p>
{% endblock %}

View File

@ -6,11 +6,37 @@ from app import app
@app.route('/', methods = ['GET']) #@app.route('/')
def index():
# First we define interactive browsers
_intbrowsers = ('camino', 'chrome', 'firefox', 'galeon', 'kmeleon', 'konqueror',
'links', 'lynx')
_intbrowsers = {'camino': ['http://caminobrowser.org/', 'Camino'],
'chrome': ['https://www.google.com/chrome/', 'Google Chrome'],
'firefox': ['https://www.mozilla.org/firefox/', 'Mozilla Firefox'],
'galeon': ['http://galeon.sourceforge.net/', 'Galeon'],
'kmeleon': ['http://kmeleonbrowser.org/', 'K-Meleon'],
'konqueror': ['https://konqueror.org/', 'Konqueror'],
'links': ['http://links.twibright.com/', 'Links'],
'lynx': ['http://lynx.browser.org/', 'Lynx']}
_os = {'aix': ['https://www.ibm.com/power/operating-systems/aix', 'AIX'],
'amiga': ['http://www.amiga.org/', 'Amiga'],
'android': ['https://www.android.com/', 'Android'],
'bsd': ['http://www.bsd.org/', 'BSD'],
'chromec': ['https://www.chromium.org/chromium-os', 'ChromeOS'],
'hpux': ['https://www.hpe.com/us/en/servers/hp-ux.html', 'HP-UX'],
'iphone': ['https://www.apple.com/iphone/', 'iPhone'],
'ipad': ['https://www.apple.com/ipad/', 'iPad'],
'irix': ['https://www.sgi.com/', 'IRIX'],
'linux': ['https://www.kernel.org/', 'GNU/Linux'],
'macos': ['https://www.apple.com/macos/', 'macOS'],
'sco': ['http://www.sco.com/products/unix/', 'SCO'],
'solaris': ['https://www.oracle.com/solaris/', 'Solaris'],
'wii': ['http://wii.com/', 'Wii'],
'windows': ['https://www.microsoft.com/windows/', 'Windows']}
_alts = {'amiga': ' (have you tried <a href="http://aros.sourceforge.net/">AROS</a> yet?)',
'macos': ' (have you tried <a href="https://elementary.io/">ElementaryOS</a> yet?)',
'sgi': ' (have you tried <a href="http://www.maxxinteractive.com">MaXX</a> yet?)',
'windows': ' (have you tried <a href="https://https://reactos.org/">ReactOS</a> yet?)'}
# And then we set some parameter options for less typing later on.
_yes = ('y', 'yes', 'true', '1')
_no = ('y', 'no', 'false', '0')
_yes = ('y', 'yes', 'true', '1', True)
_no = ('y', 'no', 'false', '0', False, 'none')
# http://werkzeug.pocoo.org/docs/0.12/utils/#module-werkzeug.useragents
visitor = {'client': {'str': request.user_agent.string,
'browser': request.user_agent.browser,
'os': request.user_agent.platform,
@ -20,21 +46,50 @@ def index():
'ip': request.remote_addr,
'headers': dict(request.headers)}
# We have to convert these to strings so we can do tuple comparisons on lower()s.
_json = str(request.args.get('json')).lower()
_html = str(request.args.get('html')).lower()
# Handle possibly conflicting options.
# This forces JSON if html=0, and forces HTML if json=0. json= is processed first.
if _json in _no:
_html = '1'
elif _html in _no:
_json = '1'
params = {'json': str(request.args.get('json')).lower(),
'html': str(request.args.get('html')).lower(),
'raw': str(request.args.get('raw')).lower()}
if visitor['client']['browser'] in _intbrowsers.keys():
if params['html'] == 'none':
params['html'] = True
if params['json'] == 'none':
params['json'] = False
elif params['json'] in _yes:
params['json'] = True
for k in params.keys():
if params[k] in _no:
params[k] = False
else:
params[k] = True
# Set the tabs for JSON
try:
_tabs = int(request.args.get('tabs'))
params['tabs'] = int(request.args.get('tabs'))
except (ValueError, TypeError):
_tabs = None
if (visitor['client']['browser'] in _intbrowsers and _json not in _yes) or (_html in _yes):
return(render_template('index.html', visitor = visitor))
if visitor['client']['browser'] in _intbrowsers.keys() or params['html']:
params['tabs'] = 4
else:
params['tabs'] = None
j = json.dumps(visitor, indent = params['tabs'])
if (visitor['client']['browser'] in _intbrowsers.keys() and params['html'] and not params['raw']) or \
(visitor['client']['browser'] not in _intbrowsers.keys() and params['html']):
return(render_template('index.html',
visitor = visitor,
browsers = _intbrowsers,
os = _os,
alts = _alts,
json = j,
params = params))
else:
j = json.dumps(visitor, indent = _tabs)
if visitor['client']['browser'] in _intbrowsers.keys() and not params['raw']:
return(render_template('json.html',
json = j,
params = params))
return(j)

@app.route('/about', methods = ['GET'])
def about():
return(render_template('about.html'))

@app.route('/usage', methods = ['GET'])
def usage():
return(render_template('usage.html'))