Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2022-25306: Changeset 2679983 for wp-statistics – WordPress Plugin Repository

The WP Statistics WordPress plugin is vulnerable to Cross-Site Scripting due to insufficient escaping and sanitization of the browser parameter found in the ~/includes/class-wp-statistics-visitor.php file which allows attackers to inject arbitrary web scripts onto several pages that execute when site administrators view a sites statistics, in versions up to and including 13.1.5.

CVE
#sql#web
  • wp-statistics/trunk/includes/admin/class-wp-statistics-admin-template.php

    r2587105

    r2679983

242

242

243

243

            // Push To list

244

 

            $list\[$number\_days\] = array('title' => $title, 'link' => $link, 'active' => $active);

 

244

            $list\[$number\_days\] = array('title' => $title, 'link' => sanitize\_url($link), 'active' => $active);

245

245

        }

246

246
  • wp-statistics/trunk/includes/admin/meta-box/wp-statistics-meta-box-platforms.php

    r2428043

    r2679983

85

85

86

86

                // Sanitize Version name

87

 

                $lists\_name\[\] = $l\['platform'\];

 

87

                $lists\_name\[\] = sanitize\_text\_field($l\['platform'\]);

88

88

89

89

                // Get List Count
  • wp-statistics/trunk/includes/admin/templates/optimization/purging.php

    r2626597

    r2679983

219

219

220

220

                    <p class="description"><?php \_e('All data table will be lost.', 'wp-statistics'); ?></p>

221

 

                    <input id="empty-table-submit" class="button button-primary" type="submit" value="<?php \_e('Clear now!',

222

 

                        'wp-statistics'); ?>" name="empty-table-submit" Onclick="return false;"/>

 

221

                    <input id="empty-table-submit" class="button button-primary" type="submit" value="<?php \_e('Clear now!', 'wp-statistics'); ?>" name="empty-table-submit" Onclick="return false;"/>

223

222

                    <span id="empty-status"></span>

224

223

                    <div id="empty-result"></div>

…

…

 

235

234

                    <label for="purge-data"><?php \_e('Days', 'wp-statistics'); ?></label>

236

235

237

 

                    <p class="description"><?php echo \_\_('Delete user statistics data older than the selected number of days.',

238

 

                                'wp-statistics') . ' ' . \_\_('Minimum value is 30 days.', 'wp-statistics'); ?></p>

239

 

                    <input id="purge-data-submit" class="button button-primary" type="submit" value="<?php \_e('Purge now!',

240

 

                        'wp-statistics'); ?>" name="purge-data-submit" Onclick="return false;"/>

 

236

                    <p class="description"><?php echo \_\_('Delete user statistics data older than the selected number of days.', 'wp-statistics') . ' ' . \_\_('Minimum value is 30 days.', 'wp-statistics'); ?></p>

 

237

                    <input id="purge-data-submit" class="button button-primary" type="submit" value="<?php \_e('Purge now!', 'wp-statistics'); ?>" name="purge-data-submit" Onclick="return false;"/>

241

238

                    <span id="purge-data-status"></span>

242

239

                    <div id="purge-data-result"></div>

…

…

 

254

251

                    <label for="purge-visitor-hits"><?php \_e('Hits', 'wp-statistics'); ?></label>

255

252

256

 

                    <p class="description"><?php echo \_\_('Delete user statistics data where the user has more than the defined number of hits in a day.',

257

 

                                'wp-statistics') . ' ' . \_\_('This can be useful to clear up old data when your site has been hit by a bot.',

258

 

                                'wp-statistics') . ' ' . \_\_('This will remove the visitor and their hits to the site, however it will not remove individual page hits as that data is not recorded on a per use basis.',

259

 

                                'wp-statistics') . ' ' . \_\_('Minimum value is 10 hits.', 'wp-statistics'); ?></p>

260

 

                    <input id="purge-visitor-hits-submit" class="button button-primary" type="submit" value="<?php \_e('Purge now!',

261

 

                        'wp-statistics'); ?>" name="purge-visitor-hits-submit" Onclick="return false;"/>

 

