Skip to content

Commit cba683f

Browse files
committedMay 11, 2011
Safety check for wms server filters
1 parent 3cc052d commit cba683f

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed
 

‎src/mapserver/qgswmsserver.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ QMap<QString, QString> QgsWMSServer::applyRequestedLayerFilters( const QStringLi
15221522
if ( filterIt != mParameterMap.end() )
15231523
{
15241524
QString filterParameter = filterIt->second;
1525-
QStringList layerSplit = filterParameter.split( "," );
1525+
QStringList layerSplit = filterParameter.split( ";" );
15261526
QStringList::const_iterator layerIt = layerSplit.constBegin();
15271527
for ( ; layerIt != layerSplit.constEnd(); ++layerIt )
15281528
{
@@ -1532,6 +1532,15 @@ QMap<QString, QString> QgsWMSServer::applyRequestedLayerFilters( const QStringLi
15321532
continue;
15331533
}
15341534

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+
15351544
//we know the layer name, but need to go through the list because a layer could be there several times...
15361545
int listPos = 1;
15371546
QStringList::const_iterator layerIt = layerList.constBegin();
@@ -1581,3 +1590,68 @@ void QgsWMSServer::restoreLayerFilters( const QMap < QString, QString >& filterM
15811590
}
15821591
}
15831592
}
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+
}

‎src/mapserver/qgswmsserver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ class QgsWMSServer
143143
QMap<QString, QString> applyRequestedLayerFilters( const QStringList& layerList, const QStringList& layerIds ) const;
144144
/**Restores the original layer filters*/
145145
void restoreLayerFilters( const QMap < QString, QString >& filterMap ) const;
146+
/**Tests if a filter sql string is allowed (safe)
147+
@return true in case of success, false if string seems unsafe*/
148+
bool testFilterStringSafety( const QString& filter ) const;
146149

147150
/**Map containing the WMS parameters*/
148151
std::map<QString, QString> mParameterMap;

0 commit comments

Comments
 (0)
Please sign in to comment.