Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-3080: Changeset 2924014 for wp-mail-catcher – WordPress Plugin Repository

The WP Mail Catcher plugin for WordPress is vulnerable to Stored Cross-Site Scripting via an email subject in versions up to, and including, 2.1.2 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVE
#sql#xss#web#js#git#wordpress#php#auth
  • wp-mail-catcher/trunk/WpMailCatcher.php

    r2922550

    r2924014

7

7

Description: Logging your mail will stop you from ever losing your emails again! This fast, lightweight plugin (under 140kb in size!) is also useful for debugging or backing up your messages.

8

8

Author: James Ward

9

 

Version: 2.1.2

 

9

Version: 2.1.3

10

10

Author URI: https://jamesward.io

11

11

Donate link: https://paypal.me/jamesmward
  • wp-mail-catcher/trunk/readme.txt

    r2922550

    r2924014

3

3

Tags: mail logging, email log, email logger, logging, email logging, mail, crm

4

4

Requires at least: 4.7

5

 

Tested up to: 6.2.2

 

5

Tested up to: 6.2.3

6

6

Requires PHP: 7.4

7

 

Stable tag: 2.1.2

 

7

Stable tag: 2.1.3

8

8

License: GNU General Public License v3.0

9

9

License URI: https://raw.githubusercontent.com/JWardee/wp-mail-catcher/master/LICENSE

…

…

 

95

95

\== Changelog ==

96

96

 

97

\= 2.1.3 =

 

98

 

99

\- Fix: Improved HTML email detection

 

100

\- Fix: Improved XSS filtering

 

101

97

102

\= 2.1.2 =

98

103
  • wp-mail-catcher/trunk/src/GeneralHelper.php

    r2922541

    r2924014

28

28

    public static $reviewLink;

29

29

    public static $actionNameSpace;

30

 

    public static $htmlEmailHeader = 'content-type: text/html;';

 

30

    public static $htmlEmailHeader = 'content-type: text/html';

31

31

32

32

    public static function setSettings()

…

…

 

133

133

    }

134

134

135

 

    public static function sanitiseForQuery($value)

 

135

    public static function sanitiseForDbQuery($value)

136

