Making The Avatar Crash Clients (in-progress)

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
This is our latest goal, we have to get it done --- we will basically be pro-status as soon as we can walk in any server and when ANYONE clicks us, they go down.
We all know that https://bugreports.qt.io/secure/attachment/46674/BBF7096DCAF1CD03DE8364E14DB58939.BMP causes the TeamSpeak 3 client to crash. This currently is due to the fact that TeamSpeak 3 is still running QT version 5.4.1. If they simply updated to 5.4.2 (why may happen soon) this vulnerability is out the window, never to be extremely funny --- how it should be.

Code:
.bmp
.cur
.dds
.gif
.icns
.ico
.jp2
.jpeg
.jpg
.mng
.pbm
.pgm
.png
.ppm
.tga
.tif
.tiff
.wbmp
.webp
.xbm
.xpm

These are the file types that TeamSpeak 3 currently supports for an avatar.
Overview
--------

The builtin BMP decoder in QtGui prior to Qt 5.5 contained a bug that would
lead to a divsion by zero when loading certain corrupt BMP files. This in
turn
would cause the application loading these hand crafted BMPs to crash.

Details
-------

It is possible to construct BMP files such that when calculating the masks
required to extract the colour components a division by zero occurred.

Impact
------

An application loading the malicious BMP file will crash.

Workaround
----------

None
Our primary target is going to be the Qt5Gui.dll, which among other things is responsible for rendering the BMP images in the client.

tDXyENp.png

Image courtesy of Kaptan647
I have already tried to force the corrupt BMP file as my avatar server-side, it resulted in this for viewers:
K851WSX.png


To elaborate on the process of what I did, I connected to my SSH (TS3 server). Went into the TS3 directory, cd ./files/virtualserver_1/internal --- from there I used wget to fetch the BMP file (corrupt qt image). Then I copied my avatar's file name, removed the file and renamed the corrupt BMP to the avatar file name. In theory, this should make people load the corrupt BMP and crash them. The results came back failing.

The research is ongoing, feel free to join.
 
Last edited:

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
I have already tried to force the corrupt BMP file as my avatar server-side, it resulted in this for viewers:
K851WSX.png


To elaborate on the process of what I did, I connected to my SSH (TS3 server). Went into the TS3 directory, cd ./files/virtualserver_1/internal --- from there I used wget to fetch the BMP file (corrupt qt image). Then I copied my avatar's file name, removed the file and renamed the corrupt BMP to the avatar file name. In theory, this should make people load the corrupt BMP and crash them. The results came back failing.
I'm almost sure you messed up something here x)
The way the avatars works is just so strange anyway.
You need to mess with md5 as the filename IIRC.
I also strongly suggest you do your experiments on a linux box as it will show you a bit more debug on the console.
 

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
That may be the case, it is a very simple thing to test --- why don't you try to trigger a crash on Linux? :p
I performed that test on a Ubuntu server by the way. I did not do anything with MD5 nor file names, I do not understand why they would md5sum an avatar file --- makes almost no sense (for security purposes). If someone can change the image files on your TeamSpeak 3 server without authorization, you have bigger problems.
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
It's how the client check if the avatar is correct or if it has changed (caching and stuff).
Right now i can't do much as I'm on holidays :p
You can also try to set your avatar with yaqta, I got it to work one day x)
 

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
I believe the md5 has more to do with a combination of the uploaded file name and a time-stamp. I do not believe the md5 name given to the file(s) is for security reasons. I will do a test with a valid image file, then we will know if it works --- if someone sees the 2nd image, we know. I will probably do that test tomorrow though, because I have stayed up way too late haha. ;)
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
I believe the md5 has more to do with a combination of the uploaded file name and a time-stamp. I do not believe the md5 name given to the file(s) is for security reasons.
Nah, i don't see any security that needs to applied to an avatar :p
 

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
hcVTtgR.png

My test did work, however rather than display an invalid file image --- it is showing a numbered avatar. The difference? The file I chose was not the crash BMP file. So, what exactly does this mean? There is some sort of check whether it is server-side or client-side to see whether the image being loaded from an avatar is a valid image (most likely client-side). This is fucking weird, because images in an avatar have better security than all other images. While the actual image did not load, we now do know that there is a difference between a detected invalid image and a valid replacement image. This is not good for us. Due to this, it would be almost impossible to abuse the avatar to crash people, unless we found a crazy workaround to bypass the image validity check. :eek:

Code:
8/11/2015 10:55:27    ClientUI    Warning    Error, avatar md5 does not match. Cannot display image.a81abba4195f89ebf4cf05150661cf7d <-> 1ace95219b41e1ae3ba1a221ebf9e514

Apparently there is an md5sum on the image(s) used as avatars --- that is pathetic, very stupid. That seriously makes no sense in my opinion. Why are avatars treated more securely than anything else in TeamSpeak 3? :D
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
I still think you messed something up x)
Those numbered icons are placeholders that appears when the selected img/icon could not be found.
 

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
Code:
8/11/2015 11:13:32    ClientUI    Warning    Error, avatar md5 does not match. Cannot display image.48f47179449cc12dc322bc394e59a3b9 <-> 36945a5d100af870c4e81c35329243b0
8/11/2015 11:15:50    ClientUI    Warning    Error, avatar md5 does not match. Cannot display image.900d02b72650955526ecbcc1950a9a88 <-> 36945a5d100af870c4e81c35329243b0
What the hell --- this shit is weird, I am going to try to make this work. I am assuming something in the database has to be edited for that user's md5sum avatar to match.

AMeSwq8.png


Time for the ultimate test... HOLY FUCKING SHIT DUDE, IT WORKS HAHAHAHAHAHAHAHAAAAHHAHAHAAHHA I LOVE YOU --- I just made a funny demonstration video.
 
Last edited:

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
Of course it works :D
Video set to private until we have something made up for the VIP section to use. ;)

How I was able to execute this Proof of Concept (PoC):
1. Get the TeamSpeak 3 server downloaded and installed on your local machine --- launch it.
2. Get http://sqlitebrowser.org/ installed.
3. Connect to your TeamSpeak 3 server using the TeamSpeak 3 client.
4. Upload a valid bitmap image of your choice as an avatar (this is done over port 30033).
5. Navigate to "teamspeak3-server_win32/files/virtualserver_1/internal".
6. Get the MD5 hash of your current avatar, keep this somewhere you can access.
7. Open "teamspeak3-server_win32/ts3server.sqlitedb" using SQLiteBrowser.
8. In the database look for data containing the name "client_flag_avatar", make sure the MD5 matches the one you kept.
9. Update the column information with the MD5 of the corrupt BMP that causes a crash. You will probably need to close the server process for the changes to work.
10. Replace the avatar_a1wd6a1d6d156d0ad32 blah blah file inside of "teamspeak3-server_win32/files/virtualserver_1/internal" with the corrupt BMP, but keep the same file name ("avatar_******"). :cool:
Yeah, this was fun --- I hope you have fun if you try this haha. I will probably make a video of how to setup this PoC later, if someone wants to make a better text tutorial --- go ahead, I will not be offended lol.
 
Last edited:

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
Setting the corrupt BMP as your avatar METHODS:

1. Maybe it would be possible to modify the way in which Qt5Gui.dll works by making it believe the invalid/corrupt BMP file is indeed valid.
2. Decryption of the protocol would be nice, then we could potentially check out how an image is set at the protocol level, from there we could do the same thing with the corrupt BMP binary.
3. A plugin in the TeamSpeak 3 client or potentially hooking the client in some way. Manipulating the way in which the TeamSpeak 3 client operates to force it to send the request to the server to set the corrupt BMP file.

;) Can anyone think of another way?
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
The plugin way seems totally possible. I'm gonna try to come up with something :)
 

Asphyxia

