CVE-2024-21517 (Other, published 2024-06-22T05:15Z)
Description: value: This affects versions of the package opencart/opencart from 4.0.0.0. A reflected XSS issue was identified in the redirect parameter of customer account/login route. An attacker can inject arbitrary HTML and Javascript into the page response. As this vulnerability is present in the account functionality it could be used to target and attack customers of the OpenCart shop.**Notes:**1) The fix for this vulnerability is incomplete
Severity: nan (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/opencart/opencart
Files changed:
upload/catalog/controller/account/login.php
upload/catalog/controller/cms/comment.php
upload/catalog/controller/startup/seo_url.php
upload/catalog/view/template/account/login.twig
upload/catalog/view/template/cms/comment.twig
upload/catalog/view/template/cms/comment_list.twig
upload/catalog/view/template/cms/comment_reply.twig
Commit message: added login to comment


Vulnerable code:
			$data['redirect'] = urldecode($this->request->get['redirect']);
			if (isset($this->request->post['redirect']) && str_starts_with(html_entity_decode($this->request->post['redirect'], ENT_QUOTES, 'UTF-8'), $this->config->get('config_url'))) {
				$json['redirect'] = html_entity_decode($this->request->post['redirect'], ENT_QUOTES, 'UTF-8') . '&customer_token=' . $this->session->data['customer_token'];
		$data['login'] = $this->url->link('account/login', 'language=' . $this->config->get('config_language'));

		if (!$this->customer->isLogged() && !$this->config->get('config_comment_guest')) {
			$json['error'] = $this->language->get('error_login');
		}

				'rating'             => (bool)$this->request->get['rating'],
		$parts = explode('&', $url_info['query']);
		foreach ($parts as $part) {
			$pair = explode('=', $part);
              <div class="text-end">
                <button type="submit" class="btn btn-primary">{{ button_login }}</button>
              </div>
  <button type="button" value="{{ like }}" id="input-rating-like" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></button>
  <button type="button" value="{{ dislike }}" id="input-rating-dislike" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></button>
    <a href="" class="btn btn-secondary">{{ button_login }}</a>


            <button type="button" value="{{ comment.like }}" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></button>
            <button type="button" value="{{ comment.dislike }}" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></button>

            {% if comment_guest %}
              <button type="button" class="btn btn-secondary" disabled="disabled">{{ button_reply }}</button>




            <button type="button" value="{{ comment.reply }}" id="button-refresh-{{ comment.article_comment_id }}" data-oc-toggle="refresh" data-oc-target="#reply-{{ comment.article_comment_id }}-0" class="btn btn-secondary"><i class="fa fa-sync"></i></button>



  <button type="button" value="{{ refresh }}" id="button-refresh" data-oc-toggle="refresh" data-oc-target="#comment-0" class="btn btn-secondary"><i class="fa fa-sync"></i></button>
  <button type="button" value="{{ refresh }}" id="button-refresh-{{ parent_id }}" data-oc-toggle="refresh" data-oc-target="#reply-{{ parent_id }}-{{ page }}" class="btn btn-secondary"><i class="fa fa-sync"></i></button>

Fixed code:
			$data['redirect'] = $this->request->get['redirect'];
			if (isset($this->request->post['redirect'])) {
				$redirect = urldecode($this->request->post['redirect']);
			} else {
				$redirect = '';
			}

			if ($redirect && str_starts_with($redirect, $this->config->get('config_url'))) {
				$json['redirect'] = $redirect . '&customer_token=' . $this->session->data['customer_token'];
		$data['login'] = $this->url->link('account/login', 'language=' . $this->config->get('config_language') . '&page=' . $page . '&redirect=' . urlencode($this->url->link('cms/blog.info', 'language=' . $this->config->get('config_language') . '&article_id=' . $data['article_id'], true)));
		$data['login'] = $this->url->link('account/login', 'language=' . $this->config->get('config_language') . '&redirect=' . urlencode($this->url->link('cms/blog.info', 'language=' . $this->config->get('config_language') . '&article_id=' . $article_id, true)));
		if (isset($this->request->get['rating'])) {
			$rating = (bool)$this->request->get['rating'];
		} else {
			$rating = 0;
		}

		if (!$this->customer->isLogged()) {
			$json['error'] = $this->language->get('error_login');
		}

				'rating'             => $rating,
		$queries = explode('&', $url_info['query']);
		foreach ($queries as $query) {
			$pair = explode('=', $query);
              <div class="text-end">
                <button type="submit" class="btn btn-primary">{{ button_login }}</button>
              </div>
    <button type="button" value="{{ like }}" id="input-rating-like" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></button>
    <button type="button" value="{{ dislike }}" id="input-rating-dislike" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></button>
    <a href="{{ login }}" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></a>
    <a href="{{ login }}" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></a>
    <a href="{{ login }}" class="btn btn-secondary">{{ button_login }}</a>
            {% if logged %}
              <button type="button" value="{{ comment.like }}" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></button>
              <button type="button" value="{{ comment.dislike }}" data-oc-toggle="rate" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></button>
              <a href="{{ login }}" class="btn btn-secondary"><i class="fa fa-thumbs-up"></i></a>
              <a href="{{ login }}" class="btn btn-secondary"><i class="fa fa-thumbs-down"></i></a>
              <a href="{{ login }}" class="btn btn-secondary">{{ button_login_reply }}</a>
            <button type="button" value="{{ comment.reply }}" id="button-refresh-{{ comment.article_comment_id }}" data-oc-toggle="refresh" data-oc-target="#reply-{{ comment.article_comment_id }}-0" class="btn btn-secondary d-none"><i class="fa fa-sync"></i></button>
  <button type="button" value="{{ refresh }}" id="button-refresh" data-oc-toggle="refresh" data-oc-target="#comment-0" class="btn btn-secondary d-none"><i class="fa fa-sync"></i></button>
  <button type="button" value="{{ refresh }}" id="button-refresh-{{ parent_id }}" data-oc-toggle="refresh" data-oc-target="#reply-{{ parent_id }}-{{ page }}" class="btn btn-secondary d-none"><i class="fa fa-sync"></i></button>