mirror of
https://github.com/dobin/avred
synced 2026-06-08 13:54:13 +00:00
feature: auth for webapp
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -11,6 +11,5 @@
|
||||
<li><a href="/file/{{filename}}">{{filename}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
@@ -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
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"server":
|
||||
{
|
||||
"amsi": "http://192.168.88.127:8001/"
|
||||
}
|
||||
"amsi": "http://192.168.88.127:8001/",
|
||||
},
|
||||
"password": ""
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user