Owner
Administrator
Apr 25, 2015
1,844
2
2,197
327
The plugin way seems totally possible. I'm gonna try to come up with something :)
I barely looked into the plugin method. I am focusing more on the protocol method, #2. I noticed though that there was mentioning on the TeamSpeak 3 forum saying it was not possible to set an avatar with a plugin, supposedly it is not even possible with the SDK, with the SDK you can supposedly downloading avatar images --- but someone claimed uploading is not a possibility with a plugin nor SDK. I am not saying don't try, because that person could be wrong or maybe they just could not figure it out.. but I REALLY hope you can figure it out, that would be amazing. I am going to keep trying to work on the protocol method. ;)
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
I tried but as always there's a huge lack of doc. sendfile and requestdeletefile are not documented. So it's hit and miss right now x)
Code:
unsigned int sendFile(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* file, int overwrite, int resume, const char* sourceDirectory, anyID* result, const char* returnCode);



ts3Functions.sendFile(serverConnectionHandlerID, 0, NULL, "filename", 1, 0, "sourcedirectory", &onresult, "simpleonreturncode");
 

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,028
896
216
Could you please share the command sent when requesting to upload an avatar ?

something like "ftinitupload clientftfid=3 name=\/avatar cid=0 cpw= size=1926 overwrite=1 resume=0" i believe.
 
Last edited:

Bluscream

Retired Staff
Contributor
May 8, 2015
967
934
211
Code:
ftinitupload clientftfid=2 name=\/avatar cid=0 cpw= size=11864 overwrite=1 resume=0

clientftfid=2 serverftfid=10541 ftkey=\/QNqv4\/PcTog6cqzAKklymukW\/mWZSgD port=30033 ip=xx.xxx.xxx.xxx, seekpos=0

error id=0 msg=ok

clientupdate client_flag_avatar=6a565dc9a809fa5988bd5653d4a7ea35

error id=0 msg=ok

TIP: You can start yatqa.exe with the parameter "-debug" to get a log file.
 

Bluscream

Retired Staff
Contributor
May 8, 2015
967
934
211
Code:
    /* Filetransfer */
    unsigned int (*getTransferFileName)(anyID transferID, char** result);
    unsigned int (*getTransferFilePath)(anyID transferID, char** result);
    unsigned int (*getTransferFileSize)(anyID transferID, uint64* result);
    unsigned int (*getTransferFileSizeDone)(anyID transferID, uint64* result);
    unsigned int (*isTransferSender)(anyID transferID, int* result);  /* 1 == upload, 0 == download */
    unsigned int (*getTransferStatus)(anyID transferID, int* result);
    unsigned int (*getCurrentTransferSpeed)(anyID transferID, float* result);
    unsigned int (*getAverageTransferSpeed)(anyID transferID, float* result);
    unsigned int (*getTransferRunTime)(anyID transferID, uint64* result);
    unsigned int (*sendFile)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* file, int overwrite, int resume, const char* sourceDirectory, anyID* result, const char* returnCode);
    unsigned int (*requestFile)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* file, int overwrite, int resume, const char* destinationDirectory, anyID* result, const char* returnCode);
    unsigned int (*haltTransfer)(uint64 serverConnectionHandlerID, anyID transferID, int deleteUnfinishedFile, const char* returnCode);
    unsigned int (*requestFileList)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* path, const char* returnCode);
    unsigned int (*requestFileInfo)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* file, const char* returnCode);
    unsigned int (*requestDeleteFile)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char** file, const char* returnCode);
    unsigned int (*requestCreateDirectory)(uint64 serverConnectionHandlerID, uint64 channelID, const char* channelPW, const char* directoryPath, const char* returnCode);
    unsigned int (*requestRenameFile)(uint64 serverConnectionHandlerID, uint64 fromChannelID, const char* channelPW, uint64 toChannelID, const char* toChannelPW, const char* oldFile, const char* newFile, const char* returnCode);

    /* Client functions */
    unsigned int (*getAvatar)(uint64 scHandlerID, anyID clientID, char* result, size_t maxLen);
Code:
enum FileTransferState {
    FILETRANSFER_INITIALISING = 0,
    FILETRANSFER_ACTIVE,
    FILETRANSFER_FINISHED,
};
enum {
    FileListType_Directory = 0,
    FileListType_File,
};
 
Last edited:
Top