security: restrict backup file upload (#1522)

This commit is contained in:
Hayden 2022-08-02 12:53:58 -08:00 committed by GitHub
parent 6649ccf224
commit 11478134a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 2 deletions

View File

@ -72,13 +72,24 @@ class AdminBackupController(BaseAdminController):
@router.post("/upload", response_model=SuccessResponse) @router.post("/upload", response_model=SuccessResponse)
def upload_one(self, archive: UploadFile = File(...)): def upload_one(self, archive: UploadFile = File(...)):
"""Upload a .zip File to later be imported into Mealie""" """Upload a .zip File to later be imported into Mealie"""
if "." not in archive.filename:
raise HTTPException(status.HTTP_400_BAD_REQUEST)
if archive.filename.split(".")[-1] != "zip":
raise HTTPException(status.HTTP_400_BAD_REQUEST)
name = Path(archive.filename).stem
app_dirs = get_app_dirs() app_dirs = get_app_dirs()
dest = app_dirs.BACKUP_DIR.joinpath(archive.filename) dest = app_dirs.BACKUP_DIR.joinpath(f"{name}.zip")
if dest.absolute().parent != app_dirs.BACKUP_DIR:
raise HTTPException(status.HTTP_400_BAD_REQUEST)
with dest.open("wb") as buffer: with dest.open("wb") as buffer:
shutil.copyfileobj(archive.file, buffer) shutil.copyfileobj(archive.file, buffer)
if not dest.is_file: if not dest.is_file():
raise HTTPException(status.HTTP_400_BAD_REQUEST) raise HTTPException(status.HTTP_400_BAD_REQUEST)
@router.post("/{file_name}/restore", response_model=SuccessResponse) @router.post("/{file_name}/restore", response_model=SuccessResponse)

View File

@ -0,0 +1,25 @@
from fastapi.testclient import TestClient
from mealie.core.config import get_app_dirs
from tests import data
from tests.utils.fixture_schemas import TestUser
def test_recipe_asset_exploit(api_client: TestClient, admin_user: TestUser):
dirs = get_app_dirs()
file_payload = {
"archive": ("../test.txt", data.images_test_image_1.read_bytes()),
}
response = api_client.post(
"/api/admin/backups/upload",
files=file_payload,
headers=admin_user.token,
)
assert response.status_code == 400
# Ensure File was not created
assert not (dirs.BACKUP_DIR / "test.txt").exists()
assert not (dirs.BACKUP_DIR.parent / "test.txt").exists()