253

                    <p class="description"><?php echo \_\_('Delete user statistics data where the user has more than the defined number of hits in a day.', 'wp-statistics') . ' ' . \_\_('This can be useful to clear up old data when your site has been hit by a bot.', 'wp-statistics') . ' ' . \_\_('This will remove the visitor and their hits to the site, however it will not remove individual page hits as that data is not recorded on a per use basis.', 'wp-statistics') . ' ' . \_\_('Minimum value is 10 hits.', 'wp-statistics'); ?></p>

 

254

                    <input id="purge-visitor-hits-submit" class="button button-primary" type="submit" value="<?php \_e('Purge now!', 'wp-statistics'); ?>" name="purge-visitor-hits-submit" Onclick="return false;"/>

262

255

                    <span id="purge-visitor-hits-status"></span>

263

256

                    <div id="purge-visitor-hits-result"></div>

…

…

 

291

284

                    </select>

292

285

293

 

                    <p class="description"><?php \_e('All visitor data will be lost for this agent type.',

294

 

                            'wp-statistics'); ?></p>

295

 

                    <input id="delete-agents-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!',

296

 

                        'wp-statistics'); ?>" name="delete-agents-submit" Onclick="return false;">

 

286

                    <p class="description"><?php \_e('All visitor data will be lost for this agent type.', 'wp-statistics'); ?></p>

 

287

                    <input id="delete-agents-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!', 'wp-statistics'); ?>" name="delete-agents-submit" Onclick="return false;">

297

288

                    <span id="delete-agents-status"></span>

298

289

                    <div id="delete-agents-result"></div>

…

…

 

319

310

                    </select>

320

311

321

 

                    <p class="description"><?php \_e('All visitor data will be lost for this platform type.',

322

 

                            'wp-statistics'); ?></p>

323

 

                    <input id="delete-platforms-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!',

324

 

                        'wp-statistics'); ?>" name="delete-platforms-submit" Onclick="return false;">

 

312

                    <p class="description"><?php \_e('All visitor data will be lost for this platform type.', 'wp-statistics'); ?></p>

 

313

                    <input id="delete-platforms-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!', 'wp-statistics'); ?>" name="delete-platforms-submit" Onclick="return false;">

325

314

                    <span id="delete-platforms-status"></span>

326

315

                    <div id="delete-platforms-result"></div>

…

…

 

336

325

                    <input dir="ltr" id="delete-ip" type="text" name="delete-ip"/>

337

326

338

 

                    <p class="description"><?php \_e('All visitor data will be lost for this IP.',

339

 

                            'wp-statistics'); ?></p>

340

 

                    <input id="delete-ip-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!',

341

 

                        'wp-statistics'); ?>" name="delete-ip-submit" Onclick="return false;">

 

327

                    <p class="description"><?php \_e('All visitor data will be lost for this IP.', 'wp-statistics'); ?></p>

 

328

                    <input id="delete-ip-submit" class="button button-primary" type="submit" value="<?php \_e('Delete now!', 'wp-statistics'); ?>" name="delete-ip-submit" Onclick="return false;">

342

329

                    <span id="delete-ip-status"></span>

343

330

                    <div id="delete-ip-result"></div>
  • wp-statistics/trunk/includes/admin/templates/pages/refer.url.php

    r2587105

    r2679983

5

5

    |

6

6

    <li>

7

 

        <a class="current" href="<?php echo add\_query\_arg(array('referrer' => $args\['domain'\])); ?>">

 

7

        <a class="current" href="<?php echo esc\_url(add\_query\_arg(array('referrer' => $args\['domain'\]))); ?>">

8

8

            <?php echo $args\['domain'\]; ?>

9

9

            <span class="count">(<?php echo number\_format\_i18n($total); ?>)</span>
  • wp-statistics/trunk/includes/admin/templates/pages/visitors.php

    r2587105

    r2679983

31

31

                                <?php } ?>

32

32

                                <td>

33

 

                                    <a href="<?php echo add\_query\_arg('order', ((isset($\_GET\['order'\]) and $\_GET\['order'\] == "asc") ? 'desc' : 'asc')); ?>">

 

33

                                    <a href="<?php echo esc\_url( add\_query\_arg('order', ((isset($\_GET\['order'\]) and $\_GET\['order'\] == "asc") ? 'desc' : 'asc'))); ?>">

34

34

                                        <?php \_e('Date', 'wp-statistics'); ?>

35

