mirror of
https://github.com/borgbackup/borg.git
synced 2026-04-23 07:07:52 -04:00
Only allow whitelisted RPC calls in server mode
Without this check, the client is able to call any method of RepositoryServer and Repository, potentially circumventing restrict_to_paths or even run arbitrary code.
This commit is contained in:
parent
4ab4ecc7af
commit
046b196bab
2 changed files with 24 additions and 2 deletions
|
|
@ -22,8 +22,23 @@ class ConnectionClosed(Error):
|
|||
class PathNotAllowed(Error):
|
||||
"""Repository path not allowed"""
|
||||
|
||||
class InvalidRPCMethod(Error):
|
||||
"""RPC method is not valid"""
|
||||
|
||||
class RepositoryServer(object):
|
||||
rpc_methods = (
|
||||
'__len__',
|
||||
'check',
|
||||
'commit',
|
||||
'delete',
|
||||
'get',
|
||||
'list',
|
||||
'negotiate',
|
||||
'open',
|
||||
'put',
|
||||
'repair',
|
||||
'rollback',
|
||||
)
|
||||
|
||||
def __init__(self, restrict_to_paths):
|
||||
self.repository = None
|
||||
|
|
@ -47,6 +62,8 @@ class RepositoryServer(object):
|
|||
for type, msgid, method, args in unpacker:
|
||||
method = method.decode('ascii')
|
||||
try:
|
||||
if not method in self.rpc_methods:
|
||||
raise InvalidRPCMethod(method)
|
||||
try:
|
||||
f = getattr(self, method)
|
||||
except AttributeError:
|
||||
|
|
@ -155,8 +172,10 @@ class RemoteRepository(object):
|
|||
raise IntegrityError(res)
|
||||
elif error == b'PathNotAllowed':
|
||||
raise PathNotAllowed(*res)
|
||||
if error == b'ObjectNotFound':
|
||||
elif error == b'ObjectNotFound':
|
||||
raise Repository.ObjectNotFound(res[0], self.location.orig)
|
||||
elif error == b'InvalidRPCMethod':
|
||||
raise InvalidRPCMethod(*res)
|
||||
raise self.RPCError(error)
|
||||
else:
|
||||
yield res
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import tempfile
|
|||
from attic.testsuite.mock import patch
|
||||
from attic.hashindex import NSIndex
|
||||
from attic.helpers import Location, IntegrityError, UpgradableLock
|
||||
from attic.remote import RemoteRepository
|
||||
from attic.remote import RemoteRepository, InvalidRPCMethod
|
||||
from attic.repository import Repository
|
||||
from attic.testsuite import AtticTestCase
|
||||
|
||||
|
|
@ -319,6 +319,9 @@ class RemoteRepositoryTestCase(RepositoryTestCase):
|
|||
def open(self, create=False):
|
||||
return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), create=create)
|
||||
|
||||
def test_invalid_rpc(self):
|
||||
self.assert_raises(InvalidRPCMethod, lambda: self.repository.call('__init__', None))
|
||||
|
||||
|
||||
class RemoteRepositoryCheckTestCase(RepositoryCheckTestCase):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue