Vulnerability: Cross-site scripting (XSS) vulnerability in OpenCart before 2.1.0.2 allows remote attackers to inject arbitrary web script or HTML via the zone_id parameter to index.php.
Vulnerability ID: CVE-2015-4671
CWE: CWE-79
Severity score: 2.9
Project: https://github.com/opencart/opencart
Published: 2016-01-12
File: upload/catalog/controller/account/address.php
Commit message: Fixed low risk XSS issue with user account address edit. Thanks to @robert81 for the find.

Close #3721
Commit author: James Allsup

Vulnerable version (before fix):
 protected function getForm() { 		}  		if (isset($this->request->post['country_id'])) { 			$data['country_id'] = $this->request->post['country_id']; 		}  elseif (!empty($address_info)) { 			$data['country_id'] = $address_info['country_id']; 		} else { 			$data['country_id'] = $this->config->get('config_country_id'); 		}  		if (isset($this->request->post['zone_id'])) { 			$data['zone_id'] = $this->request->post['zone_id']; 		}  elseif (!empty($address_info)) { 			$data['zone_id'] = $address_info['zone_id']; 		} else { protected function validateForm() { 			$this->error['postcode'] = $this->language->get('error_postcode'); 		}  		if ($this->request->post['country_id'] == '') { 			$this->error['country'] = $this->language->get('error_country'); 		}  		if (!isset($this->request->post['zone_id']) || $this->request->post['zone_id'] == '') { 			$this->error['zone'] = $this->language->get('error_zone'); 		} 

Fixed version (after fix):
 protected function getForm() { 		}  		if (isset($this->request->post['country_id'])) { 			$data['country_id'] = (int)$this->request->post['country_id']; 		}  elseif (!empty($address_info)) { 			$data['country_id'] = $address_info['country_id']; 		} else { 			$data['country_id'] = $this->config->get('config_country_id'); 		}  		if (isset($this->request->post['zone_id'])) { 			$data['zone_id'] = (int)$this->request->post['zone_id']; 		}  elseif (!empty($address_info)) { 			$data['zone_id'] = $address_info['zone_id']; 		} else { protected function validateForm() { 			$this->error['postcode'] = $this->language->get('error_postcode'); 		}  		if ($this->request->post['country_id'] == '' || !is_int($this->request->post['country_id'])) { 			$this->error['country'] = $this->language->get('error_country'); 		}  		if (!isset($this->request->post['zone_id']) || $this->request->post['zone_id'] == '' || !is_int($this->request->post['zone_id'])) { 			$this->error['zone'] = $this->language->get('error_zone'); 		} 

Patch:
patch: @@ -425,15 +425,15 @@ protected function getForm() {
 		}
 
 		if (isset($this->request->post['country_id'])) {
-			$data['country_id'] = $this->request->post['country_id'];
+			$data['country_id'] = (int)$this->request->post['country_id'];
 		}  elseif (!empty($address_info)) {
 			$data['country_id'] = $address_info['country_id'];
 		} else {
 			$data['country_id'] = $this->config->get('config_country_id');
 		}
 
 		if (isset($this->request->post['zone_id'])) {
-			$data['zone_id'] = $this->request->post['zone_id'];
+			$data['zone_id'] = (int)$this->request->post['zone_id'];
 		}  elseif (!empty($address_info)) {
 			$data['zone_id'] = $address_info['zone_id'];
 		} else {
@@ -503,11 +503,11 @@ protected function validateForm() {
 			$this->error['postcode'] = $this->language->get('error_postcode');
 		}
 
-		if ($this->request->post['country_id'] == '') {
+		if ($this->request->post['country_id'] == '' || !is_int($this->request->post['country_id'])) {
 			$this->error['country'] = $this->language->get('error_country');
 		}
 
-		if (!isset($this->request->post['zone_id']) || $this->request->post['zone_id'] == '') {
+		if (!isset($this->request->post['zone_id']) || $this->request->post['zone_id'] == '' || !is_int($this->request->post['zone_id'])) {
 			$this->error['zone'] = $this->language->get('error_zone');
 		}
path: upload/catalog/controller/account/address.php