35

                                        <span class="dashicons dashicons-arrow-<?php echo((isset($\_GET\['order'\]) and $\_GET\['order'\] == "asc") ? 'up' : 'down'); ?>"></span>
  • wp-statistics/trunk/includes/api/v2/class-wp-statistics-api-hit.php

    r2626597

    r2679983

36

36

    {

37

37

        return array(

38

 

            'browser',

39

 

            'platform',

40

 

            'version',

41

 

            'ip',

42

 

            'track\_all',

43

 

            'timestamp',

44

 

            'page\_uri',

45

 

            'user\_id',

 

38

            'browser'   => array('required' => true, 'type' => 'string'),

 

39

            'platform'  => array('required' => true, 'type' => 'string'),

 

40

            'version'   => array('required' => true, 'type' => 'string'),

 

41

            'ip'        => array('required' => true, 'type' => 'string', 'format' => 'ip'),

 

42

            'track\_all' => array('required' => true, 'type' => 'integer'),

 

43

            'timestamp' => array('required' => true, 'type' => 'integer'),

 

44

            'page\_uri'  => array('required' => true, 'type' => 'string'),

 

45

            'user\_id'   => array('required' => true, 'type' => 'integer'),

 

46

            '\_wpnonce'  => array('required' => true, 'type' => 'string')

46

47

        );

47

48

    }

…

…

 

54

55

    public function register\_routes()

55

56

    {

56

 

57

 

        // Create Require Params

58

 

        $params = array();

59

 

        foreach (self::require\_params\_hit() as $p) {

60

 

            $params\[$p\] = array('required' => true);

61

 

        }

62

 

63

 

        // Add X-WP-Nonce

64

 

        $params\['\_wpnonce'\] = array('required' => true);

65

 

66

57

        // Record WP-Statistics when Cache is enable

67

58

        register\_rest\_route(self::$namespace, '/' . self::$endpoint, array(

…

…

 

69

60

                'methods'             => \\WP\_REST\_Server::READABLE,

70

61

                'callback'            => array($this, 'hit\_callback'),

71

 

                'args'                => $params,

 

62

                'args'                => self::require\_params\_hit(),

72

63

                'permission\_callback' => function (\\WP\_REST\_Request $request) {

73

64

                    return true;
  • wp-statistics/trunk/includes/class-wp-statistics-hits.php

    r2671297

    r2679983

67

67

        if (isset($this->rest\_hits->browser) and isset($this->rest\_hits->platform) and isset($this->rest\_hits->version)) {

68

68

            return array(

69

 

                'browser'  => $this->rest\_hits->browser,

70

 

                'platform' => $this->rest\_hits->platform,

71

 

                'version'  => $this->rest\_hits->version,

 

69

                'browser'  => esc\_sql(sanitize\_text\_field($this->rest\_hits->browser)),

 

70

                'platform' => esc\_sql(sanitize\_text\_field($this->rest\_hits->platform)),

 

71

                'version'  => esc\_sql(sanitize\_text\_field($this->rest\_hits->version)),

72

72

            );

73

73

        }

…

…

 

95

95

    public function set\_user\_ip($ip)

96

96

    {

97

 

        return isset($this->rest\_hits->ip) ? $this->rest\_hits->ip : $ip;

 

97

        return isset($this->rest\_hits->ip) ? esc\_sql($this->rest\_hits->ip) : esc\_sql($ip);

98

98

    }

99

99

…

…

 

181

181

        if (isset($this->rest\_hits->current\_page\_type) and isset($this->rest\_hits->current\_page\_id)) {

182

182

            return array(

183

 

                'type'         => $this->rest\_hits->current\_page\_type,

184

 

                'id'           => $this->rest\_hits->current\_page\_id,

 

183

                'type'         => esc\_sql($this->rest\_hits->current\_page\_type),

 

184

                'id'           => esc\_sql($this->rest\_hits->current\_page\_id),

185

185

                'search\_query' => isset($this->rest\_hits->search\_query) ? $this->rest\_hits->search\_query : ''

186

186

            );
  • wp-statistics/trunk/includes/class-wp-statistics-ip.php

    r2428043

    r2679983

80

80

        }

81

81

82

 

        return apply\_filters('wp\_statistics\_user\_ip', $ip);

 

82

        return apply\_filters('wp\_statistics\_user\_ip', sanitize\_text\_field($ip));

83

83

    }

84

84

…

…

 

130

130

        }

131

131

132

 

        return $user\_ip;

 

132

        return sanitize\_text\_field($user\_ip);

133

133

    }

134

134
  • wp-statistics/trunk/includes/class-wp-statistics-pages.php

    r2626597

    r2679983

52

52

        }