136

    {

137

137

        switch (gettype($value)) {

…

…

 

149

149

    }

150

150

151

 

    public static function sanitiseHtmlspecialchars($input): string

152

 

    {

153

 

        return htmlspecialchars(

154

 

            $input,

155

 

            ENT\_QUOTES | ENT\_SUBSTITUTE | ENT\_HTML401,

156

 

            null,

157

 

            false

158

 

        );

 

151

    private static function getAllowedTags()

 

152

    {

 

153

        $tags = wp\_kses\_allowed\_html('post');

 

154

        $tags\['style'\] = \[\];

 

155

        return $tags;

 

156

    }

 

157

 

158

    public static function filterHtml($value)

 

159

    {

 

160

        return wp\_kses($value, self::getAllowedTags());

159

161

    }

160

162

…

…

 

167

169

        global $wpdb;

168

170

169

 

        $urls = self::sanitiseForQuery($urls);

 

171

        $urls = self::sanitiseForDbQuery($urls);

170

172

171

173

        $sql = "SELECT DISTINCT post\_id
  • wp-mail-catcher/trunk/src/Loggers/BuddyPress.php

    r2920307

    r2924014

45

45

        return \[

46

46

            'time' => time(),

47

 

            'email\_to' => GeneralHelper::arrayToString($tos),

48

 

            'subject' => $bpMail->get\_subject(),

49

 

            'message' => $this->sanitiseInput($bpMail->get\_content()),

 

47

            'email\_to' => GeneralHelper::filterHtml(GeneralHelper::arrayToString($tos)),

 

48

            'subject' => GeneralHelper::filterHtml($bpMail->get\_subject()),

 

49

            'message' => GeneralHelper::filterHtml($bpMail->get\_content()),

50

50

            'backtrace\_segment' => json\_encode($this->getBacktrace('bp\_send\_email')),

51

51

            'status' => 1,
  • wp-mail-catcher/trunk/src/Loggers/LogHelper.php

    r2922541

    r2924014

143

143

    }

144

144

145

 

    protected function sanitiseInput($input): string

146

 

    {

147

 

        return htmlspecialchars(

148

 

            $input,

149

 

            ENT\_QUOTES | ENT\_SUBSTITUTE | ENT\_HTML401,

150

 

            null,

151

 

            false

152

 

        );

153

 

    }

154

 

155

 

    protected function sanitiseAndRemoveScripts($input): string

156

 

    {

157

 

        return preg\_replace(

158

 

            '#<script(.\*?)>(.\*?)</script>#is',

159

 

            '',

160

 

            GeneralHelper::sanitiseHtmlspecialchars($input)

161

 

        );

162

 

    }

163

 

164

145

    /\*\*

165

146

     \* Get the details of the method that originally triggered wp\_mail
  • wp-mail-catcher/trunk/src/Loggers/WpMail.php

    r2922541

    r2924014

43

43

        return \[

44

44

            'time' => time(),

45

 

            'email\_to' => $this->sanitiseInput(GeneralHelper::arrayToString($args\['to'\])),

46

 

            'subject' => $this->sanitiseInput($args\['subject'\]),

47

 

            'message' => $this->sanitiseAndRemoveScripts($args\['message'\]),

 

45

            'email\_to' => GeneralHelper::filterHtml(GeneralHelper::arrayToString($args\['to'\])),

 

46

            'subject' => GeneralHelper::filterHtml($args\['subject'\]),

 

47

            'message' => GeneralHelper::filterHtml($args\['message'\]),

48

48

            'backtrace\_segment' => json\_encode($this->getBacktrace()),

49

49

            'status' => 1,
  • wp-mail-catcher/trunk/src/MailAdminTable.php

    r2922541

    r2924014

30

30

31

31

        return self::$instance;

 

32

    }

 

33

 

34

    private function runHtmlSpecialChars($value)

 

35

    {

 

36

        $value = GeneralHelper::filterHtml($value);

 

37

 

38

        return htmlspecialchars(

 

39

            $value,

 

40

            ENT\_QUOTES | ENT\_SUBSTITUTE | ENT\_HTML401,

 

41

            null,

 

42

            false

 

43

        );

32

44

    }

33

45

…

…

 

59

71

60

72

            $subjectDecoded = base64\_decode($subjectEncoded);

61

 

            $subjectDecoded = GeneralHelper::sanitiseHtmlspecialchars($subjectDecoded);

 

73

            $subjectDecoded = $this->runHtmlSpecialChars($subjectDecoded);

 

74

62

75

            return '<span class="asci-help" data-hover-message="' . \_\_("This subject was base64 decoded") . '">

63

76

                        <a href="' . $this->asciSubjectHelpLink . '" target="\_blank">(?)</a>

…

…

 

75

88

            $subjectDecoded = quoted\_printable\_decode($subjectEncoded);

76

89

            $subjectDecoded = base64\_decode($subjectEncoded);

77

 

            $subjectDecoded = GeneralHelper::sanitiseHtmlspecialchars($subjectDecoded);

 

90

            $subjectDecoded = $this->runHtmlSpecialChars($subjectDecoded);

 

91

78

92

            return '<span class="asci-help" data-hover-message="' . \_\_("This subject was quoted printable decoded") . '">

79

93

                        <a href="' . $this->asciSubjectHelpLink . '" target="\_blank">(?)</a>

…

…

 

82

96

        }

83

97

84

 

        return GeneralHelper::sanitiseHtmlspecialchars($subject);

 

98

        return $this->runHtmlSpecialChars($subject);

85

99

    }

86

100

…

…

 

126

140

        \];

127

141

128

 

        return sprintf('%1$s %2$s', GeneralHelper::sanitiseHtmlspecialchars($item\['email\_to'\]), $this->row\_actions($actions));

 

