fix: Application import deserialization vulnerability #2604 (#2633)

This commit is contained in:
shaohuzhang1 2025-03-20 12:10:06 +08:00 committed by GitHub
parent 5baa141b89
commit f19ad24907
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 3 deletions

View File

@ -39,7 +39,7 @@ from common.exception.app_exception import AppApiException, NotFound404, AppUnau
from common.field.common import UploadedImageField, UploadedFileField from common.field.common import UploadedImageField, UploadedFileField
from common.models.db_model_manage import DBModelManage from common.models.db_model_manage import DBModelManage
from common.response import result from common.response import result
from common.util.common import valid_license, password_encrypt from common.util.common import valid_license, password_encrypt, restricted_loads
from common.util.field_message import ErrMessage from common.util.field_message import ErrMessage
from common.util.file_util import get_file_content from common.util.file_util import get_file_content
from dataset.models import DataSet, Document, Image from dataset.models import DataSet, Document, Image
@ -60,6 +60,7 @@ chat_cache = cache.caches['chat_cache']
class MKInstance: class MKInstance:
def __init__(self, application: dict, function_lib_list: List[dict], version: str): def __init__(self, application: dict, function_lib_list: List[dict], version: str):
self.application = application self.application = application
self.function_lib_list = function_lib_list self.function_lib_list = function_lib_list
@ -727,7 +728,7 @@ class ApplicationSerializer(serializers.Serializer):
user_id = self.data.get('user_id') user_id = self.data.get('user_id')
mk_instance_bytes = self.data.get('file').read() mk_instance_bytes = self.data.get('file').read()
try: try:
mk_instance = pickle.loads(mk_instance_bytes) mk_instance = restricted_loads(mk_instance_bytes)
except Exception as e: except Exception as e:
raise AppApiException(1001, _("Unsupported file format")) raise AppApiException(1001, _("Unsupported file format"))
application = mk_instance.application application = mk_instance.application
@ -813,7 +814,7 @@ class ApplicationSerializer(serializers.Serializer):
return FunctionLibSerializer.Query( return FunctionLibSerializer.Query(
data={'user_id': application.user_id, 'is_active': True, data={'user_id': application.user_id, 'is_active': True,
'function_type': FunctionType.PUBLIC} 'function_type': FunctionType.PUBLIC}
).list(with_valid=True) ).list(with_valid=True)
def get_function_lib(self, function_lib_id, with_valid=True): def get_function_lib(self, function_lib_id, with_valid=True):
if with_valid: if with_valid:

View File

@ -10,6 +10,7 @@ import hashlib
import importlib import importlib
import io import io
import mimetypes import mimetypes
import pickle
import re import re
import shutil import shutil
from functools import reduce from functools import reduce
@ -23,6 +24,30 @@ from pydub import AudioSegment
from ..exception.app_exception import AppApiException from ..exception.app_exception import AppApiException
from ..models.db_model_manage import DBModelManage from ..models.db_model_manage import DBModelManage
safe_builtins = {
'MKInstance'
}
ALLOWED_CLASSES = {
("builtins", "dict"),
('uuid', 'UUID'),
("application.serializers.application_serializers", "MKInstance")
}
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if (module, name) in ALLOWED_CLASSES:
return super().find_class(module, name)
raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
(module, name))
def restricted_loads(s):
"""Helper function analogous to pickle.loads()."""
return RestrictedUnpickler(io.BytesIO(s)).load()
def encryption(message: str): def encryption(message: str):
""" """