Commit b05787fb authored by Damian Johnson's avatar Damian Johnson
Browse files

Checking the auth cookie's size before reading

Adding a check that the authentication cookie is 32 bytes before sending its
contents to the control port. This is to prevent a malicious socket from
tricking us into reading them arbitrary file content. Tested by hardcoding an
alternative file as being the cookie and confirming that this makes arm abort
initialization. Caught by rransom.

https://trac.torproject.org/projects/tor/ticket/4305
parent 1f347f33
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -550,6 +550,10 @@ class TorManager:
    
    if authType == TorCtl.AUTH_TYPE.COOKIE:
      try:
        authCookieSize = os.path.getsize(authValue)
        if authCookieSize != 32:
          raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (authValue, authCookieSize))
        
        torctlConn.authenticate(authValue)
        torTools.getConn().init(torctlConn)
      except Exception, exc:
+10 −0
Original line number Diff line number Diff line
@@ -146,6 +146,12 @@ class HeaderPanel(panel.Panel, threading.Thread):
        cli.popups.showMsg("Unable to reconnect (socket '%s' doesn't exist)" % self._config["startup.interface.socket"], 3)
      
      if not torctlConn and allowPortConnection:
        # TODO: This has diverged from starter.py's connection, for instance it
        # doesn't account for relative cookie paths or multiple authentication
        # methods. We can't use the starter.py's connection function directly
        # due to password prompts, but we could certainly make this mess more
        # manageable.
        
        try:
          ctlAddr, ctlPort = self._config["startup.interface.ipAddress"], self._config["startup.interface.port"]
          tmpConn, authType, authValue = TorCtl.TorCtl.preauth_connect(ctlAddr, ctlPort)
@@ -153,6 +159,10 @@ class HeaderPanel(panel.Panel, threading.Thread):
          if authType == TorCtl.TorCtl.AUTH_TYPE.PASSWORD:
            authValue = cli.popups.inputPrompt("Controller Password: ")
            if not authValue: raise IOError() # cancel reconnection
          elif authType == TorCtl.TorCtl.AUTH_TYPE.COOKIE:
            authCookieSize = os.path.getsize(authValue)
            if authCookieSize != 32:
              raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (authValue, authCookieSize))
          
          tmpConn.authenticate(authValue)
          torctlConn = tmpConn
+13 −0
Original line number Diff line number Diff line
@@ -244,6 +244,19 @@ def _torCtlConnect(controlAddr="127.0.0.1", controlPort=9051, passphrase=None, i
        
        conn._cookiePath = os.path.join(pathPrefix, pathSuffix)
      
      # Abort if the file isn't 32 bytes long. This is to avoid exposing
      # arbitrary file content to the port.
      #
      # Without this a malicious socket could, for instance, claim that
      # '~/.bash_history' or '~/.ssh/id_rsa' was its authentication cookie to
      # trick us into reading it for them with our current permissions.
      #
      # https://trac.torproject.org/projects/tor/ticket/4305
      
      authCookieSize = os.path.getsize(conn._cookiePath)
      if authCookieSize != 32:
        raise IOError("authentication cookie '%s' is the wrong size (%i bytes instead of 32)" % (conn._cookiePath, authCookieSize))
    
    conn.authenticate(authValue)
    return conn
  except Exception, exc: