{"action":"opened","issue":{"url":"https://api.github.com/repos/jborg/attic/issues/316","labels_url":"https://api.github.com/repos/jborg/attic/issues/316/labels{/name}","comments_url":"https://api.github.com/repos/jborg/attic/issues/316/comments","events_url":"https://api.github.com/repos/jborg/attic/issues/316/events","html_url":"https://github.com/jborg/attic/issues/316","id":83968963,"number":316,"title":"`attic serve` implementation is not secure enough","user":{"login":"trou","id":1587988,"avatar_url":"https://avatars.githubusercontent.com/u/1587988?v=3","gravatar_id":"","url":"https://api.github.com/users/trou","html_url":"https://github.com/trou","followers_url":"https://api.github.com/users/trou/followers","following_url":"https://api.github.com/users/trou/following{/other_user}","gists_url":"https://api.github.com/users/trou/gists{/gist_id}","starred_url":"https://api.github.com/users/trou/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trou/subscriptions","organizations_url":"https://api.github.com/users/trou/orgs","repos_url":"https://api.github.com/users/trou/repos","events_url":"https://api.github.com/users/trou/events{/privacy}","received_events_url":"https://api.github.com/users/trou/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-06-02T10:56:59Z","updated_at":"2015-06-02T10:56:59Z","closed_at":null,"body":"Hello,\r\nthe way `attic serve` currently works is a bit insecure, particularly if https://github.com/jborg/attic/pull/277 is taken into account. In particular, `--restrict-to-path` can be easily bypassed.\r\n\r\nThe problem lies in `remote.py`:\r\n```python\r\n        unpacker = msgpack.Unpacker(use_list=False)\r\n        while True:\r\n            r, w, es = select.select([stdin_fd], [], [], 10)\r\n            if r:\r\n                data = os.read(stdin_fd, BUFSIZE)\r\n                if not data:\r\n                    return\r\n                unpacker.feed(data)\r\n                for type, msgid, method, args in unpacker:\r\n                    method = method.decode('ascii')\r\n                    try:\r\n                        try:\r\n                            f = getattr(self, method)\r\n                        except AttributeError:\r\n                            f = getattr(self.repository, method)\r\n                        res = f(*args)\r\n                    except Exception as e:\r\n                        os.write(stdout_fd, msgpack.packb((1, msgid, e.__class__.__name__, e.args)))\r\n                    else:\r\n                        os.write(stdout_fd, msgpack.packb((1, msgid, None, res)))\r\n            if es:\r\n                return\r\n```\r\nIf we consider an attacker who can access a remote SSH with `attic server --restrict-to-path` as forced command, he can send msgpack'd data to call arbitrary methods on both `RepositoryServer` and `Repository` objects, *including Python's object builtin methods*.\r\n\r\nWhile arbitrary Python code execution is not straightforward (because strings are actually unpacked as byte strings), it is way too permissive as one can pass arbitrary arguments to all methods.\r\n\r\nA potential fix would be whitelisting the allowed methods and parameters."}}