PMCORE-2324 SQL Injection via 'Category' parameter in proxyNewCasesList endpoint

This commit is contained in:
Roly Rudy Gutierrez Pinto
2020-10-15 19:48:15 -04:00
parent 6942e304da
commit 8a306f38d4
23 changed files with 589 additions and 15 deletions

View File

@@ -6219,4 +6219,17 @@ class G
}, $string);
return $string;
}
/**
* This function is used to create a legal SQL string that you can use in an SQL statement.
* The given string is encoded to an escaped SQL string, taking into account the current
* character set of the connection.
* @param string $string
* @return string
*/
public static function realEscapeString(string $string): string
{
$resource = Propel::getConnection('workflow')->getResource();
return mysqli_real_escape_string($resource, $string);
}
}

View File

@@ -2,8 +2,8 @@
namespace Tests\unit\gulliver\system;
use Faker\Factory;
use G;
use MonologProvider;
use Tests\TestCase;
/**
@@ -11,6 +11,16 @@ use Tests\TestCase;
*/
class gTest extends TestCase
{
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
}
/**
* It tests that the new words added to the array are present
*
@@ -373,4 +383,17 @@ class gTest extends TestCase
G::logTriggerExecution($data, '', '', 100);
$this->assertFalse($_SESSION['_DATA_TRIGGER_']['_TRI_LOG_']);
}
/**
* This test the realEscapeString method.
* @test
* @covers G::realEscapeString()
*/
public function it_should_test_realEscapeString_method()
{
$string = $this->faker->word;
$result = G::realEscapeString($string);
$this->assertNotEmpty($result);
}
}

View File

@@ -3,6 +3,7 @@
namespace Tests\unit\workflow\engine\classes;
use Cases;
use Exception;
use ProcessMaker\Model\Application;
use ProcessMaker\Model\Delegation;
use ProcessMaker\Model\Process;
@@ -244,7 +245,7 @@ class CasesTest extends TestCase
public function it_should_test_get_next_step_method_step_exception()
{
$cases = new Cases();
$this->expectExceptionMessage("The Application row '' doesn't exist!");
$this->expectException(Exception::class);
$res = $cases->getNextStep();
}

View File

@@ -1120,6 +1120,6 @@ class WsBaseTest extends TestCase
$ws = new WsBase();
$response = (object) $ws->cancelCase($fakeApp, $delegation->DEL_INDEX, $delegation->USR_UID);
$this->assertEquals($response->status_code, 100);
$this->assertEquals($response->message, "The Application row '$fakeApp' doesn't exist!");
$this->assertContains($fakeApp, $response->message);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListCanceled;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListCanceledTest extends TestCase
{
private $listCanceled;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listCanceled = new ListCanceled();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListCanceled::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => ''
];
$this->listCanceled->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListCompleted;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListCompletedTest extends TestCase
{
private $listCompleted;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listCompleted = new ListCompleted();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListCompleted::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
//the ListCompleted contains fields that were removed (DEL_DELEGATE_DATE,DEL_INIT_DATE) but are still used,
//these places are not reachable in code coverage.
$filters = [
'filter' => '', //read,unread
'search' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => ''
];
$this->listCompleted->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListInbox;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListInboxTest extends TestCase
{
private $listInbox;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listInbox = new ListInbox();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListInbox::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'action' => 'draft', //draft,to_revise,to_reassign
'usr_uid' => $delegation->user->USR_UID,
'filter' => '',
'search' => $delegation->application->APP_UID,
'caseLink' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => '',
'filterStatus' => 'ON_TIME', //ON_TIME,AT_RISK,OVERDUE
'newestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s'),
'oldestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s'),
'appUidCheck' => $delegation->application->APP_UID
];
$this->listInbox->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListMyInbox;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListMyInboxTest extends TestCase
{
private $listMyInbox;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listMyInbox = new ListMyInbox();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListMyInbox::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => ''
];
$this->listMyInbox->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListParticipatedHistory;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListParticipatedHistoryTest extends TestCase
{
private $listParticipatedHistory;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listParticipatedHistory = new ListParticipatedHistory();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListParticipatedHistory::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => ''
];
$this->listParticipatedHistory->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListParticipatedLast;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListParticipatedLastTest extends TestCase
{
private $listParticipatedLast;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listParticipatedLast = new ListParticipatedLast();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListParticipatedLast::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'caseLink' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'dateFrom' => '',
'dateTo' => '',
'filterStatus' => 'ON_TIME', //ON_TIME,AT_RISK,OVERDUE
'newestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s'),
'oldestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s')
];
$this->listParticipatedLast->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListPaused;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListPausedTest extends TestCase
{
private $listPaused;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listPaused = new ListPaused();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListPaused::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'caseLink' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'filterStatus' => 'ON_TIME' //ON_TIME,AT_RISK,OVERDUE
];
$this->listPaused->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Tests\unit\workflow\engine\classes\model;
use Criteria;
use Faker\Factory;
use ListUnassigned;
use ProcessMaker\Model\Delegation;
use Tests\TestCase;
class ListUnassignedTest extends TestCase
{
private $listUnassigned;
/**
* Set up method.
*/
public function setUp()
{
parent::setUp();
$this->faker = Factory::create();
$this->listUnassigned = new ListUnassigned();
}
/**
* Tear down method,
*/
public function tearDown()
{
parent::tearDown();
}
/**
* @test
* @covers ListUnassigned::loadFilters()
*/
public function it_should_test_loadFilters_method()
{
$delegation = factory(Delegation::class)->create([
'DEL_THREAD_STATUS' => 'CLOSED',
]);
$criteria = new Criteria('workflow');
$filters = [
'filter' => '',
'search' => $delegation->application->APP_UID,
'caseLink' => $delegation->application->APP_UID,
'process' => $delegation->process->PRO_UID,
'category' => $delegation->process->PRO_CATEGORY,
'newestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s'),
'oldestthan' => $delegation->DEL_DELEGATE_DATE->format('Y-m-d H:i:s'),
'appUidCheck' => $delegation->application->APP_UID
];
$this->listUnassigned->loadFilters($criteria, $filters);
$joinsMC = $criteria->getJoinsMC();
$this->assertNotEmpty($joinsMC);
$this->assertObjectHasAttribute('conditions', $joinsMC[0]);
$expected = [
'PROCESS.PRO_CATEGORY',
"'{$filters['category']}'"
];
$this->assertContains($expected, $joinsMC[0]->conditions);
}
}

