#1994·bisheng

Bisheng 中的两个关键路径穿越漏洞

作者: Ro1ME创建于 2026年4月20日更新于 2026年4月20日

Location: src/backend/bisheng/core/cache/utils.py:290-349 Entry Point: src/backend/bisheng/api/v1/workstation.py:177 (knowledgeUpload endpoint) CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) CVSS 3.1: 9.1 (Critical)

Vulnerable Code

python
@create_cache_folder
def save_download_file(file_input: Union[bytes, BinaryIO], folder_name: str, filename: str) -> str:
    """
    Synchronous I/O intensive tasks:
    Write data stream to a temporary file
    Simultaneously calculate SHA256
    Rename a file based on the hash
    """
    
    # Convert to stream objects
    if isinstance(file_input, bytes):
        src_stream = BytesIO(file_input)
    else:
        src_stream = file_input
        if hasattr(src_stream, 'seek'):
            src_stream.seek(0)
    
    # Prepare a temporary file
    cache_path = Path(CACHE_DIR)
    folder_path = cache_path / folder_name
    
    # Create the folder if it doesn't exist
    if not folder_path.exists():
        folder_path.mkdir(exist_ok=True)
    
    temp_filename = f"tmp_{uuid4().hex}"
    temp_file_path = folder_path / temp_filename
    
    sha256_hash = hashlib.sha256()
    
    try:
        # Write to temporary file and calculate SHA256 simultaneously
        with open(temp_file_path, 'wb') as dst_file:
            chunk_size = 65536  # 64KB
            while True:
                chunk = src_stream.read(chunk_size)
                if not chunk:
                    break
                sha256_hash.update(chunk)
                dst_file.write(chunk)
        
        # calculate final hash
        file_hash = sha256_hash.hexdigest()
        
        # Logic for handling filename length limits
        safe_filename = filename
        if len(filename) > 60:
            safe_filename = filename[-60:]  # VULNERABILITY: Takes last 60 chars, preserves path traversal
        
        final_file_name = f'{file_hash}_{safe_filename}'  # VULNERABILITY: No path validation
        final_file_path = folder_path / final_file_name  # Path traversal possible here
        
        # Rename (Move) Temporary File to Final Path
        if final_file_path.exists():
            os.remove(temp_file_path)
            return str(final_file_path)
        
        shutil.move(str(temp_file_path), str(final_file_path))  # VULNERABILITY: Moves to traversed path
        return str(final_file_path)

内容来源: dataelement/bisheng