Skip to content

Commit

Permalink
Version 1.4.3 Security hotfixes
Browse files Browse the repository at this point in the history
- CVE-2019-3958	/api/sales/add Sales Item Name Authenticated Persistent Cross-site Scripting.
- CVE-2019-3959	Cross-Site Request Forgery.
- CVE-2019-3960	Authenticated Unrestricted File Upload RCE.
- Fixed .htaccess in database schema.
  • Loading branch information
micwallace committed Jun 25, 2019
1 parent 8b469ab commit ba07ac7
Show file tree
Hide file tree
Showing 469 changed files with 44,798 additions and 472 deletions.
16 changes: 16 additions & 0 deletions admin/assets/wpos/wpos.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,15 @@ function WPOSAdmin(){
getLoginStatus(function(user){
if (user!=false){
if (user.isadmin==1 || (user.sections!=null && user.sections.access!='no')){

curuser = user;

$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("anti-csrf-token", (curuser ? curuser.csrf_token : ""));
}
});

WPOS.initAdmin();
} else {
alert("You do not have permission to enter this area");
Expand Down Expand Up @@ -211,7 +219,15 @@ function WPOSAdmin(){
WPOS.sendJsonDataAsync("auth", JSON.stringify({username: username, password: password}), function(user){
if (user!==false){
if (user.isadmin==1 || (user.sections!=null && user.sections.access!='no')){

curuser = user;

$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("anti-csrf-token", (curuser ? curuser.csrf_token : ""));
}
});

WPOS.initAdmin();
} else {
alert("You do not have permission to enter this area");
Expand Down
2 changes: 1 addition & 1 deletion admin/content/reports.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function exportCurrentReport(){
function browserPrintHtml(html){
var printw = window.open('', 'wpos report', 'height=800,width=650');
printw.document.write('<html><head><title>Wpos Report</title>');
printw.document.write('<link media="all" href="assets/css/bootstrap.min.css" rel="stylesheet"/><link media="all" rel="stylesheet" href="assets/css/font-awesome.min.css"/><link media="all" rel="stylesheet" href="assets/css/ace-fonts.css"/><link media="all" rel="stylesheet" href="assets/css/ace.min.css"/>');
printw.document.write('<link media="all" href="/assets/css/bootstrap.min.css" rel="stylesheet"/><link media="all" rel="stylesheet" href="/assets/css/font-awesome.min.css"/><link media="all" rel="stylesheet" href="/assets/css/ace-fonts.css"/><link media="all" rel="stylesheet" href="/assets/css/ace.min.css"/>');
printw.document.write('</head><body style="background-color: #FFFFFF;">');
printw.document.write(html);
printw.document.write('</body></html>');
Expand Down
28 changes: 27 additions & 1 deletion api/wpos.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
$_SERVER['APP_ROOT'] = "/";

require($_SERVER['DOCUMENT_ROOT'] . $_SERVER['APP_ROOT'] . 'library/wpos/config.php');
require_once($_SERVER['DOCUMENT_ROOT'] . $_SERVER['APP_ROOT'] . 'library/autoload.php');
// setup api error handling
set_error_handler("errorHandler", E_ERROR | E_PARSE);
set_error_handler("warningHandler", E_WARNING);
Expand Down Expand Up @@ -91,9 +92,23 @@
$result['error'] = "Access Denied!";
returnResult($result);
}

if ($_SERVER['HTTP_ANTI_CSRF_TOKEN'] != $auth->getCsrfToken()) {
$result['errorCode'] = "auth";
$result['error'] = "CSRF token invalid. Please try reloading the page.";
returnResult($result);
}

// Decode JSON data if provided
if (isset($_REQUEST['data']) && $_REQUEST['data']!=""){
if (($requests=json_decode($_REQUEST['data']))==false){

// Easier to sanitize in JSON format all at once.
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$cleanData = $purifier->purify($_REQUEST['data']);

if (($requests=json_decode($cleanData))==false){
$result['errorCode'] = "request";
$result['error'] = "Could not parse the provided json request";
returnResult($result);
}
Expand Down Expand Up @@ -696,8 +711,19 @@ function routeApiCall($action, $data, $result) {

case "file/upload":
if (isset($_FILES['file'])) {

$uploaddir = 'docs';

$file_type = $_FILES['foreign_character_upload']['type']; //returns the mimetype

$allowed = array("image/jpeg", "image/gif", "image/png", "application/pdf");
if(!in_array($file_type, $allowed)) {
$result['error'] = 'Only jpg, gif, and pdf files are allowed.';
break;
}

$newpath = $uploaddir . DIRECTORY_SEPARATOR . basename($_FILES['file']['name']);

if (move_uploaded_file($_FILES['file']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . $_SERVER['APP_ROOT'] . $newpath) !== false) {
$result['data'] = ["path" => "/" . $newpath];
} else {
Expand Down
12 changes: 12 additions & 0 deletions assets/js/wpos/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ function WPOS() {
// set current user will possibly get passed additional data from server in the future but for now just username and pass is enough
setCurrentUser(response);
updateAuthTable(response);

$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("anti-csrf-token", (currentuser ? currentuser.csrf_token : ""));
}
});
}
if (callback)
callback(response!==false);
Expand All @@ -294,6 +300,12 @@ function WPOS() {
// set current user will possibly get passed additional data from server in the future but for now just username and pass is enough
setCurrentUser(response);
updateAuthTable(response);

$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("anti-csrf-token", (currentuser ? currentuser.csrf_token : ""));
}
});
return true;
} else {
return false;
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
"require": {
"php": ">=5.4.0",
"wisembly/elephant.io": "~3.0",
"ifsnop/mysqldump-php":"2.*"
"ifsnop/mysqldump-php":"2.*",
"ezyang/htmlpurifier": "^4.10"
},
"autoload": {
"psr-4": {
"ElephantIO\\": ["library/"]
}
}
}
}
56 changes: 51 additions & 5 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion library/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

// autoload.php @generated by Composer

require_once __DIR__ . '/composer' . '/autoload_real.php';
require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit04c164d2cd90f723569852fc7a37e407::getLoader();
60 changes: 46 additions & 14 deletions library/composer/ClassLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ class ClassLoader

private $useIncludePath = false;
private $classMap = array();

private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;

public function getPrefixes()
{
Expand Down Expand Up @@ -271,6 +272,26 @@ public function isClassMapAuthoritative()
return $this->classMapAuthoritative;
}

/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}

/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}

/**
* Registers this instance as an autoloader.
*
Expand Down Expand Up @@ -313,29 +334,34 @@ public function loadClass($class)
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}

// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative) {
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}

$file = $this->findFileWithExtension($class, '.php');

// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}

if ($file === null) {
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}

if (false === $file) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
$this->missingClasses[$class] = true;
}

return $file;
Expand All @@ -348,10 +374,14 @@ private function findFileWithExtension($class, $ext)

$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
Expand Down Expand Up @@ -399,6 +429,8 @@ private function findFileWithExtension($class, $ext)
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}

return false;
}
}

Expand Down
Loading

0 comments on commit ba07ac7

Please sign in to comment.