Package: lbreakout2
Severity: grave
Tags: security patch
Justification: user security hole

[ Details are sparse about this one, if you come to the conclusion that
  this is not RC, then please lower severity, but I assume it is. ]
[ Woody might be affected as well, I haven't checked that yet ]

>From the 2.6beta changelog:
- security issue fixed: bad sprintf/scanf calls could lead to crashes
  or potential security problems (05/02/14 U.H.)
 
There is no further information and upstream's website is very sparse
and there's no mailing list or anything like that, so I had a look
at the rather largish diff between 2.5.2 and 2.6beta and reviewed it
for possibly security relevant changes, which you can find attached.

At least a buffer overflow in highscore handling (should be writable by
arbitrary users) and the missing format strings in network multiplayer
handling code seem exploitable as lbreakout runs as setgid games.

Please review the diff and upload a fixed package to t-p-u, if you agree.

Cheers,
        Moritz

-- System Information:
Debian Release: 3.1
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)
Kernel: Linux 2.6.11
Locale: LANG=C, [EMAIL PROTECTED] (charmap=ISO-8859-15)
diff -Naur lbreakout2-2.5.2/client/chart.c lbreakout2-2.6beta/client/chart.c
--- lbreakout2-2.5.2/client/chart.c	2003-05-25 11:37:05.000000000 +0200
+++ lbreakout2-2.5.2/client/chart.c	2005-03-28 20:07:30.000000000 +0200
@@ -138,7 +138,7 @@
 				if ( aux[0] != '>' ) break;
 				chart = calloc( 1, sizeof( Set_Chart ) );
 				/* get name: >>>name */
-				fscanf( file, ">>>%s\n", setname );
+				fscanf( file, ">>>%1023s\n", setname );
 				chart->name = strdup( setname );
 				/* entries */
 				chart_read_entries( file, file_name, chart );
@@ -234,7 +234,7 @@
     /* open file */
     file = fopen( file_name, "w" );
     if ( !file ) {
-        fprintf( stderr, "??? Highscore chart loaded properly but cannot save?\n" );
+        fprintf( stderr, "??? Highscore chart loaded properly but cannot save? (%s)\n",file_name );
         return;
     }
 	/* save all charts */
diff -Naur lbreakout2-2.5.2/client/client_handlers.c lbreakout2-2.6beta/client/client_handlers.c
--- lbreakout2-2.5.2/client/client_handlers.c	2003-06-18 10:46:13.000000000 +0200
+++ lbreakout2-2.5.2/client/client_handlers.c	2005-02-16 22:07:28.000000000 +0100
@@ -146,7 +146,7 @@
 	
 	/* extract ip and port and build a new socket out of it */
 	gui_edit_get_text( edit_server, server, 128, 0, -1 );
