@@ -481,10 +481,18 @@ private byte[] CloudFunctionSpelPOC(IHttpRequestResponse httpRequestResponse, St
481481 * @return IScanIssue
482482 */
483483 private IScanIssue CloudGatewayScan (IHttpRequestResponse httpRequestResponse ) {
484+ boolean isProdApi = false ;
484485 // 这里判断是否有spring 404的特征: Whitelabel Error Page
485- if (!this .isSpringFinger (httpRequestResponse , false ) && !this .isSpringFinger (httpRequestResponse , true )) return null ;
486+ if (!this .isSpringFinger (httpRequestResponse , false ) && !this .isSpringFinger (httpRequestResponse , true )) {
487+ // 无spring 404特征的情况下判断是否有routes
488+ if (this .isSpringGatewayFinger (httpRequestResponse , true )) {
489+ isProdApi = true ;
490+ } else if (!this .isSpringGatewayFinger (httpRequestResponse , false )){
491+ return null ;
492+ }
493+ }
486494 URL url = this .helpers .analyzeRequest (httpRequestResponse ).getUrl ();
487- String uri = Utils .getUri (url .toString ());
495+ String uri = Utils .getUri (url .toString ()) + ( isProdApi ? "prod-api/" : "" ) ;
488496 String random_uri = Utils .randomStr (5 );
489497 if (this .CloudGatewayRegisterRoute (httpRequestResponse , uri , random_uri , "whoami" )) {
490498 if (this .CloudGatewayRefresh (httpRequestResponse , uri )) {
@@ -684,6 +692,54 @@ private boolean isSpringFinger(IHttpRequestResponse httpRequestResponse, boolean
684692 return false ;
685693 }
686694
695+ /**
696+ *
697+ * SpringGateway
698+ * 访问/actuator/gateway/routes、/prod-api/actuator/gateway/routes
699+ * 判断响应内容是否有SpringGateway特征: route_id
700+ *
701+ * @param httpRequestResponse
702+ * @return
703+ */
704+ private boolean isSpringGatewayFinger (IHttpRequestResponse httpRequestResponse , boolean isProdApi ) {
705+ try {
706+ IRequestInfo requestInfo = this .helpers .analyzeRequest (httpRequestResponse );
707+ IHttpService service = httpRequestResponse .getHttpService ();
708+ String url = Utils .getUri (requestInfo .getUrl ().toString ());
709+ if (isProdApi ) {
710+ url = url + "prod-api/actuator/gateway/routes" ;
711+ } else {
712+ url = url + "actuator/gateway/routes" ;
713+ }
714+ byte [] newRequest = this .helpers .buildHttpRequest (new URL (service .getProtocol (), service .getHost (), service .getPort (), url ));
715+ requestInfo = this .helpers .analyzeRequest (service , newRequest ); // 重新打包好新的uri请求
716+ // header中Accpet: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
717+ List <String > headers = requestInfo .getHeaders ();
718+ for (String header : headers ) {
719+ if (header .startsWith ("Accept" )) { // 坑点: 带冒号匹配会报错
720+ headers .remove (header );
721+ headers .add ("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" );
722+ break ;
723+ }
724+ }
725+ // 截取新请求, buildHttpRequest()之后会包含原本的GET请求内容和自定义构造的headers内容, 所以要截取
726+ IRequestInfo requestInfo1 = this .helpers .analyzeRequest (service , newRequest );
727+ newRequest = new String (newRequest ).substring (requestInfo1 .getBodyOffset ()).getBytes ();
728+ // 组装请求
729+ newRequest = this .helpers .buildHttpMessage (headers , newRequest );
730+ IHttpRequestResponse requestResponse = this .burpExtender .callbacks .makeHttpRequest (httpRequestResponse .getHttpService (), newRequest );
731+ String body = new String (requestResponse .getResponse ()).substring (this .helpers .analyzeResponse (requestResponse .getResponse ()).getBodyOffset ()).toLowerCase ();
732+ if (body .contains ("route_id" )) {
733+ this .burpExtender .stdout .println ("[*] Detect SpringGateway Finger: " + url );
734+ return true ;
735+ }
736+ } catch (MalformedURLException e ) {
737+ e .printStackTrace ();
738+ this .burpExtender .stderr .println (e .getMessage ());
739+ }
740+ return false ;
741+ }
742+
687743 /**
688744 * 随机Agent头
689745 * 先将原来的Agent删掉,再添加随机Agent
0 commit comments