SHARE
TWEET

Untitled

a guest Aug 10th, 2016 12,930 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Teamspeak 3 RCE advisory by:
  2. ff214370685e536b9ee021c7ff6b7680bfbe6008bc29f87511b6b90256043536
  3. August 10, 2016
  4.  
  5.  
  6. While auditing the Teamspeak 3 server I've discovered several 0-day
  7. vulnerabilities which I'll describe in detail in this advisory. They exist in
  8. the newest version of the server, version 3.0.13.
  9.  
  10. I found 10 vulnerabilities. Some of these are critical and allow remote code
  11. execution. For the average user, that means that these vulnerabilities can be
  12. exploited by a malicious attacker in order to take over any Teamspeak server,
  13. not only becoming serveradmin, but getting a shell on the affected machine.
  14.  
  15. Here's the output of an exploit which uses two of the vulnerabilities:
  16.  
  17.     $ python exploit_teamspeak.py
  18.     leaking distinct stack pointers
  19.      '\xa2'  '\x9a'  '\x8a' . '_' .. '\xa0'
  20.     got a ptr: 0x7fa29a8a5fa0
  21.      '\xa2'  '\x9a'  '\x9a'  'o' ... '\xa0'
  22.     got a ptr: 0x7fa29a9a6fa0
  23.      '\xa2'  '\x9a'  '\xaa' . '\x7f'  '\xa0'
  24.     got a ptr: 0x7fa29aaa7fa0
  25.     stack ptr: 0x7fa29a8a5fa0
  26.     assumed stack base: 0x7fa29a5a5000
  27.     sleeping a bit to avoid flood detection.......
  28.     initializing stack sprayers............
  29.     spraying the stacks............
  30.     doing some magic.....
  31.  
  32.     Got a shell from ('127.0.0.1', 38416)
  33.     ts3@ts3:/home/ts3/teamspeak3-server$
  34.  
  35.  
  36. I won't release the exploit anytime soon, but I will note that writing one is
  37. a great learning experience.
  38.  
  39.  
  40. Next I'll describe my findings. I'll be referring to function names. The
  41. Teamspeak developers strip their binaries of symbols, but they messed up once
  42. and forgot to do so.
  43.  
  44. If you want to follow along at home, I'm sure your favorite search engine can
  45. help you find the non-stripped server binary.
  46.  
  47. Now on to the vulns!
  48.  
  49.  
  50. --- vuln 1: race condition leading to use-after-free ---
  51.  
  52. The ts3 server is threaded. When accessing objects like a Client or a Channel,
  53. which can be shared among threads, it's necessary to hold a mutex. However the
  54. function VirtualServerBase::sendCommandLowPacket drops its mutex before
  55. accessing a Client object. Here's the vulnerable code:
  56.  
  57.     0x49d26d:
  58.     call    _pthread_mutex_unlock
  59.     mov     rdi, client
  60.  
  61.     ; this will mov rax, [rdi+0F0h]
  62.     call    Client::getTransmissionReceiveBase(void)
  63.  
  64.     mov     rcx, [rax]
  65.     mov     rdx, [rbx+VirtualServer.vsb.vserv_id]
  66.     mov     rdi, rax
  67.     mov     rsi, r14
  68.     call    qword ptr [rcx+58h]
  69.  
  70. As we can see, the mutex is unlocked and then a TransmissionReceiveBase struct
  71. is taken out of the Client. Then its vtable is used for a call. Looking at
  72. the kernel source we see that, at least on Linux, _pthread_mutex_unlock will
  73. swap out the current thread if there's another thread blocked waiting for the
  74. mutex.
  75.  
  76. This other thread could then free the Client and place controlled data on top
  77. of the freed block. When the first thread runs again, we control the
  78. TransmissionReceiveBase object completely. The indirect call through its
  79. vtable allows us to get $pc.
  80.  
  81. This is one of the vulnerabilities used in the exploit above.
  82.  
  83.  
  84. --- vuln 2: disclosure of a partially uninitialized stack buffer ---
  85.  
  86. When a client first connects to the server, it sends over an IV. The IV is
  87. base64-encoded. The server decodes it in VirtualServerBase::clientInitIV.
  88. However the server ignores the return value of Crypt::decodeBase64 which is
  89. the decoded length. Instead it assumes that the length is always 10 bytes.
  90.  
  91. If the client only encodes e.g. 9 bytes and sends them over, one byte of the
  92. IV will be uninitialized. The client can guess this byte. Only a correct guess
  93. will prevent later cryptographic operations from failing. Thus the client can
  94. deduce the byte. It can repeat the process, sending over only 8 bytes, etc.
  95. This lets us do a byte-at-a-time leak from the stack.
  96.  
  97. Specifically it lets us leak a stack pointer, beating ASLR. This was used in
  98. the exploit above.
  99.  
  100.  
  101. --- vuln 3: disclosure of heap memory ---
  102.  
  103. The ts3 server compresses command packets with the "qlz" library. However a
  104. known vulnerability resides in one of the older versions of this library.
  105. This was already fixed in the newest qlz release (a beta release). However the
  106. ts3 server uses an older version of this library.
  107.  
  108. The vulnerability is described here:
  109.  
  110.     http://blog.frama-c.com/index.php?post/2011/04/05/QuickLZ-1
  111.  
  112. But it's straightforward to find for anyone looking at qlz's source code. You
  113. don't need any fancy "software analyzer" to find it, like in that silly blog
  114. post.
  115.  
  116. The vulnerability is qlz-specific and essentially allows you to "decompress"
  117. data, but much of the decompressed data is actually uninitialized.
  118.  
  119. Why is this a problem for the ts3 server? Because we can send a short
  120. compressed command packet over which starts with "some_command return_code=".
  121. When we use this vuln and the packet is decompressed, the following bytes will
  122. be included in the packet. So the packet that ts3 sees is "some_command
  123. return_code=<bytes from the heap>".
  124.  
  125. Since the return_code parameter is reflected back to us, this lets us leak
  126. data from the heap.
  127.  
  128.  
  129. -----
  130.  
  131. Those three vulnerabilities were the critical ones. Below I'll briefly
  132. describe some minor ones, resulting in DoS or more interesting things.
  133.  
  134.  
  135.  
  136.  
  137. --- vuln 4: check if any file exists on the server ---
  138.  
  139. The function VirtualServer::getpermission_fileTransferInitDownload accepts a
  140. path from the client and gives different error messages depending on whether
  141. the file exists or not.
  142.  
  143. For example using "/../../../etc/passwd" gives "bad path" while
  144. "/../../../etc/passwz" gives "no such file". This can be used to determine the
  145. remote OS and installed software, enumerate open fds, etc.
  146.  
  147.  
  148. --- vulns 5, 6, 7, 8: race conditions galore ---
  149.  
  150. The function PermissionManager::getChannelGroupInherited looks up and uses a
  151. Channel struct without holding any mutex. The channel is only used to look up
  152. a channelid, so this is an infoleak/DoS at best.
  153.  
  154. In the function VirtualServer::sendRemoteDebuggingInfo we look up a Client
  155. struct, then drop the mutex, and then we proceed to use the Client to look up
  156. its uuid. Again this is an infoleak/DoS at best.
  157.  
  158. In ServerParser::cmd_permget we look up a Client without holding any mutex.
  159.  
  160. In ServerParser::cmd_clientsetserverquerylogin we do the same.
  161.  
  162.  
  163. --- vuln 9: ParameterParser index-out-of-bounds DoS ---
  164.  
  165. In PacketHandler::inINITPacket_SolvePuzzle we initialize a ParameterParser. It
  166. keeps a vector of parameters. Later, in ServerParser::inPacket, we call
  167. ParameterParser::getParam to get the parameter at index 0. However it's
  168. possible to send just the string " " which will result in the ParameterParser
  169. vector having zero entries. Then this zero-indexing will go out of bounds.
  170.  
  171. This is unfortunately a DoS at best since the retrieved parameter is just
  172. compared against "clientinitiv", which isn't terribly useful.
  173.  
  174.  
  175. --- vuln 10: double clientinit DoS ---
  176.  
  177. If we run the "clientinit" command twice, the server crashes with a failed
  178. assertion.
  179.  
  180.  
  181.  
  182.  
  183.  
  184. Q&A:
  185.  
  186. Q: What can normal users do?
  187. A: Wait for the Teamspeak developers to patch the vulnerabilities, then download
  188.    a new version of the server. Exploiting these vulns to get RCE is quite
  189.    tricky and it's unlikely that anyone will manage to create a working
  190.    exploit before a patch is released.
  191.  
  192. Q: How did you find these?
  193. A: Lots of staring at disassembly.
  194.  
  195. Q: Why not do coordinated disclosure?
  196. A: The Teamspeak developers censor their forums and sweep vulnerabilities
  197.    under the rug as "crashes". I am not comfortable with that. Furthermore I
  198.    fear legal action from them.
  199.  
  200. Q: Does this mean that Teamspeak is totally insecure? Should users move to
  201.    other VoIP software?
  202. A: Any complex piece of software has vulnerabilities. I would guess that
  203.    similar things could be found in Mumble/Ventrilo/etc., if enough time were
  204.    devoted to it.
  205.    
  206.  
  207.  
  208. Advisory by:
  209. ff214370685e536b9ee021c7ff6b7680bfbe6008bc29f87511b6b90256043536
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top