Hello,

I wanted to report a potentially exploitable issue within the cmd_pgnload()
and cmd_pgnreplay() functions in cmd.cc. In the loop between lines 482-485
in the former function, a specially crafted epdline could overrun the data
buffer located here:

char data[MAXSTR]="";
char epdline[MAXSTR]="";

/* snip */

int i=0;


*while ( epdline[i] != '\n' ) {  data[i+9] = epdline[i];  ++i;*
*}*

Since this loop only ends when there is a newline within epdline, the end
of the data buffer is not checked and the program will continue to copy
bytes into and past the buffer, eventually overwriting the return address
on the stack. A PGN file that exploits this bug is potentially possible,
but it is easier to reproduce this in gdb by setting a breakpoint on the
load_pgn_as_epd() function. Then load any compliant file with the pgnload
command as follows:

pgnload *<filename>*

If you step after the SaveEPD() call but before the temporary file
".tmp.epd" is opened with fopen(), you can write to (or replace) the
temporary file with a buffer overflow payload, like two hundred of "A".
Continuing the program will cause it to open and copy this into the 128
byte data buffer, overflowing it and overwriting the return address, as
well as any stack cookie or other data in the way. This code is mirrored in
the cmd_pgnreplay() function also, and can be mitigated in the same way. It
should be reproducible there using the same steps.

I have attached a patch to this email with a potential fix to this issue. I
hope this finds you well.

Regards,

Michael Vaughan
--- /tmp/cmd.cc	2021-04-04 23:20:06.720388661 -0400
+++ cmd.cc	2021-04-04 23:14:35.095359251 -0400
@@ -480,8 +480,13 @@
   strcpy( data, "setboard " );
   int i=0;
   while ( epdline[i] != '\n' ) {
-    data[i+9] = epdline[i];
-    ++i;
+    if ((i + 9) < MAXSTR - 1) {
+        data[i+9] = epdline[i];
+        ++i;
+    } else {
+        printf(_("Error reading contents of file '%s'.\n"), token[1]);
+        break;
+    }
   }
   data[i+9] = '\0';
   SetDataToEngine( data );
@@ -504,8 +509,13 @@
   strcpy( data, "setboard " );
   int i=0;
   while ( epdline[i] != '\n' ) {
-    data[i+9] = epdline[i];
-    ++i;
+    if ((i + 9) < MAXSTR - 1) {
+        data[i+9] = epdline[i];
+        ++i;
+    } else {
+        printf(_("Error reading contents of file '%s'.\n"), token[1]);
+        break;
+    }
   }
   data[i+9] = '\0';
 

Reply via email to