home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / sshd_redirect.txt < prev    next >
Encoding:
Text File  |  2001-11-06  |  8.3 KB  |  245 lines

  1.  
  2. I hope this hasn't been posted before, but I think it hasn't, it concerns
  3. a bug in ssh/sshd, allowing non-root to redirect priviliged ports on, at
  4. least, Linux, Solaris and SunOS.
  5.  
  6. I've informed my ISP's sysadmin of the LocalForward problem
  7. (if you missed it, adding a line like
  8.  
  9.         LocalForward 80 remotehost:80
  10.  
  11. to your $HOME/.ssh/config will forward a priviliged port to a remote port,
  12. whithout needing root).
  13.  
  14. Anyway, he fixed it, and I showed him the bug still works when using
  15. 2^16 + 80 (ie. 16 bit wrap). Make sure that if you decide not to remove
  16. the suid-root bit like my sysadmin, but patch ssh itself, not to make this
  17. mistake.
  18.  
  19. Ok, he also fixed this problem, but then I got the idea to hack sshd using the
  20. same trick!
  21.  
  22. On host1, you open an ssh connection to a machine running sshd where you
  23. have a working account using -R (RemoteForward, which is somewhat the opposite
  24. of LocalForward, but behaves the same in this case) like this:
  25.  
  26. host1$ ssh -R 65621:host1.com:80 victim.com
  27. ivo's passord:
  28. victim$
  29.  
  30. (in this case, 65621 is equal to 2^16+85, i.e. port 85, the other ports
  31. were in use (by previous attempts :).
  32.  
  33. And sshd on victim.com will hapilly forward priviliged port victim.com:85
  34. to host1.com:80!
  35.  
  36. Some remarks:
  37.  
  38. - This could also be considered a bug in bind(), because it doesn't wrap
  39.   portnumbers > 65536, but still, it makes sshd vurnerable, at least on Linux
  40.   (2.0.29), Solaris 2.4 and SunOs 4.1.4
  41.  
  42. - People who patched ssh or removed the suid-bit are still vurnerable, because
  43.   this is a bug in sshd, not ssh
  44.  
  45. - You need to login on victim.com before sshd will redirect the port.
  46.  
  47.  
  48.  
  49. ===================================================================================
  50.  
  51.  
  52. Two bugs are present, the first one does'nt check the config file for
  53. privelged ports _at_all_ (a check is done when given on the command line),
  54. the second one doesnt check for ports over 65535 which will wrap around.
  55. This problem is that ssh/sshd uses an int instead of an unsigned short to do
  56. the comparison on. So wrapping doesnt occur till its placed in the struct
  57. sockaddr_in.
  58.  
  59. I've included patches (I'm not the author of ssh so these are completely
  60. unoffical), hoping anyone would point out anything I might of missed
  61. out, and ofcourse for people to use as a temporary fix till the author
  62. releases one.
  63.  
  64. These are against 1.2.17
  65.  
  66. -- cut here
  67.  
  68. Common subdirectories: ssh-1.2.17/gmp-2.0.2-ssh-2 and ssh-fixed-1.2.17/gmp-2.0.2-ssh-2
  69. diff -c ssh-1.2.17/newchannels.c ssh-fixed-1.2.17/newchannels.c
  70. *** ssh-1.2.17/newchannels.c    Wed Oct 30 04:27:54 1996
  71. --- ssh-fixed-1.2.17/newchannels.c      Sat Aug 23 14:19:29 1997
  72. ***************
  73. *** 1247,1252 ****
  74. --- 1247,1256 ----
  75.  
  76.     /* Check that an unprivileged user is not trying to forward a privileged
  77.        port. */
  78. +
  79. +   if (port > 65535)
  80. +     packet_disconnect("Requested port is %d is invalid",port);
  81. +
  82.     if (port < 1024 && !is_root)
  83.       packet_disconnect("Requested forwarding of port %d but user is not root.",
  84.                       port);
  85. diff -c ssh-1.2.17/readconf.c ssh-fixed-1.2.17/readconf.c
  86. *** ssh-1.2.17/readconf.c       Wed Oct 30 04:27:53 1996
  87. --- ssh-fixed-1.2.17/readconf.c Sat Aug 23 14:29:08 1997
  88. ***************
  89. *** 389,394 ****
  90. --- 389,400 ----
  91.         fatal("%.200s line %d: Badly formatted port number.",
  92.               filename, linenum);
  93.         fwd_port = atoi(cp);
  94. +
  95. +       if(fwd_port < 1024 && original_real_uid)
  96. +       fatal("Port %d may only be forwarded by root.",fwd_port);
  97. +       if(fwd_port > 65535)
  98. +       fatal("Port %d is illegal",fwd_port);
  99. +
  100.         cp = strtok(NULL, WHITESPACE);
  101.         if (!cp)
  102.         fatal("%.200s line %d: Missing second argument.",
  103. ***************
  104. *** 408,413 ****
  105. --- 414,425 ----
  106.         fatal("%.200s line %d: Badly formatted port number.",
  107.               filename, linenum);
  108.         fwd_port = atoi(cp);
  109. +
  110. +       if(fwd_port < 1024 && original_real_uid)
  111. +       fatal("Port %d may only be forwarded by root.",fwd_port);
  112. +       if(fwd_port > 65535)
  113. +       fatal("Port %d is illegal",fwd_port);
  114. +
  115.         cp = strtok(NULL, WHITESPACE);
  116.         if (!cp)
  117.         fatal("%.200s line %d: Missing second argument.",
  118. diff -c ssh-1.2.17/ssh.c ssh-fixed-1.2.17/ssh.c
  119. *** ssh-1.2.17/ssh.c    Wed Oct 30 04:27:54 1996
  120. --- ssh-fixed-1.2.17/ssh.c      Sat Aug 23 14:18:59 1997
  121. ***************
  122. *** 483,488 ****
  123. --- 483,499 ----
  124.               usage();
  125.               /*NOTREACHED*/
  126.             }
  127. +
  128. +         if(fwd_port > 65535)  {
  129. +           fprintf(stderr,"Illegal port specified %d\n",fwd_port);
  130. +           exit(1);
  131. +         }
  132. +         if (fwd_port < 1024 && original_real_uid != 0)  {
  133. +           fprintf(stderr,
  134. +                   "Privileged ports can only be forwarded by root.\n");
  135. +           exit(1);
  136. +         }
  137. +
  138.           add_remote_forward(&options, fwd_port, buf, fwd_host_port);
  139.           break;
  140.  
  141. ***************
  142. *** 496,503 ****
  143.             }
  144.           if (fwd_port < 1024 && original_real_uid != 0)
  145.             {
  146. !             fprintf(stderr,
  147. !                     "Privileged ports can only be forwarded by root.\n");
  148.               exit(1);
  149.             }
  150.           add_local_forward(&options, fwd_port, buf, fwd_host_port);
  151. --- 507,517 ----
  152.             }
  153.           if (fwd_port < 1024 && original_real_uid != 0)
  154.             {
  155. !             if(fwd_port > 65535)
  156. !               fprintf(stderr,"Ilegal port specified %d\n",fwd_port);
  157. !             else
  158. !               fprintf(stderr,
  159. !                       "Privileged ports can only be forwarded by root.\n");
  160.               exit(1);
  161.             }
  162.           add_local_forward(&options, fwd_port, buf, fwd_host_port);
  163. Common subdirectories: ssh-1.2.17/zlib-1.0.3 and ssh-fixed-1.2.17/zlib-1.0.3
  164.  
  165. -- cut here
  166.  
  167.  
  168. ===================================================================================
  169.  
  170.  
  171.  
  172. We have an instance of "root process unnecessarily running under
  173. control of user".
  174.  
  175. > On host1, you open an ssh connection to a machine running sshd where
  176. > you have a working account using -R (RemoteForward, which is
  177. > somewhat the opposite of LocalForward, but behaves the same in this
  178. > case) like this:
  179. > host1$ ssh -R 65621:host1.com:80 victim.com
  180. > (in this case, 65621 is equal to 2^16+85, i.e. port 85, the other ports
  181.  
  182. Some weeks ago I reported as a bug that sshd runs the port forwarder
  183. as root, breaking identd queries. This exploit shows that it can lead
  184. to even nastier problems.
  185.  
  186. I assume the main reason why sshd doesn't switch UIDs right after
  187. authentication is the pty chown problem. But couldn't this be done by
  188. the main sshd daemon using some sort of command channel to its
  189. children? Then the first child sshd could run as user and avoid this
  190. sort of problems.
  191.  
  192. > - This could also be considered a bug in bind(), because it doesn't wrap
  193. >   portnumbers > 65536, but still, it makes sshd vurnerable, at least on Linux
  194. >   (2.0.29), Solaris 2.4 and SunOs 4.1.4
  195.  
  196. No. bind(2) (and connect(2)) is called with a struct sockaddr_in as
  197. argument, and this struct contains the port number as a 16-bit value
  198. sin_port somewhere. The "wrapping" happens when the assignment to this
  199. variable truncates the value to 16 bits.
  200.  
  201. I think (not tried) this particular bug can be fixed like this:
  202.  
  203. --- newchannels.c~
  204. +++ newchannels.c
  205. @@ -1397,4 +1397,5 @@
  206.    /* Get arguments from the packet. */
  207.    port = packet_get_int();
  208. +  port &= 0xFFFF;
  209.    hostname = packet_get_string(NULL);
  210.    host_port = packet_get_int();
  211.  
  212. but the real underlying cause is that sshd does too much as root,
  213. IMHO. Wonder what more problems of this kind could come up.
  214.  
  215.  
  216.  
  217. ===================================================================================
  218.  
  219.  
  220. > - This could also be considered a bug in bind(), because it doesn't wrap
  221. >   portnumbers > 65536, but still, it makes sshd vurnerable, at least on Linux
  222. >   (2.0.29), Solaris 2.4 and SunOs 4.1.4
  223.  
  224. Actually, the port number passed to bind() is a 16-bit quantity
  225. (the sin_port member of a struct sockaddr_in).
  226.  
  227. The fix would be to compare nthos(foo.sin_port) with IPPORT_RESERVED.
  228.  
  229.  
  230. ===================================================================================
  231.  
  232.  
  233.  
  234. > This problem is that ssh/sshd uses an int instead of an unsigned short to do
  235. > the comparison on. So wrapping doesnt occur till its placed in the struct
  236. > sockaddr_in.
  237.  
  238. It looks like (from reading it, not from running it) the patch will
  239. consider negative port numbers to be "privileged" rather than
  240. "invalid", thus yielding the incorrect massage.  This is, of course, a
  241. cosmetic problem rather than a functional one.
  242.  
  243.  
  244.  
  245.