-	snprintf( config.server, 64, server );
+	snprintf( config.server, 64, "%s", server );
 	if ( !net_build_addr( &newaddr, server, 0 ) ) {
 		client_printf_chatter( 1, "ERROR: address %s does not resolve", config.server );
 		return;
diff -Naur lbreakout2-2.5.2/client/client_recv.c lbreakout2-2.6beta/client/client_recv.c
--- lbreakout2-2.5.2/client/client_recv.c	2003-05-29 21:05:39.000000000 +0200
+++ lbreakout2-2.5.2/client/client_recv.c	2005-02-16 22:07:32.000000000 +0100
@@ -157,7 +157,7 @@
 			/* users */
 			case MSG_ADD_USER:
 				num = msg_read_int32();
-				snprintf( name, 16, msg_read_string() ); name[15] = 0;
+				snprintf( name, 16, "%s", msg_read_string() ); name[15] = 0;
 				if ( msg_read_failed() ) break;
 				client_add_user( num, name );
 				gui_list_update( 
@@ -223,8 +223,8 @@
 					client_transmit( CODE_BLUE, msglen, msgbuf );
 					break;
 				}
-				snprintf( mp_peer_name, 15, msg_read_string() );
-				snprintf( mp_levelset, 16, msg_read_string() );
+				snprintf( mp_peer_name, 15, "%s", msg_read_string() );
+				snprintf( mp_levelset, 16, "%s", msg_read_string() );
 				mp_diff = msg_read_int8();
 				mp_rounds = msg_read_int8();
 				mp_frags = msg_read_int8();
diff -Naur lbreakout2-2.5.2/client/comm.c lbreakout2-2.6beta/client/comm.c
--- lbreakout2-2.5.2/client/comm.c	2005-01-13 21:02:27.000000000 +0100
+++ lbreakout2-2.5.2/client/comm.c	2005-03-28 16:04:37.000000000 +0200
@@ -237,7 +237,7 @@
 				break;
 			case MSG_ADD_USER:
 				i = msg_read_int32();
-				snprintf( name, 16, msg_read_string() ); name[15] = 0;
+				snprintf( name, 16, "%s", msg_read_string() ); name[15] = 0;
 				if ( msg_read_failed() ) break;
 				client_add_user( i, name );
 				handled = 1;
diff -Naur lbreakout2-2.5.2/client/editor.c lbreakout2-2.6beta/client/editor.c
--- lbreakout2-2.5.2/client/editor.c	2003-05-18 19:22:11.000000000 +0200
+++ lbreakout2-2.5.2/client/editor.c	2005-02-16 22:07:28.000000000 +0100
@@ -639,12 +639,12 @@
     strcpy( str, "" );
     if ( edit_buttons[x][y] == BUTTON_EDIT_AUTHOR )
         if ( enter_string( font, "Author's Name:", str, 24 ) ) {
-            snprintf( edit_cur_level->author, 31, str );
+            snprintf( edit_cur_level->author, 31, "%s", str );
             *full_update = 1;
         }
     if ( edit_buttons[x][y] == BUTTON_EDIT_NAME )
         if ( enter_string( font, "Title:", str, 24 ) ) {
-            snprintf( edit_cur_level->name, 31, str );
+            snprintf( edit_cur_level->name, 31, "%s", str );
             *full_update = 1;
         }
     /* sel frame tile position */
diff -Naur lbreakout2-2.5.2/game/comm.c lbreakout2-2.6beta/game/comm.c
--- lbreakout2-2.5.2/game/comm.c	2005-01-13 20:51:36.000000000 +0100
+++ lbreakout2-2.6beta/game/comm.c	2005-04-08 22:27:44.000000000 +0200
@@ -494,8 +494,8 @@
 {
 	char *ptr = msg + *pos;
 	
-	snprintf( ptr, 16, level->name );  ptr[15] = 0; ptr += 16;
-	snprintf( ptr, 16, level->author); ptr[15] = 0; ptr += 16;
+	snprintf( ptr, 16, "%s", level->name );  ptr[15] = 0; ptr += 16;
+	snprintf( ptr, 16, "%s", level->author); ptr[15] = 0; ptr += 16;
 	memcpy( ptr, level->bricks, 252 ); ptr += 252;
 	memcpy( ptr, level->extras, 252 ); ptr += 252;
 	
@@ -507,8 +507,8 @@
 {
 	char *ptr = msg + *pos;
 	
-	snprintf( level->name, 16, ptr ); ptr += 16;
-	snprintf( level->author, 16, ptr ); ptr += 16;
+	snprintf( level->name, 16, "%s", ptr ); ptr += 16;
+	snprintf( level->author, 16, "%s", ptr ); ptr += 16;
 	memcpy( level->bricks, ptr, 252 ); ptr += 252;
 	memcpy( level->extras, ptr, 252 ); ptr += 252;
 
diff -Naur lbreakout2-2.5.2/game/levels.c lbreakout2-2.6beta/game/levels.c
--- lbreakout2-2.5.2/game/levels.c	2004-09-25 19:41:06.000000000 +0200
+++ lbreakout2-2.5.2/game/levels.c	2005-05-15 13:39:51.000000000 +0200
@@ -74,7 +74,7 @@
 	if ( fname[0] != '/' ) /* keep global pathes */
 		snprintf( path, sizeof(path)-1, "%s/levels/%s", SRC_DIR, fname );
 	else
-		snprintf( path, sizeof(path)-1, fname );
+		snprintf( path, sizeof(path)-1, "%s", fname );
 				
 	if ( ( file = fopen( path, mode ) ) == 0 ) {
 		fprintf( stderr, "couldn't open %s\n", path );
@@ -192,7 +192,7 @@
 	
 	if ( levels->count == 0 ) return 0;
 	set = salloc( 1, sizeof( LevelSet ) );
-	snprintf( set->name, 20, name );
+	snprintf( set->name, 20, "%s", name );
 	set->levels = salloc( levels->count, sizeof( Level* ) );
 	set->count = levels->count;
 	set->version = version;
@@ -344,10 +344,10 @@
 	if ( !strequal( "Level:", buffer ) ) goto failure;
 	/* author */
 	if ( !next_line( file, buffer ) ) goto failure;
-	snprintf( level->author, 31, buffer );
+	snprintf( level->author, 31, "%s", buffer );
 	/* level name */
 	if ( !next_line( file, buffer ) ) goto failure;
-	snprintf( level->name, 31, buffer );
+	snprintf( level->name, 31, "%s", buffer );
 	/* bricks: */
 	if ( !next_line( file, buffer ) ) goto failure;
 	if ( !strequal( "Bricks:", buffer ) ) goto failure;
@@ -389,8 +389,8 @@
 {
     int i, j;
     Level *level = calloc( 1, sizeof( Level ) );
-    snprintf( level->author, 31, author );
-    snprintf( level->name, 31, name );
+    snprintf( level->author, 31, "%s", author );
+    snprintf( level->name, 31, "%s", name );
     /* empty arena */
     for ( i = 0; i < EDIT_WIDTH; i++ )
         for ( j = 0; j < EDIT_HEIGHT; j++ ) {
diff -Naur lbreakout2-2.5.2/gui/gui_edit.c lbreakout2-2.6beta/gui/gui_edit.c
--- lbreakout2-2.5.2/gui/gui_edit.c	2003-06-04 21:15:30.000000000 +0200
+++ lbreakout2-2.5.2/gui/gui_edit.c	2005-02-16 22:07:24.000000000 +0100
@@ -422,7 +422,7 @@
 {
     if ( widget->type != GUI_EDIT ) return;
     /* copy text */
-    snprintf( widget->spec.edit.buffer, widget->spec.edit.size + 1, text );
+    snprintf( widget->spec.edit.buffer, widget->spec.edit.size + 1, "%s", text );
     widget->spec.edit.length = strlen( widget->spec.edit.buffer );
     /* reset */
     /* first character in first line */
@@ -456,7 +456,7 @@
     if ( length > limit )
         length = limit;
     if ( length )
-        snprintf( buffer, limit, widget->spec.edit.buffer );
+        snprintf( buffer, limit, "%s", widget->spec.edit.buffer );
     else
         buffer[0] = 0;
     return 1;

Reply via email to