53

53

54

 

        //Single Post Fro All Post Type

 

54

        //Single Post From All Post Type

55

55

        if (is\_singular()) {

56

56

            $current\_page\['type'\] = "post";

…

…

 

223

223

224

224

        // Check if we have already been to this page today.

225

 

        $exist = $wpdb->get\_row("SELECT \`page\_id\` FROM \`" . DB::table('pages') . "\` WHERE \`date\` = '" . TimeZone::getCurrentDate('Y-m-d') . "' " . (array\_key\_exists("search\_query", $current\_page) === true ? "AND \`uri\` = '" . esc\_sql($page\_uri) . "'" : "") . "AND \`type\` = '{$current\_page\['type'\]}' AND \`id\` = {$current\_page\['id'\]}", ARRAY\_A);

 

225

        $exist = $wpdb->get\_row("SELECT \`page\_id\` FROM \`" . DB::table('pages') . "\` WHERE \`date\` = '" . TimeZone::getCurrentDate('Y-m-d') . "' " . (array\_key\_exists("search\_query", $current\_page) === true ? "AND \`uri\` = '" . esc\_sql($page\_uri) . "'" : "") . "AND \`type\` = '{$current\_page\['type'\]}' AND \`id\` = '{$current\_page\['id'\]}'", ARRAY\_A);

226

226

227

227

        // Update Exist Page
  • wp-statistics/trunk/includes/class-wp-statistics-user-online.php

    r2428952

    r2679983

264

264

        foreach ($result as $items) {

265

265

 

266

            $ip       = esc\_html($items->ip);

 

267

            $agent    = esc\_html($items->agent);

 

268

            $platform = esc\_html($items->platform);

 

269

266

270

            $item = array(

267

271

                'referred' => Referred::get\_referrer\_link($items->referred),

268

 

                'agent'    => $items->agent,

269

 

                'platform' => $items->platform,

 

272

                'agent'    => $agent,

 

273

                'platform' => $platform,

270

274

                'version'  => $items->version,

271

275

            );

…

…

 

287

291

            // Push Browser

288

292

            $item\['browser'\] = array(

289

 

                'name' => $items->agent,

290

 

                'logo' => UserAgent::getBrowserLogo($items->agent),

291

 

                'link' => Menus::admin\_url('overview', array('agent' => $items->agent))

 

293

                'name' => $agent,

 

294

                'logo' => UserAgent::getBrowserLogo($agent),

 

295

                'link' => Menus::admin\_url('overview', array('agent' => $agent))

292

296

            );

293

297

294

298

            // Push IP

295

 

            if (IP::IsHashIP($items->ip)) {

 

299

            if (IP::IsHashIP($ip)) {

296

300

                $item\['hash\_ip'\] = IP::$hash\_ip\_prefix;

297

301

            } else {

298

 

                $item\['ip'\]  = array('value' => $items->ip, 'link' => Menus::admin\_url('visitors', array('ip' => $items->ip)));

299

 

                $item\['map'\] = GeoIP::geoIPTools($items->ip);

 

302

                $item\['ip'\]  = array('value' => $ip, 'link' => Menus::admin\_url('visitors', array('ip' => $ip)));

 

303

                $item\['map'\] = GeoIP::geoIPTools($ip);

300

304

            }

301

305

…

…

 

307

311

            // Push City

308

312

            if (GeoIP::active('city')) {

309

 

                $item\['city'\] = GeoIP::getCity($items->ip);

 

313

                $item\['city'\] = GeoIP::getCity($ip);

310

314

            }

311

315
  • wp-statistics/trunk/includes/class-wp-statistics-visitor.php

    r2428952

    r2679983

273

273

        foreach ($result as $items) {

274

274

 

275

            $ip       = esc\_html($items->ip);

 

276

            $agent    = esc\_html($items->agent);

 

277

            $platform = esc\_html($items->platform);

 

278

275

279

            $item = array(

276

280

                'hits'     => (int)$items->hits,

…

…

 

278

282

                'refer'    => $items->referred,

279

283

                'date'     => date\_i18n(get\_option('date\_format'), strtotime($items->last\_counter)),

280

 

                'agent'    => $items->agent,

281

 

                'platform' => $items->platform,

282

 

                'version'  => $items->version

 

284

                'agent'    => $agent,

 

285

                'platform' => $platform,

 

286

                'version'  => esc\_html($items->version)

283

287

            );

284

288

…

…

 

294

298

            // Push Browser

295

299

            $item\['browser'\] = array(

296

 

                'name' => $items->agent,

297

 

                'logo' => UserAgent::getBrowserLogo($items->agent),

298

 

                'link' => Menus::admin\_url('overview', array('agent' => $items->agent))

 

300

                'name' => $agent,

 

301

                'logo' => UserAgent::getBrowserLogo($agent),

 

302

                'link' => Menus::admin\_url('overview', array('agent' => $agent))

299

303

            );

300

304

301

305

            // Push IP

302

 

            if (IP::IsHashIP($items->ip)) {

 

306

            if (IP::IsHashIP($ip)) {

303

307

                $item\['hash\_ip'\] = IP::$hash\_ip\_prefix;

304

308

            } else {

305

 

                $item\['ip'\]  = array('value' => $items->ip, 'link' => Menus::admin\_url('visitors', array('ip' => $items->ip)));

306

 

                $item\['map'\] = GeoIP::geoIPTools($items->ip);

 

309

                $item\['ip'\]  = array('value' => $ip, 'link' => Menus::admin\_url('visitors', array('ip' => $ip)));

 

310

                $item\['map'\] = GeoIP::geoIPTools($ip);

307

311

            }

308

312

…

…

 

314

318

            // Push City

315

319

            if (GeoIP::active('city')) {

316

 

                $item\['city'\] = GeoIP::getCity($items->ip);

 

320

                $item\['city'\] = GeoIP::getCity($ip);

317

321

            }

318

322
  • wp-statistics/trunk/includes/template-functions.php

    r2626597

    r2679983

606

606

        //Check Browser is defined in wp-statistics

607

607

        if (array\_key\_exists(strtolower($out\[0\]), $default\_browser)) {

608

 

            $Browsers\[\] = $out\[0\];

 

608

            $Browsers\[\] = esc\_html($out\[0\]);

609

609

        }

610

610

    }

…

…

 

657

657

    $Platforms = array();

658

658

    foreach ($result as $out) {

659

 

        $Platforms\[\] = $out\[0\];

 

659

        $Platforms\[\] = esc\_html($out\[0\]);

660

660

    }

661

661
  • wp-statistics/trunk/readme.txt

    r2671297

    r2679983

5

5

Requires at least: 3.0

6

6

Tested up to: 5.9

7

 

Stable tag: 13.1.5

 

7

Stable tag: 13.1.6

8

8

Requires PHP: 5.6

9

9

License: GPLv3

…

…

 

125

125

126

126

\== Changelog ==

 

127

\= v13.1.6 - 16.02.2022 =

 

128

\* Bugfix: Hardened plugin security. (Special thanks to Muhammad Zeeshan (Xib3rR4dAr) & WPScan for reporting the issues)

 

129

127

130

\= v13.1.5 - 02.02.2022 =

128

131

\* Enhancement: Tested up to v5.9

129

132

\* Enhancement: Disable showing the notices with hidden class in the admin settings page

130

133

\* Bugfix: A security issue to accepting the correct \`exclusion\_reason\` through request

131

 

\* Bugfix: The 403 Forbidden Error issue

 

134

\* Bugfix: The 403 Forbidden Error issue in REST request

132

135

133

136

\= v13.1.4 - 14.01.2022 =
  • wp-statistics/trunk/wp-statistics.php

    r2671297

    r2679983

4

4

 \* Plugin URI: https://wp-statistics.com/

5

5

 \* Description: This plugin gives you the complete information on your website's visitors.

6

 

 \* Version: 13.1.5

 

6

 \* Version: 13.1.6

7

7

 \* Author: VeronaLabs

8

8

 \* Author URI: https://veronalabs.com/

CVE: Latest News

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