@@ -1522,7 +1522,7 @@ QMap<QString, QString> QgsWMSServer::applyRequestedLayerFilters( const QStringLi
1522
1522
if ( filterIt != mParameterMap .end () )
1523
1523
{
1524
1524
QString filterParameter = filterIt->second ;
1525
- QStringList layerSplit = filterParameter.split ( " , " );
1525
+ QStringList layerSplit = filterParameter.split ( " ; " );
1526
1526
QStringList::const_iterator layerIt = layerSplit.constBegin ();
1527
1527
for ( ; layerIt != layerSplit.constEnd (); ++layerIt )
1528
1528
{
@@ -1532,6 +1532,15 @@ QMap<QString, QString> QgsWMSServer::applyRequestedLayerFilters( const QStringLi
1532
1532
continue ;
1533
1533
}
1534
1534
1535
+ // filter string could be unsafe (danger of sql injection)
1536
+ if ( !testFilterStringSafety ( eqSplit.at ( 1 ) ) )
1537
+ {
1538
+ throw QgsMapServiceException ( " Filter string rejected" , " The filter string " + eqSplit.at ( 1 ) +
1539
+ " has been rejected because of security reasons. Note: Text strings have to be enclosed in single or double quotes. " +
1540
+ " A space between each word / special character is mandatory. Allowed Keywords and special characters are " +
1541
+ " AND,OR,IN,<,>=,>,>=,!=,',',(,). Not allowed are semicolons in the filter expression." );
1542
+ }
1543
+
1535
1544
// we know the layer name, but need to go through the list because a layer could be there several times...
1536
1545
int listPos = 1 ;
1537
1546
QStringList::const_iterator layerIt = layerList.constBegin ();
@@ -1581,3 +1590,68 @@ void QgsWMSServer::restoreLayerFilters( const QMap < QString, QString >& filterM
1581
1590
}
1582
1591
}
1583
1592
}
1593
+
1594
+ bool QgsWMSServer::testFilterStringSafety ( const QString& filter ) const
1595
+ {
1596
+ // ; too dangerous for sql injections
1597
+ if ( filter.contains ( " ;" ) )
1598
+ {
1599
+ return false ;
1600
+ }
1601
+
1602
+ QStringList tokens = filter.split ( " " , QString::SkipEmptyParts );
1603
+ QStringList::const_iterator tokenIt = tokens.constBegin ();
1604
+ for ( ; tokenIt != tokens.constEnd (); ++tokenIt )
1605
+ {
1606
+ // whitelist of allowed characters and keywords
1607
+ if ( tokenIt->compare ( " ," ) == 0
1608
+ || tokenIt->compare ( " (" ) == 0
1609
+ || tokenIt->compare ( " )" ) == 0
1610
+ || tokenIt->compare ( " =" ) == 0
1611
+ || tokenIt->compare ( " !=" ) == 0
1612
+ || tokenIt->compare ( " <" ) == 0
1613
+ || tokenIt->compare ( " <=" ) == 0
1614
+ || tokenIt->compare ( " >" ) == 0
1615
+ || tokenIt->compare ( " >=" ) == 0
1616
+ || tokenIt->compare ( " AND" , Qt::CaseInsensitive ) == 0
1617
+ || tokenIt->compare ( " OR" , Qt::CaseInsensitive ) == 0
1618
+ || tokenIt->compare ( " IN" , Qt::CaseInsensitive ) == 0 )
1619
+ {
1620
+ continue ;
1621
+ }
1622
+
1623
+ // numbers are ok
1624
+ bool isNumeric;
1625
+ tokenIt->toDouble ( &isNumeric );
1626
+ if ( isNumeric )
1627
+ {
1628
+ continue ;
1629
+ }
1630
+
1631
+ // numeric strings need to be quoted once either with single or with double quotes
1632
+
1633
+ // single quote
1634
+ if ( tokenIt->size () > 2
1635
+ && ( *tokenIt )[0 ] == QChar ( ' \' ' )
1636
+ && ( *tokenIt )[tokenIt->size () - 1 ] == QChar ( ' \' ' )
1637
+ && ( *tokenIt )[1 ] != QChar ( ' \' ' )
1638
+ && ( *tokenIt )[tokenIt->size () - 2 ] != QChar ( ' \' ' ) )
1639
+ {
1640
+ continue ;
1641
+ }
1642
+
1643
+ // double quote
1644
+ if ( tokenIt->size () > 2
1645
+ && ( *tokenIt )[0 ] == QChar ( ' "' )
1646
+ && ( *tokenIt )[tokenIt->size () - 1 ] == QChar ( ' "' )
1647
+ && ( *tokenIt )[1 ] != QChar ( ' "' )
1648
+ && ( *tokenIt )[tokenIt->size () - 2 ] != QChar ( ' "' ) )
1649
+ {
1650
+ continue ;
1651
+ }
1652
+
1653
+ return false ;
1654
+ }
1655
+
1656
+ return true ;
1657
+ }
0 commit comments