feature: auth for webapp

This commit is contained in:
2023-05-28 15:55:33 +02:00
parent fdde7b4fed
commit 0e8eaa3cbb
10 changed files with 152 additions and 23 deletions
+4 -1
View File
@@ -128,9 +128,12 @@ $ ./avred.py --file test.ps1 --server amsi
As a web server:
```sh
$ python3 avred-web.py --listenip 127.0.0.1 --listenport 8080
$ python3 avredweb.py --listenip 127.0.0.1 --listenport 8080
```
For login, use username "admin" and password configured in `config.json` in key `password`.
From command line:
```sh
$ python3 avred.py --server amsi --file malware/evil.exe
+4 -1
View File
@@ -15,10 +15,13 @@
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="nav-link {{ 'active' if request.path == '/' else '' }}" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link {{ 'active' if request.path == '/upload' else '' }}" href="/upload">Upload</a></li>
{% if 'localhost' in request.host_url %}
{% if current_user.is_authenticated %}
<li class="nav-item"><a class="nav-link {{ 'active' if request.path == '/files_results' else '' }}" href="/files_results">Files</a></li>
{% endif %}
<li class="nav-item"><a class="nav-link {{ 'active' if request.path.startswith('/examples') else ''}}" href="/examples">Examples</a></li>
{% if not current_user.is_authenticated %}
<li class="nav-item"><a class="nav-link {{ 'active' if request.path == '/login' else '' }}" href="/login">Login</a></li>
{% endif %}
</ul>
</div>
</div>
-1
View File
@@ -11,6 +11,5 @@
<li><a href="/file/{{filename}}">{{filename}}</a></li>
{% endfor %}
</ul>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
{% include 'includes/header.html' %}
</head>
<body>
{% include 'includes/navigation.html' %}
<h1>Login</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flash-messages">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form method="POST" action="{{ url_for('views_auth.login') }}">
<div>
<label for="username">Username</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<input type="submit" value="Log In">
</div>
</form>
</body>
</html>
+4 -10
View File
@@ -8,6 +8,7 @@ import requests
import sys
import zipfile
import logging
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, login_manager
from model.model import *
#from waitress import serve
@@ -25,10 +26,8 @@ def index():
@views.route("/files")
@login_required
def files():
if not current_app.config['LIST_FILES']:
return render_template('index.html')
examples = get_filepaths(current_app.config['UPLOAD_FOLDER'], EXT_INFO)
res = []
for example in examples:
@@ -38,10 +37,8 @@ def files():
@views.route("/files_results")
@login_required
def files_results():
if not current_app.config['LIST_FILES']:
return render_template('index.html')
filepaths = get_filepaths(current_app.config['UPLOAD_FOLDER'], EXT_INFO)
outcomes = []
for filepath in filepaths:
@@ -70,9 +67,8 @@ def file(filename):
@views.route("/file/<filename>/download")
@login_required
def fileDownload(filename):
if not current_app.config['DOWNLOAD_FILES']:
return render_template('index.html')
filename = secure_filename(filename)
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
return send_file(filepath, as_attachment=True)
@@ -111,8 +107,6 @@ def examples_list():
@views.route("/example/<filename>/download")
def fileDownloadExample(filename):
if not current_app.config['DOWNLOAD_FILES']:
return render_template('index.html')
filename = secure_filename(filename)
filepath = os.path.join(current_app.config['EXAMPLE_FOLDER'], filename)
return send_file(filepath, as_attachment=True)
+41
View File
@@ -0,0 +1,41 @@
from flask import Blueprint, current_app, flash, request, redirect, url_for, render_template
from werkzeug.utils import secure_filename
import os
import random
import subprocess
import pickle
import requests
import sys
import zipfile
import logging
import psutil
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required
views_auth = Blueprint('views_auth', __name__)
login_manager = LoginManager()
class User(UserMixin):
def __init__(self, username, password):
self.id = 1 # Assuming a single user, so ID is hardcoded
self.username = username
self.password = password
@login_manager.user_loader
def load_user(user_id):
if user_id == '1':
return User('admin', 'password')
@views_auth.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = load_user('1')
if user and user.password == password:
login_user(user)
return redirect('/')
return render_template('login.html')
+9 -5
View File
@@ -7,6 +7,9 @@ from flask import Flask
from config import Config
from app.views import views
from app.views_upload import views_upload
from app.views_auth import views_auth, login_manager
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required
if __name__ == "__main__":
@@ -14,8 +17,6 @@ if __name__ == "__main__":
parser.add_argument('--listenip', type=str, help='IP to listen on', default="0.0.0.0")
parser.add_argument('--listenport', type=int, help='Port to listen on', default=5000)
parser.add_argument('--debug', action='store_true', help='Debug', default=False)
parser.add_argument('--disable-listfiles', action='store_true', help='Disable List Files', default=False)
parser.add_argument('--disable-downloadfiles', action='store_true', help='Disable Download Files', default=False)
args = parser.parse_args()
config = Config()
@@ -35,17 +36,20 @@ if __name__ == "__main__":
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['AVRED_SERVERS'] = config.get('server')
app.config['PASSWORD'] = config.get('password')
app.config['AVRED_SCANNER'] = os.path.join(root_folder, 'avred.py')
app.config['ALLOWED_EXTENSIONS'] = { 'exe', 'dll', 'ps1', 'docm', 'bin', 'lnk' }
app.config['LIST_FILES'] = not args.disable_listfiles
app.config['DOWNLOAD_FILES'] = not args.disable_downloadfiles
app.config.from_prefixed_env()
for key in ('UPLOAD_FOLDER', 'EXAMPLE_FOLDER', 'ALLOWED_EXTENSIONS', 'LIST_FILES'):
for key in ('UPLOAD_FOLDER', 'EXAMPLE_FOLDER', 'ALLOWED_EXTENSIONS',):
print("{}: {}".format(key, app.config[key]))
print("")
app.register_blueprint(views)
app.register_blueprint(views_upload)
app.register_blueprint(views_auth)
login_manager.init_app(app)
app.run(host=args.listenip, port=args.listenport, debug=args.debug)
+3 -2
View File
@@ -1,6 +1,7 @@
{
"server":
{
"amsi": "http://192.168.88.127:8001/"
}
"amsi": "http://192.168.88.127:8001/",
},
"password": ""
}
+4 -1
View File
@@ -12,4 +12,7 @@ class Config(object):
self.data = json.load(jsonfile)
def get(self, value):
return self.data[value]
if value in self.data:
return self.data[value]
else:
return ""
+50 -2
View File
@@ -1,6 +1,47 @@
# Analysis results
* long scans
* detected, but no matches
broken:
* mimikatz
very long, in examples/broken.bin/:
* 072877b961e31e8792a296c63b9c7b56.bin -> ok, hash based
* 15FC009D9CAAA8F11D6C3DA2B69EA06E.bin -> incremental. header?
* 91FC9D1B635FDEE4E56AEC32688A0E6C.bin -> incremental, header, sections are fucked
bad hash based detection?
https://avred.r00ted.ch/example/286f7b377f5d0ca3505ed1ba6601c947.bin
* why doesnt it find anything? detected by amsi, but no matches
* same with: SharpHound!
what about self extracting rar archives?
* 091457444b7e7899c242c5125ddc0571.bin
-> do not scan for now
----------------------------------------------
fucked endlessly:
[INFO ][2023/02/13 18:20][avred.py: 70] main() :: Using file: app/examples/075df4723073ff08cd3e90d2b1f11722.bin
* rubeus: only match 0 triggers? why.. (no .data)
https://avred.yookiterm.ch/file/685805936d8744225f8c11965202de8e.bin
* good example with two (independant?) sections: code/data
https://avred.yookiterm.ch/file/100cf902ac31766f7d8a521eeb6f8d68.bin
* last two work, but conclusion does not show it
good signatures:
* https://avred.yookiterm.ch/file/03db29c71b0031af08081f5e2f7dcdf2.bin
* msf/test3 does never end, and needs --isolate?
## Sharphound
@@ -53,4 +94,11 @@ Seems defender somehow realized it is malicious again!
solution:
Just ignore .text...
--------------------
some PE files have zero detections?
* 070ef82a0bded089b6f996a392ca7b9a.bin
* 05a02e08cce99d3821574d8612f757fd.bin
-> fixed, recheck
-> fixed