-
-
Notifications
You must be signed in to change notification settings - Fork 360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Denials of service with SLD parameter in WMS requests #4703
Conversation
Set I guess a good solution could be to allow the use of sld remote only from selected sources. |
milestoning this for 6.4 so we don't forget it. Can anyone familiar with SLD comment on the proposed fixes? ping @mkofahl @dmorissette @tomkralidis |
I like the size limit put forth in/for We could also add the ability for users to set this with `ows_filesize_limit" "bytes" (which could be used for many other areas potentially in the code where MapServer is fetching remote resources. |
for the |
For point [4], in 08ac591 I have moved the msGetLayerIndex call out of the inner loop. In theory it would need to be called in the inner loop as the inner loop is potentially adding layers, however the added layers are added to the end of the layer list, which means that nIndex does not change. |
for point [3] we now unlink the temporary file in case of error, in 1765c1e |
@rouault do I understand correctly that point [5] is a case where the server is recursively calling itself? In this case it may actually lead to a complete denial of service, once you have occupied all the webserver's workers. I'm not sure how to mitigate this however, as it seems that such a request is compliant with the spec. |
can be overriden by the (wms|ows)_remote_sld_max_bytes metadata entry
For point [2] I have added a default limit of 1 Megabyte to remote SLD size in 0abb694 + typo in 664c7dc . cc @dmorissette . The (ows|wms)_remote_sld_max_bytes metadata value to override this will need to be documented (cc @havatv). We also need to setup some autotests for remote SLD handling. |
@tbonfort about [5], yes the server is calling itself recursively and it can completely block itself. However I'm not sure if it is really critical, since an hostile client could just issue X requests with a SLD that points to a URL that timeouts. The trick is [5] is just some fun to do it with just one request, in case a policy on the server would block simultaneous request from the same IP for example. |
- requires a http server serving the root of the msautotest directory, that can be started with python -m SimpleHTTPServer - tests for MapServer/MapServer#4703
- check working sld - check 404 - check invalid protocol (add file:// once MapServer/MapServer#4703 is merged)
Avoid O(N^2) looping on supplied NamedLayers Only allow HTTP and HTTPS for curl request unlink temporary sld file in case of error limit remote SLD downloads to 1 Megabyte by default, can be overriden by the (wms|ows)_remote_sld_max_bytes metadata entry
points [1] through [4] rebased,squashed and applied to master in 0294d6a . For [5] I have no idea what to do. |
Sorry, typo in the commit message - should be "wms server" (not "wfs server"). |
I've identified several flows in the handling of the SLD parameter of WMS GetFeature requests :
--> We could check in msHTTPGetFile() that the URL starts with http:// or https://
--> Could be mitigated by making sure that msHTTPWriteFct (in the case of dowloading a SLD or an external graphic from msSLDParseExternalGraphic()) stops after downloading, let's say 1 MB, 10 MB ?
For example:
Breaking in the debugger shows that the time is spent in msGetLayerIndex(). Indeed, the issue is in msSLDApplySLD() that has :
The complexity of this is O(nLayers^3).
The above complexity could likely be reduced in O(nLayers * log(nLayers)) by using smart data structures (hashtable, etc...). An easier workaround would be to validate that nLayers isn't too large, 100, 1000 ? For reference, on my PC, 1000 layers means 13 seconds.
The structure is : GET_FEATURE_URL&SLD=url_encode_of(GET_FEATURE_URL&SLD=url_encode_of(GET_FEATURE_URL&SLD=url_encode_of(GET_FEATURE_URL&SLD=url_encode_of(GET_FEATURE_URL))))
Example :
http://127.0.0.1:80/cgi-bin/mapserv.fcgi?map=/home/even/mapserver/git/mapserver/msautotest/wxs/wms_sld.map&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG:4326&WIDTH=560&HEIGHT=350&LAYERS=road_styles,road_styles,road_styles&FORMAT=image/png&BGCOLOR=0xFFFFFF&TRANSPARENT=FALSE&EXCEPTIONS=INIMAGE&BBOX=44.6139013125,-66.998804375,48.0904731875,-61.436289375&SLD=http%3A%2F%2F127.0.0.1%3A80%2Fcgi-bin%2Fmapserv.fcgi%3Fmap%3D%2Fhome%2Feven%2Fmapserver%2Fgit%2Fmapserver%2Fmsautotest%2Fwxs%2Fwms_sld.map%26SERVICE%3DWMS%26VERSION%3D1.3.0%26REQUEST%3DGetMap%26CRS%3DEPSG%3A4326%26WIDTH%3D560%26HEIGHT%3D350%26LAYERS%3Droad_styles%2Croad_styles%2Croad_styles%26FORMAT%3Dimage%2Fpng%26BGCOLOR%3D0xFFFFFF%26TRANSPARENT%3DFALSE%26EXCEPTIONS%3DINIMAGE%26BBOX%3D44.6139013125%2C-66.998804375%2C48.0904731875%2C-61.436289375%26SLD%3Dhttp%253A%252F%252F127.0.0.1%253A80%252Fcgi-bin%252Fmapserv.fcgi%253Fmap%253D%252Fhome%252Feven%252Fmapserver%252Fgit%252Fmapserver%252Fmsautotest%252Fwxs%252Fwms_sld.map%2526SERVICE%253DWMS%2526VERSION%253D1.3.0%2526REQUEST%253DGetMap%2526CRS%253DEPSG%253A4326%2526WIDTH%253D560%2526HEIGHT%253D350%2526LAYERS%253Droad_styles%252Croad_styles%252Croad_styles%2526FORMAT%253Dimage%252Fpng%2526BGCOLOR%253D0xFFFFFF%2526TRANSPARENT%253DFALSE%2526EXCEPTIONS%253DINIMAGE%2526BBOX%253D44.6139013125%252C-66.998804375%252C48.0904731875%252C-61.436289375%2526SLD%253Dhttp%25253A%25252F%25252F127.0.0.1%25253A80%25252Fcgi-bin%25252Fmapserv.fcgi%25253Fmap%25253D%25252Fhome%25252Feven%25252Fmapserver%25252Fgit%25252Fmapserver%25252Fmsautotest%25252Fwxs%25252Fwms_sld.map%252526SERVICE%25253DWMS%252526VERSION%25253D1.3.0%252526REQUEST%25253DGetMap%252526CRS%25253DEPSG%25253A4326%252526WIDTH%25253D560%252526HEIGHT%25253D350%252526LAYERS%25253Droad_styles%25252Croad_styles%25252Croad_styles%252526FORMAT%25253Dimage%25252Fpng%252526BGCOLOR%25253D0xFFFFFF%252526TRANSPARENT%25253DFALSE%252526EXCEPTIONS%25253DINIMAGE%252526BBOX%25253D44.6139013125%25252C-66.998804375%25252C48.0904731875%25252C-61.436289375%252526SLD%25253Dhttp%2525253A%2525252F%2525252F127.0.0.1%2525253A80%2525252Fcgi-bin%2525252Fmapserv.fcgi%2525253Fmap%2525253D%2525252Fhome%2525252Feven%2525252Fmapserver%2525252Fgit%2525252Fmapserver%2525252Fmsautotest%2525252Fwxs%2525252Fwms_sld.map%25252526SERVICE%2525253DWMS%25252526VERSION%2525253D1.3.0%25252526REQUEST%2525253DGetMap%25252526CRS%2525253DEPSG%2525253A4326%25252526WIDTH%2525253D560%25252526HEIGHT%2525253D350%25252526LAYERS%2525253Droad_styles%2525252Croad_styles%2525252Croad_styles%25252526FORMAT%2525253Dimage%2525252Fpng%25252526BGCOLOR%2525253D0xFFFFFF%25252526TRANSPARENT%2525253DFALSE%25252526EXCEPTIONS%2525253DINIMAGE%25252526BBOX%2525253D44.6139013125%2525252C-66.998804375%2525252C48.0904731875%2525252C-61.436289375
--> Could be mitigated by validating that the SLD URL doesn't contain % and ? characters ? And that it has a .xml or .sld extension ?
Of course all of this can be avoided by defining "ows_sld_enabled" "false" in the mapfile, but as true is the default value, many servers are potentially vulnerable. The documentation doesn't really warns the user about the implications of enabling SLD. Perhaps should the default value be changed to "false" for 6.4 or 7.0 ?