Package: obexpushd
Version: 0.4-3
Severity: grave
Tags: security, patch
Justification: user security hole
Hi,
I forward this to Debian to take necessary steps.
I also attach the patch that fixes this issue. Note that this is exploitable
with any mobile device by just naming a file to exploit this like:
;some command
or
`some command`
Steps taken to prevent this:
Use
'%s'
instead of only
%s
and replace all ' with _
The option to use scriptable output is not used by default.
This should take care of all such attacks. If you have further suggestion or
still see problems, please contact me.
Thanks
HS
-- System Information:
Debian Release: testing/unstable
APT prefers testing
APT policy: (500, 'testing')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18.1
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
diff -Nurp obexpushd-0.4/src/obexpushd.c obexpushd-0.4_fixed/src/obexpushd.c
--- obexpushd-0.4/src/obexpushd.c 2006-10-25 10:30:30.000000000 +0200
+++ obexpushd-0.4_fixed/src/obexpushd.c 2006-11-06 12:38:28.343845590 +0100
@@ -263,37 +263,71 @@ int create_file (obex_t* handle, int mod
}
}
+int put_close (obex_t* handle) {
+ struct file_data_t* data = OBEX_GetUserData(handle);
+ if (script) {
+ if (pclose(data->out) < 0)
+ return -errno;
+ } else {
+ if (fclose(data->out) == EOF)
+ return -errno;
+ }
+ return 0;
+}
+
int put_open (obex_t* handle) {
+ int err = 0;
struct file_data_t* data = OBEX_GetUserData(handle);
+
+ if (data->out)
+ err = put_close(handle);
+ if (err < 0)
+ return err;
if (script && strlen(script)) {
uint8_t* name = utf16to8(data->name);
+ char* type = (type? strdup(data->type): NULL);
char* cmd;
if (name) {
+ size_t i;
size_t size = strlen(script)+1;
- size += 1+utf8len(name);
- if (data->type)
- size += 1+strlen(data->type);
+ size += 3+utf8len(name);
+ if (type)
+ size += 3+strlen(type);
cmd = malloc(size);
- if (!cmd)
+ if (!cmd) {
+ free(name);
+ free(type);
return -ENOMEM;
+ }
memset(cmd,0,size);
- sprintf(cmd, "%s %s %s",script, name, (data->type? data->type: ""));
+
+ /* clean name and type against attacks:
+ * replace ' with _
+ */
+ for (i=0; i < utf8len(name); ++i)
+ if (name[i] == '\'')
+ name[i] = '_';
+ if (!type) {
+ (void)snprintf(cmd, size, "%s '%s'", script, (char*)name);
+ } else {
+ for (i=0; i < strlen(type); ++i)
+ if (type[i] == '\'')
+ type[i] = '_';
+ (void)snprintf(cmd, size, "%s '%s' '%s'", script, (char*)name,type);
+ }
} else {
cmd = strdup(script);
}
errno = 0;
data->out = popen(cmd,"w");
+ if (!data->out)
+ err = (errno? -errno: -ENOMEM);
free(cmd);
- if (!data->out) {
- if (errno == 0)
- return -ENOMEM;
- else
- return -errno;
- }
- return 0;
+ free(name);
+ free(type);
} else {
int status = create_file(handle,O_WRONLY);
@@ -311,9 +345,8 @@ int put_open (obex_t* handle) {
if (data->type && strlen(data->type))
if (debug) printf("%u: file type: %s\n",data->id,data->type);
if (debug) printf("%u: total expected size: %zu byte(s)\n",data->id,data->length);
-
- return 0;
}
+ return err;
}
int put_write (obex_t* handle, const uint8_t* buf, int len) {
@@ -330,18 +363,6 @@ int put_write (obex_t* handle, const uin
return 0;
}
-int put_close (obex_t* handle) {
- struct file_data_t* data = OBEX_GetUserData(handle);
- if (script) {
- if (pclose(data->out) < 0)
- return -errno;
- } else {
- if (fclose(data->out) == EOF)
- return -errno;
- }
- return 0;
-}
-
void obex_object_headers (obex_t* handle, obex_object_t* obj) {
uint8_t id = 0;
obex_headerdata_t value;