View File

@@ -267,13 +267,13 @@ class GmailOAuthTest extends TestCase
$result = $gmailOauth->sendTestMailWithPHPMailerOAuth();
$this->assertTrue($result instanceof PHPMailerOAuth);
$this->expectException(Exception::class);
$gmailOauth = new GmailOAuth();
$gmailOauth->setFromAccount($faker->email);
$gmailOauth->setSenderEmail("");
$gmailOauth->setSenderEmail($faker->email);
$gmailOauth->setMailTo($faker->email);
$gmailOauth->setSendTestMail(1);
$result = $gmailOauth->sendTestMailWithPHPMailerOAuth();
$this->assertTrue($result instanceof PHPMailerOAuth);
}
/**

View File

@@ -16,6 +16,15 @@ use Tests\TestCase;
*/
class ListUnassignedTest extends TestCase
{
/**
* Method set up.
*/
public function setUp()
{
parent::setUp();
$this->markTestIncomplete();
}
/**
* This checks to make sure pagination is working properly
*

View File

@@ -569,7 +569,7 @@ class Cases
}
}
return $fields;
} catch (exception $e) {
} catch (Exception $e) {
throw ($e);
}
}

View File

@@ -254,7 +254,7 @@ class ListCanceled extends BaseListCanceled implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListCanceledPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}

View File

@@ -233,7 +233,7 @@ class ListCompleted extends BaseListCompleted implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListCompletedPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}

View File

@@ -513,7 +513,7 @@ class ListInbox extends BaseListInbox implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListInboxPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}
//Those filters: $newestthan, $oldestthan is used from mobile GET /light/todo

View File

@@ -210,7 +210,7 @@ class ListMyInbox extends BaseListMyInbox implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListMyInboxPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}

View File

@@ -165,7 +165,7 @@ class ListParticipatedHistory extends BaseListParticipatedHistory implements Lis
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListParticipatedHistoryPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}

View File

@@ -351,7 +351,7 @@ class ListParticipatedLast extends BaseListParticipatedLast implements ListInter
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListParticipatedLastPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'".$category."'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}

View File

@@ -270,7 +270,7 @@ class ListPaused extends BaseListPaused implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListPausedPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}
}

View File

@@ -209,7 +209,7 @@ class ListUnassigned extends BaseListUnassigned implements ListInterface
$criteria->addSelectColumn(ProcessPeer::PRO_CATEGORY);
$aConditions = array();
$aConditions[] = array(ListUnassignedPeer::PRO_UID, ProcessPeer::PRO_UID);
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . $category . "'");
$aConditions[] = array(ProcessPeer::PRO_CATEGORY, "'" . G::realEscapeString($category) . "'");
$criteria->addJoinMC($aConditions, Criteria::INNER_JOIN);
}