142

        $emailTo = $this->runHtmlSpecialChars($item\['email\_to'\]);

 

143

 

144

        return sprintf('%1$s %2$s', $emailTo, $this->row\_actions($actions));

129

145

    }

130

146
  • wp-mail-catcher/trunk/src/Models/Logs.php

    r2922546

    r2924014

85

85

         \* Sanitise each value in the array

86

86

         \*/

87

 

        array\_walk\_recursive($args, 'WpMailCatcher\\GeneralHelper::sanitiseForQuery');

 

87

        array\_walk\_recursive($args, 'WpMailCatcher\\GeneralHelper::sanitiseForDbQuery');

88

88

89

89

        $sql = "SELECT " . implode(',', $columnsToSelect) . "

…

…

 

181

181

            } elseif (isset($result\['additional\_headers'\])) {

182

182

                $result\['is\_html'\] = GeneralHelper::doesArrayContainSubString(

183

 

                    $result\['additional\_headers'\],

184

 

                    GeneralHelper::$htmlEmailHeader

 

183

                    str\_replace(' ', '', $result\['additional\_headers'\]),

 

184

                    str\_replace(' ', '', GeneralHelper::$htmlEmailHeader)

185

185

                );

186

 

            }

187

 

188

 

            if (isset($result\['message'\])) {

189

 

                $result\['message'\] = stripslashes(htmlspecialchars\_decode($result\['message'\]));

190

 

            }

191

 

192

 

            if (isset($result\['subject'\])) {

193

 

                $result\['subject'\] = stripslashes(htmlspecialchars\_decode($result\['subject'\]));

194

 

            }

195

 

196

 

            if (isset($result\['email\_to'\])) {

197

 

                $result\['email\_to'\] = stripslashes(htmlspecialchars\_decode($result\['email\_to'\]));

198

186

            }

199

187

…

…

 

239

227

240

228

        $ids = GeneralHelper::arrayToString($ids);

241

 

        $ids = GeneralHelper::sanitiseForQuery($ids);

 

229

        $ids = GeneralHelper::sanitiseForDbQuery($ids);

242

230

243

231

        $wpdb->query("DELETE FROM " . $wpdb->prefix . GeneralHelper::$tableName . "
  • wp-mail-catcher/trunk/src/Models/Mail.php

    r2920307

    r2924014

21

21

22

22

            add\_filter('wp\_mail\_content\_type', $updateContentType, self::$contentTypeFilterPriority);

 

23

 

24

            if (isset($log\['message'\])) {

 

25

                $log\['message'\] = GeneralHelper::filterHtml($log\['message'\]);

 

26

            }

 

27

 

28

            if (isset($log\['subject'\])) {

 

29

                $log\['subject'\] = GeneralHelper::filterHtml($log\['subject'\]);

 

30

            }

23

31

24

32

            wp\_mail(

…

…

 

54

62

                return in\_array($key, GeneralHelper::$csvExportLegalColumns);

55

63

            }, ARRAY\_FILTER\_USE\_KEY);

 

64

 

65

            if (isset($log\['message'\])) {

 

66

                $log\['message'\] = GeneralHelper::filterHtml($log\['message'\]);

 

67

            }

 

68

 

69

            if (isset($log\['subject'\])) {

 

70

                $log\['subject'\] = GeneralHelper::filterHtml($log\['subject'\]);

 

71

            }

56

72

57

73

            if (isset($log\['attachments'\]) && !empty($log\['attachments'\]) && is\_array($log\['attachments'\])) {
  • wp-mail-catcher/trunk/src/Views/HtmlMessage.php

    r2920307

    r2924014

1

1

<?php

2

2

3

 

echo $log\['message'\] ?? '';

 

3

use WpMailCatcher\\GeneralHelper;

 

4

 

5

echo GeneralHelper::filterHtml($log\['message'\] ?? '');

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907