[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fIyw_LovSr4klLUtAxyZcY3KZHfk7AZy5ECew7hpWc0c":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":51,"_status":50},334,"Why did the attempt to directly access the 'rctxt' field from a JettyJspServlet instance fail, and how did the article work around it?","The `rctxt` field is a private member of the parent class `JspServlet`, not inherited by `JettyJspServlet`. To access it, you must use `getSuperclass().getDeclaredField(\"rctxt\")` on the instance, as shown in the article's step-by-step reflection chain.","\u003Cp>The `rctxt` field is a private member of the parent class `JspServlet`, not inherited by `JettyJspServlet`. To access it, you must use `getSuperclass().getDeclaredField(&quot;rctxt&quot;)` on the instance, as shown in the article&#39;s step-by-step reflection chain.\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fjava-exploitation-techniques-modifying-properties-via-reflection\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","why-did-the-attempt-to-directly-access-the-rctxt-field-from-a-jettyjspservlet-in-1777484197198","getSuperclass, getDeclaredField, JettyJspServlet, JspServlet, inheritance",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},85,"Java Exploitation Techniques - Modifying Properties via Reflection","java-exploitation-techniques-modifying-properties-via-reflection","Learn Java reflection techniques for modifying properties and enumerating JspServletWrapper instances in Zimbra environments. Step-by-step implementation guide.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article 'Setting Up Zimbra Vulnerability Debugging Environment', we mentioned enumerating JspServletWrapper instances through reflection. This article will take that as an example to detail the implementation approach and specifics, facilitating extrapolation to implement other functionalities.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Common operations in reflection\u003C\u002Fli>\u003Cli>Obtaining all fields of a class\u003C\u002Fli>\u003Cli>Obtaining all methods of a class\u003C\u002Fli>\u003Cli>Invoking class methods\u003C\u002Fli>\u003Cli>Implementation details of enumerating JspServletWrapper instances\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Common Operations in Reflection\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Obtaining all fields of a class\u003C\u002Fh3>\u003Cp>getField():\u003C\u002Fp>\u003Cp>Can retrieve public fields from both this class and its parent class\u003C\u002Fp>\u003Cp>getDeclaredField():\u003C\u002Fp>\u003Cp>Can retrieve all fields from this class\u003C\u002Fp>\u003Cp>Here is an example code using the Zimbra environment as an example\u003C\u002Fp>\u003Ch4>(1) Get all fields of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Get all fields of the parent class of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getSuperclass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2. Get all methods of a class\u003C\u002Fh3>\u003Cp>getMethods():\u003C\u002Fp>\u003Cp>Can obtain public methods (modified by the public modifier) from this class as well as its parent class or parent interface\u003C\u002Fp>\u003Cp>getDeclaredMethods():\u003C\u002Fp>\u003Cp>Can obtain all methods in this class, including private, protected, default, and public methods\u003C\u002Fp>\u003Cp>Here, using the Zimbra environment as an example, provide sample code\u003C\u002Fp>\u003Ch4>(1) Get all methods of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method[] methods = request.getClass().getDeclaredMethods();\u003Cbr>    for(Method method:methods){\u003Cbr>        out.print(method.getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Get all methods of the parent class of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method[] methods = request.getClass().getSuperclass().getDeclaredMethods();\u003Cbr>    for(Method method:methods){\u003Cbr>        out.print(method.getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>3. Invoking specific methods of a class\u003C\u002Fh3>\u003Cp>Here, using the Zimbra environment as an example, sample code is provided\u003C\u002Fp>\u003Cp>After setting up the Zimbra vulnerability debugging environment, locate the getHeader(String name) method of the request object. The code details are as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>public String getHeader(String name) {\u003Cbr>    org.eclipse.jetty.http.MetaData.Request metadata = this._metaData;\u003Cbr>    return metadata == null ? null : metadata.getFields().get(name);\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Referring to the code details, the parameter type is String\u003C\u002Fp>\u003Cp>Invoke the getHeader(String name) method of the request object with the parameter \"User-Agent\". The implementation code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method m1 = request.getClass().getDeclaredMethod(\"getHeader\", String.class);\u003Cbr>    out.println(m1.invoke(request, \"User-Agent\")); \u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 Implementation Details of Enumerating JspServletWrapper Instances\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Setting Breakpoints\u003C\u002Fh3>\u003Cp>Select the file servlet-api-3.1.jar, then navigate to javax.servlet-&gt;http-&gt;HttpServlet.class. Set a breakpoint at an appropriate location. When execution reaches the breakpoint, you can view the complete structure of the request object, as shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018742428_0_c862fc79c1.jpeg\">\u003C\u002Fp>\u003Cp>By examining the structure of the request object, we ultimately located the position of the JspServletWrapper instance. The intuitive mapping is: request-&gt;_scope-&gt;_servlet-&gt;rctxt-&gt;jsps\u003C\u002Fp>\u003Cp>Next, we need to follow this mapping and obtain the JspServletWrapper instance through multiple reflections.\u003C\u002Fp>\u003Ch4>(1) Reading all fields of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getDeclaredFields();\u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Find _scope in the echoed results\u003C\u002Fp>\u003Ch4>(2) Obtain the _scope instance from the request object and enumerate its fields again\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    Field[] fields=obj1.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Find _servlet in the echoed results\u003C\u002Fp>\u003Ch4>(3) Obtain the _servlet instance and enumerate its fields again\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    Field[] fields=obj2.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The echo result is: serialVersionUID\u003C\u002Fp>\u003Cp>There is no rctxt field here\u003C\u002Fp>\u003Cp>Attempting to find the cause: Start the debugger and locate the key position, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018749725_1_d8abf0f1ab.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, the class of _servlet is JettyJspServlet\u003C\u002Fp>\u003Cp>JettyJspServlet inherits from JspServlet, and the only member variable is serialVersionUID, which is consistent with the results we obtained by accessing the JSP page\u003C\u002Fp>\u003Cp>Review the relevant implementation code of JspServlet, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018760627_2_64faef7cf3.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, rctxt is a member variable of JspServlet, with a private attribute, so the subclass JettyJspServlet cannot inherit the member variable rctxt\u003C\u002Fp>\u003Cp>Here we can directly select the parent class of the _servlet instance to enumerate fields\u003C\u002Fp>\u003Ch4>(4) Select the parent class of the _servlet instance to enumerate fields\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    Field[] fields = obj3.getClass().getDeclaredFields();\u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>jsps can be found in the echo results\u003C\u002Fp>\u003Ch4>(5) Obtain the jsps instance and enumerate fields\u003C\u002Fh4>\u003Cp>Open the debugger and check the type of jsps, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018776932_3_d387a3d4e7.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, the class of jsps is ConcurrentHashMap. Here, only all Keys need to be enumerated.\u003C\u002Fp>\u003Cp>After adding the required import packages, the final implementation code is obtained:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.concurrent.ConcurrentHashMap\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.*\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    f = obj3.getClass().getDeclaredField(\"jsps\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    ConcurrentHashMap obj4 = (ConcurrentHashMap)f.get(obj3);  \u003Cbr>    Enumeration enu = obj4.keys(); \u003Cbr>    while (enu.hasMoreElements()) { \u003Cbr>        out.println(enu.nextElement() + \"\u003Cbr>\"); \u003Cbr>    }  \u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>Note: Delete the specified JspServletWrapper instance\u003C\u002Fh3>\u003Cp>Simply call the remove method of ConcurrentHashMap\u003C\u002Fp>\u003Cp>Example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.concurrent.ConcurrentHashMap\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.*\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    f = obj3.getClass().getDeclaredField(\"jsps\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    ConcurrentHashMap obj4 = (ConcurrentHashMap)f.get(obj3);\u003Cbr>    obj4.remove(\"\u002Ftest.jsp\");\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the specific implementation of enumerating JspServletWrapper instances through reflection, documenting the approach and details to facilitate extrapolation for modifying other content.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article 'Setting Up Zimbra Vulnerability Debugging Environment', we mentioned enumerating JspServletWrapper instances through reflection. This article will take that as an example to detail the implementation approach and specifics, facilitating extrapolation to implement other functionalities.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Common operations in reflection\u003C\u002Fli>\u003Cli>Obtaining all fields of a class\u003C\u002Fli>\u003Cli>Obtaining all methods of a class\u003C\u002Fli>\u003Cli>Invoking class methods\u003C\u002Fli>\u003Cli>Implementation details of enumerating JspServletWrapper instances\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Common Operations in Reflection\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Obtaining all fields of a class\u003C\u002Fh3>\u003Cp>getField():\u003C\u002Fp>\u003Cp>Can retrieve public fields from both this class and its parent class\u003C\u002Fp>\u003Cp>getDeclaredField():\u003C\u002Fp>\u003Cp>Can retrieve all fields from this class\u003C\u002Fp>\u003Cp>Here is an example code using the Zimbra environment as an example\u003C\u002Fp>\u003Ch4>(1) Get all fields of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Get all fields of the parent class of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getSuperclass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2. Get all methods of a class\u003C\u002Fh3>\u003Cp>getMethods():\u003C\u002Fp>\u003Cp>Can obtain public methods (modified by the public modifier) from this class as well as its parent class or parent interface\u003C\u002Fp>\u003Cp>getDeclaredMethods():\u003C\u002Fp>\u003Cp>Can obtain all methods in this class, including private, protected, default, and public methods\u003C\u002Fp>\u003Cp>Here, using the Zimbra environment as an example, provide sample code\u003C\u002Fp>\u003Ch4>(1) Get all methods of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method[] methods = request.getClass().getDeclaredMethods();\u003Cbr>    for(Method method:methods){\u003Cbr>        out.print(method.getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Get all methods of the parent class of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method[] methods = request.getClass().getSuperclass().getDeclaredMethods();\u003Cbr>    for(Method method:methods){\u003Cbr>        out.print(method.getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>3. Invoking specific methods of a class\u003C\u002Fh3>\u003Cp>Here, using the Zimbra environment as an example, sample code is provided\u003C\u002Fp>\u003Cp>After setting up the Zimbra vulnerability debugging environment, locate the getHeader(String name) method of the request object. The code details are as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>public String getHeader(String name) {\u003Cbr>    org.eclipse.jetty.http.MetaData.Request metadata = this._metaData;\u003Cbr>    return metadata == null ? null : metadata.getFields().get(name);\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Referring to the code details, the parameter type is String\u003C\u002Fp>\u003Cp>Invoke the getHeader(String name) method of the request object with the parameter \"User-Agent\". The implementation code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field \"%&gt;\u003Cbr>&lt;%@ page import=\"java.lang.reflect.Method \"%&gt;\u003Cbr>&lt;%\u003Cbr>    Method m1 = request.getClass().getDeclaredMethod(\"getHeader\", String.class);\u003Cbr>    out.println(m1.invoke(request, \"User-Agent\")); \u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 Implementation Details of Enumerating JspServletWrapper Instances\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Setting Breakpoints\u003C\u002Fh3>\u003Cp>Select the file servlet-api-3.1.jar, then navigate to javax.servlet-&gt;http-&gt;HttpServlet.class. Set a breakpoint at an appropriate location. When execution reaches the breakpoint, you can view the complete structure of the request object, as shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018742428_0_c862fc79c1-1.jpeg\">\u003C\u002Fp>\u003Cp>By examining the structure of the request object, we ultimately located the position of the JspServletWrapper instance. The intuitive mapping is: request-&gt;_scope-&gt;_servlet-&gt;rctxt-&gt;jsps\u003C\u002Fp>\u003Cp>Next, we need to follow this mapping and obtain the JspServletWrapper instance through multiple reflections.\u003C\u002Fp>\u003Ch4>(1) Reading all fields of the request object\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%\u003Cbr>    Field[] fields=request.getClass().getDeclaredFields();\u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Find _scope in the echoed results\u003C\u002Fp>\u003Ch4>(2) Obtain the _scope instance from the request object and enumerate its fields again\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    Field[] fields=obj1.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Find _servlet in the echoed results\u003C\u002Fp>\u003Ch4>(3) Obtain the _servlet instance and enumerate its fields again\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    Field[] fields=obj2.getClass().getDeclaredFields();     \u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>\t}\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The echo result is: serialVersionUID\u003C\u002Fp>\u003Cp>There is no rctxt field here\u003C\u002Fp>\u003Cp>Attempting to find the cause: Start the debugger and locate the key position, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018749725_1_d8abf0f1ab-1.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, the class of _servlet is JettyJspServlet\u003C\u002Fp>\u003Cp>JettyJspServlet inherits from JspServlet, and the only member variable is serialVersionUID, which is consistent with the results we obtained by accessing the JSP page\u003C\u002Fp>\u003Cp>Review the relevant implementation code of JspServlet, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018760627_2_64faef7cf3-1.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, rctxt is a member variable of JspServlet, with a private attribute, so the subclass JettyJspServlet cannot inherit the member variable rctxt\u003C\u002Fp>\u003Cp>Here we can directly select the parent class of the _servlet instance to enumerate fields\u003C\u002Fp>\u003Ch4>(4) Select the parent class of the _servlet instance to enumerate fields\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    Field[] fields = obj3.getClass().getDeclaredFields();\u003Cbr>    for (int i = 0; i &lt; fields.length; i++) {\u003Cbr>        out.println(fields[i].getName() + \"\u003Cbr>\");\u003Cbr>    }\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>jsps can be found in the echo results\u003C\u002Fp>\u003Ch4>(5) Obtain the jsps instance and enumerate fields\u003C\u002Fh4>\u003Cp>Open the debugger and check the type of jsps, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018776932_3_d387a3d4e7-1.jpeg\">\u003C\u002Fp>\u003Cp>As can be seen from the figure, the class of jsps is ConcurrentHashMap. Here, only all Keys need to be enumerated.\u003C\u002Fp>\u003Cp>After adding the required import packages, the final implementation code is obtained:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.concurrent.ConcurrentHashMap\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.*\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    f = obj3.getClass().getDeclaredField(\"jsps\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    ConcurrentHashMap obj4 = (ConcurrentHashMap)f.get(obj3);  \u003Cbr>    Enumeration enu = obj4.keys(); \u003Cbr>    while (enu.hasMoreElements()) { \u003Cbr>        out.println(enu.nextElement() + \"\u003Cbr>\"); \u003Cbr>    }  \u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>Note: Delete the specified JspServletWrapper instance\u003C\u002Fh3>\u003Cp>Simply call the remove method of ConcurrentHashMap\u003C\u002Fp>\u003Cp>Example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>&lt;%@ page import=\"java.lang.reflect.Field\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.concurrent.ConcurrentHashMap\" %&gt;\u003Cbr>&lt;%@ page import=\"java.util.*\" %&gt;\u003Cbr>&lt;%       \u003Cbr>    Field f = request.getClass().getDeclaredField(\"_scope\");\u003Cbr>    f.setAccessible(true);  \u003Cbr>    Object obj1 = f.get(request);\u003Cbr>    f = obj1.getClass().getDeclaredField(\"_servlet\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj2 = f.get(obj1);\u003Cbr>    f = obj2.getClass().getSuperclass().getDeclaredField(\"rctxt\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    Object obj3 = f.get(obj2);\u003Cbr>    f = obj3.getClass().getDeclaredField(\"jsps\");\u003Cbr>    f.setAccessible(true);\u003Cbr>    ConcurrentHashMap obj4 = (ConcurrentHashMap)f.get(obj3);\u003Cbr>    obj4.remove(\"\u002Ftest.jsp\");\u003Cbr>%&gt;\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the specific implementation of enumerating JspServletWrapper instances through reflection, documenting the approach and details to facilitate extrapolation for modifying other content.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",1358,"Onedaysec",5,"published","2026-02-02T08:06:59.415Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Java Reflection Exploitation: Modifying Properties & Enumerating JspServletWrapper","Java exploitation, reflection techniques, JspServletWrapper, Zimbra vulnerability, debugging environment, field manipulation, method invocation",null,false,[],{"docs":43,"hasNextPage":40},[44,45,4,46],336,335,333,{"title":39,"description":39,"image":39},"2026-07-24T15:37:14.069Z","2026-07-23T16:01:24.337Z","draft","2026-07-23T16:05:26.250Z"]