Merge pull request #10582 from creative-commoners/pulls/4.10/cve-2022-38148

Validate SortColumn exists
This commit is contained in:
Guy Sartorelli 2022-11-21 13:30:35 +13:00 committed by GitHub
commit c7c108b29a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 7 deletions

View File

@ -11,6 +11,7 @@ use SilverStripe\ORM\DataObject;
use SilverStripe\View\ArrayData; use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
use LogicException; use LogicException;
use SilverStripe\Core\Injector\Injector;
/** /**
* GridFieldSortableHeader adds column headers to a {@link GridField} that can * GridFieldSortableHeader adds column headers to a {@link GridField} that can
@ -271,6 +272,16 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
return $dataList; return $dataList;
} }
// Prevent SQL Injection by validating that SortColumn exists
/** @var GridFieldDataColumns $columns */
$columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
$fields = $columns->getDisplayFields($gridField);
if (!array_key_exists($state->SortColumn, $fields) &&
!in_array($state->SortColumn, $this->getFieldSorting())
) {
throw new LogicException('Invalid SortColumn: ' . $state->SortColumn);
}
return $dataList->sort($state->SortColumn, $state->SortDirection('asc')); return $dataList->sort($state->SortColumn, $state->SortDirection('asc'));
} }

View File

@ -71,17 +71,18 @@ class GridFieldSortableHeaderTest extends SapphireTest
$list = Team::get()->filter([ 'ClassName' => Team::class ]); $list = Team::get()->filter([ 'ClassName' => Team::class ]);
$config = new GridFieldConfig_RecordEditor(); $config = new GridFieldConfig_RecordEditor();
$gridField = new GridField('testfield', 'testfield', $list, $config); $gridField = new GridField('testfield', 'testfield', $list, $config);
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
// Test normal sorting // Test normal sorting
$component->setFieldSorting(['Name' => 'City']);
$state = $gridField->State->GridFieldSortableHeader; $state = $gridField->State->GridFieldSortableHeader;
$state->SortColumn = 'City'; $state->SortColumn = 'City';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$compontent = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class); $listA = $component->getManipulatedData($gridField, $list);
$listA = $compontent->getManipulatedData($gridField, $list);
$state->SortDirection = 'desc'; $state->SortDirection = 'desc';
$listB = $compontent->getManipulatedData($gridField, $list); $listB = $component->getManipulatedData($gridField, $list);
$this->assertEquals( $this->assertEquals(
['Auckland', 'Cologne', 'Melbourne', 'Wellington'], ['Auckland', 'Cologne', 'Melbourne', 'Wellington'],
@ -93,12 +94,13 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test one relation 'deep' // Test one relation 'deep'
$component->setFieldSorting(['Name' => 'Cheerleader.Name']);
$state->SortColumn = 'Cheerleader.Name'; $state->SortColumn = 'Cheerleader.Name';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListA = $compontent->getManipulatedData($gridField, $list); $relationListA = $component->getManipulatedData($gridField, $list);
$state->SortDirection = 'desc'; $state->SortDirection = 'desc';
$relationListB = $compontent->getManipulatedData($gridField, $list); $relationListB = $component->getManipulatedData($gridField, $list);
$this->assertEquals( $this->assertEquals(
['Wellington', 'Melbourne', 'Cologne', 'Auckland'], ['Wellington', 'Melbourne', 'Cologne', 'Auckland'],
@ -110,12 +112,13 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test two relations 'deep' // Test two relations 'deep'
$component->setFieldSorting(['Name' => 'Cheerleader.Hat.Colour']);
$state->SortColumn = 'Cheerleader.Hat.Colour'; $state->SortColumn = 'Cheerleader.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListC = $compontent->getManipulatedData($gridField, $list); $relationListC = $component->getManipulatedData($gridField, $list);
$state->SortDirection = 'desc'; $state->SortDirection = 'desc';
$relationListD = $compontent->getManipulatedData($gridField, $list); $relationListD = $component->getManipulatedData($gridField, $list);
$this->assertEquals( $this->assertEquals(
['Cologne', 'Auckland', 'Wellington', 'Melbourne'], ['Cologne', 'Auckland', 'Wellington', 'Melbourne'],
@ -139,6 +142,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class); $component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
// Test that inherited dataobjects will work correctly // Test that inherited dataobjects will work correctly
$component->setFieldSorting(['Name' => 'Cheerleader.Hat.Colour']);
$state->SortColumn = 'Cheerleader.Hat.Colour'; $state->SortColumn = 'Cheerleader.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListA = $component->getManipulatedData($gridField, $list); $relationListA = $component->getManipulatedData($gridField, $list);
@ -179,6 +183,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test subclasses of tables // Test subclasses of tables
$component->setFieldSorting(['Name' => 'CheerleadersMom.Hat.Colour']);
$state->SortColumn = 'CheerleadersMom.Hat.Colour'; $state->SortColumn = 'CheerleadersMom.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListB = $component->getManipulatedData($gridField, $list); $relationListB = $component->getManipulatedData($gridField, $list);
@ -229,4 +234,21 @@ class GridFieldSortableHeaderTest extends SapphireTest
$relationListBdesc->column('City') $relationListBdesc->column('City')
); );
} }
public function testSortColumnValidation()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Invalid SortColumn: INVALID');
$list = Team::get()->filter([ 'ClassName' => Team::class ]);
$config = new GridFieldConfig_RecordEditor();
$gridField = new GridField('testfield', 'testfield', $list, $config);
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
$state = $gridField->State->GridFieldSortableHeader;
$state->SortColumn = 'INVALID';
$state->SortDirection = 'asc';
$component->getManipulatedData($gridField, $list);
}
} }