| @@ -50,9 +50,9 @@ | ||
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | public function insertOne($row){ |
| 53 | 53 | $this->file = fopen($this->filePath, 'a+'); |
| 54 | - fputcsv($this->file, $row, $this->delimiter, $this->enclosure); | |
| 54 | + fputcsv($this->file, array_map([$this, 'sanitizeCell'], $row), $this->delimiter, $this->enclosure); | |
| 55 | 55 | fclose($this->file); |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | public function insertAll($data){ |
| @@ -57,17 +57,35 @@ | ||
| 57 | 57 | |
| 58 | 58 | public function insertAll($data){ |
| 59 | 59 | $this->file = fopen($this->filePath, 'a+'); |
| 60 | 60 | foreach ($data as $row) { |
| 61 | - fputcsv($this->file, $row, $this->delimiter, $this->enclosure); | |
| 61 | + fputcsv($this->file, array_map([$this, 'sanitizeCell'], $row), $this->delimiter, $this->enclosure); | |
| 62 | 62 | } |
| 63 | 63 | fclose($this->file); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | + /** | |
| 67 | + * Neutralize spreadsheet formula injection (CWE-1236) by prefixing an | |
| 68 | + * apostrophe onto any string cell that starts with a character a | |
| 69 | + * spreadsheet application would interpret as the start of a formula. | |
| 70 | + */ | |
| 71 | + public function sanitizeCell($value) | |
| 72 | + { | |
| 73 | + if (!is_string($value) || $value === '') { | |
| 74 | + return $value; | |
| 75 | + } | |
| 76 | + | |
| 77 | + if (preg_match('/^[=+\-@\t\r]/', $value)) { | |
| 78 | + return "'" . $value; | |
| 79 | + } | |
| 80 | + | |
| 81 | + return $value; | |
| 82 | + } | |
| 83 | + | |
| 66 | 84 | public function output($filename) |
| 67 | 85 | { |
| 68 | 86 | if (!is_null($filename) && file_exists($this->filePath)) { |
| 69 | - $filename = filter_var($filename, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); | |
| 87 | + $filename = preg_replace('/[\x00-\x1F]/', '', sanitize_file_name($filename)); | |
| 70 | 88 | header('Cache-control: private'); |
| 71 | 89 | header('Content-Type: application/octet-stream'); |
| 72 | 90 | header('Content-Length: '.filesize($this->filePath)); |
| 73 | 91 | header('Content-Disposition: filename='.$filename); |