michael orlitzky

CVE-2024-34490: Maxima unsafe /tmp usage

posted 2024-05-06

Product
Maxima computer algebra system
Versions affected
5.47.0 and earlier
Published on
2024-05-06
Fixed in
commit 51704ccb
Bug report
https://sourceforge.net/p/maxima/bugs/3755/
MITRE
CVE-2024-34490

Summary

The plotting facilities in Maxima (up to and including v5.47.0) use predictable paths under /tmp that lead to some well-known vulnerabilities. Among other things, an attacker on the same machine may be able to overwrite files that belong to the Maxima user, or inject malicious PostScript into his plots.

Details

The temporary directory used by Maxima is determined in src/init-cl.lisp and, on UNIX systems, will typically be /tmp:

(defun default-tempdir ()
  (maxima-parse-dirstring
    (let
      ((tmpdir-windows (maxima-getenv "TEMP"))
      (tmpdir-posix (maxima-getenv "TMPDIR"))
      (tmpdir-nonstandard1 (maxima-getenv "TMP"))
      (tmpdir-nonstandard2 (maxima-getenv "TEMPDIR")))

      (cond
        ((and tmpdir-windows (string/= tmpdir-windows ""))
          tmpdir-windows)
        ((and tmpdir-posix (string/= tmpdir-windows ""))
          tmpdir-posix)
        ((and tmpdir-nonstandard1 (string/= tmpdir-nonstandard1 ""))
          tmpdir-nonstandard1)
        ((and tmpdir-nonstandard2 (string/= tmpdir-nonstandard2 ""))
          tmpdir-nonstandard2)
        ; A fallback for windows if everything else has failed
        ((string= *autoconf-windows* "true") "C:\\Windows\\temp")
        ; A fallback for the rest of the operating systems
        (t "/tmp")
))))

Prior to commit 51704ccb, several plotting functions use predictable paths within this temporary directory. For example in src/gnuplot_def.lisp we see,

(eq (getf plot-options :gnuplot_term) '$ps)
...
 (if (getf plot-options :gnuplot_out_file)
     (setq out-file (getf plot-options :gnuplot_out_file))
     (setq out-file "maxplot.ps")))

This sets the output filename to maxplot.ps. It is eventually concatenated onto Maxima's temporary directory in src/plot.lisp. When that temporary directory is /tmp, the end result is that an unsafe, predictable, world-writable path is used for the plot:

(%i1) plot2d(sin(x),[x,0,2*%pi],[gnuplot_term,ps]);
...
(%o1)            [/tmp/maxout25041.gnuplot, /tmp/maxplot.ps]

The exploits available to a local attacker in this scenario are well-known. In addition, the example above lets the attacker inject malicious PostScript into the user's plot. PostScript is a Turing-complete language, so that is not an awesome situation.

Resolution

Commit 51704ccb adds randomness to the temporary file names, making them near-impossible to guess. This solution isn't perfect because there exist further corner cases handled by, say, mkstemp. But adding the randomness is a huge improvement and likely the best return on investment given that Maxima is implemented in common lisp, which does not have mkstemp or anything like it.