summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorAAGaming <aa@mail.catvibers.me>2022-08-05 21:16:29 -0400
committerAAGaming <aa@mail.catvibers.me>2022-08-05 21:16:29 -0400
commitf21d34506d0fd09d5849fcee552447cdfbf4802f (patch)
treefa7475021d12d54f5edb74489b9ecf81a16bd639 /backend
parentab6ec981604a32611d972ede634abe7ccd19b0d2 (diff)
downloaddecky-loader-f21d34506d0fd09d5849fcee552447cdfbf4802f.tar.gz
decky-loader-f21d34506d0fd09d5849fcee552447cdfbf4802f.zip
Implement CSRF protection
Diffstat (limited to 'backend')
-rw-r--r--backend/helpers.py15
-rw-r--r--backend/legacy/library.js8
-rw-r--r--backend/main.py11
3 files changed, 30 insertions, 4 deletions
diff --git a/backend/helpers.py b/backend/helpers.py
index a75f1075..e8c2ce5b 100644
--- a/backend/helpers.py
+++ b/backend/helpers.py
@@ -1,7 +1,20 @@
+from aiohttp.web import middleware, Response
import ssl
import certifi
+import uuid
ssl_ctx = ssl.create_default_context(cafile=certifi.where())
+csrf_token = str(uuid.uuid4())
+
def get_ssl_context():
- return ssl_ctx \ No newline at end of file
+ return ssl_ctx
+
+def get_csrf_token():
+ return csrf_token
+
+@middleware
+async def csrf_middleware(request, handler):
+ if str(request.method) == "OPTIONS" or request.headers.get('Authentication') == csrf_token or str(request.rel_url) == "/auth/token" or str(request.rel_url).startswith("/plugins/load_main/") or str(request.rel_url).startswith("/static/") or str(request.rel_url).startswith("/legacy/") or str(request.rel_url).startswith("/steam_resource/"):
+ return await handler(request)
+ return Response(text='Forbidden', status='403') \ No newline at end of file
diff --git a/backend/legacy/library.js b/backend/legacy/library.js
index f9dfe699..17f4e46f 100644
--- a/backend/legacy/library.js
+++ b/backend/legacy/library.js
@@ -8,10 +8,13 @@ window.addEventListener("message", function(evt) {
}, false);
async function call_server_method(method_name, arg_object={}) {
+ const token = await fetch("http://127.0.0.1:1337/auth/token").then(r => r.text());
const response = await fetch(`http://127.0.0.1:1337/methods/${method_name}`, {
method: 'POST',
+ credentials: "include",
headers: {
'Content-Type': 'application/json',
+ Authentication: token
},
body: JSON.stringify(arg_object),
});
@@ -40,10 +43,13 @@ async function fetch_nocors(url, request={}) {
async function call_plugin_method(method_name, arg_object={}) {
if (plugin_name == undefined)
throw new Error("Plugin methods can only be called from inside plugins (duh)");
+ const token = await fetch("http://127.0.0.1:1337/auth/token").then(r => r.text());
const response = await fetch(`http://127.0.0.1:1337/plugins/${plugin_name}/methods/${method_name}`, {
method: 'POST',
+ credentials: "include",
headers: {
- 'Content-Type': 'application/json',
+ 'Content-Type': 'application/json',
+ Authentication: token
},
body: JSON.stringify({
args: arg_object,
diff --git a/backend/main.py b/backend/main.py
index b52180ab..02cc0d56 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -20,12 +20,13 @@ from os import path
from subprocess import call
import aiohttp_cors
-from aiohttp.web import Application, run_app, static
+from aiohttp.web import Application, run_app, static, get, Response
from aiohttp_jinja2 import setup as jinja_setup
from browser import PluginBrowser
from injector import inject_to_tab, tab_has_global_var
from loader import Loader
+from helpers import csrf_middleware, get_csrf_token
from utilities import Utilities
from updater import Updater
@@ -41,9 +42,10 @@ class PluginManager:
def __init__(self) -> None:
self.loop = get_event_loop()
self.web_app = Application()
+ self.web_app.middlewares.append(csrf_middleware)
self.cors = aiohttp_cors.setup(self.web_app, defaults={
"https://steamloopback.host": aiohttp_cors.ResourceOptions(expose_headers="*",
- allow_headers="*")
+ allow_headers="*", allow_credentials=True)
})
self.plugin_loader = Loader(self.web_app, CONFIG["plugin_path"], self.loop, CONFIG["live_reload"])
self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.web_app, self.plugin_loader.plugins)
@@ -57,6 +59,8 @@ class PluginManager:
self.loop.create_task(self.loader_reinjector())
self.loop.create_task(self.load_plugins())
self.loop.set_exception_handler(self.exception_handler)
+ self.web_app.add_routes([get("/auth/token", self.get_auth_token)])
+
for route in list(self.web_app.router.routes()):
self.cors.add(route)
self.web_app.add_routes([static("/static", path.join(path.dirname(__file__), 'static'))])
@@ -67,6 +71,9 @@ class PluginManager:
return
loop.default_exception_handler(context)
+ async def get_auth_token(self, request):
+ return Response(text=get_csrf_token())
+
async def wait_for_server(self):
async with ClientSession() as web:
while True: