专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 Struts2漏洞修复方案

Struts2漏洞修复方案

更新时间:2022-02-10 09:03:09 来源:赢咖4 浏览1011次

由于struts包由2.3.?升级到2.5.16,很多依赖包、配置需要响应调整。找了个总结的:

1.2.5.X版本不再提供xwork.jar ,整合到了 struts-core包中。

2.方法不能访问的问题,需要在每个action配置文件中加上 strict-method-invocation="false":

<package name="login" namespace="/login" extends="struts-default" strict-method-invocation="false">

并修改strut2.xml配置文件头部为2.5版本的:

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"><struts>

3.session失效的问题,针对weblogic server,增加session-descriptor节点:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90">
<context-root>/ynwjnw</context-root>
<container-descriptor>
<servlet-reload-check-secs>-1</servlet-reload-check-secs>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
<session-descriptor>
<cookie-name>JSESSIONID1</cookie-name>
</session-descriptor>
</weblogic-web-app>

4.2.5.16版本jdk要求1.7。1.8版本编译后部署有问题

web.xml中

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

修改为

org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter

5.struts2对multipart/form-data解析需要自定义方法解析,否则丢失表单参数。

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
        name="requestParser" class="com.***.omp.***.util.MyMultiPartRequest"
        scope="default"/>

由于xwork做了大改,AbstractMultiPartRequest类的一些属性和方法也修改了。MyMultiPartRequest类也需要相应调整。

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; 
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.LocalizedMessage;
import org.apache.struts2.dispatcher.multipart.AbstractMultiPartRequest;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;
import org.apache.struts2.dispatcher.multipart.StrutsUploadedFile;
import org.apache.struts2.dispatcher.multipart.UploadedFile; 
public class MyMultiPartRequest extends AbstractMultiPartRequest{          
        static final Logger LOG = LogManager.getLogger(JakartaMultiPartRequest.class); 
        // maps parameter name -> List of FileItem objects
        protected Map<String, List<FileItem>> files = new HashMap<String, List<FileItem>>(); 
        // maps parameter name -> List of param values
        protected Map<String, List<String>> params = new HashMap<>(); 
        // any errors while processing this request
        protected List<LocalizedMessage> errors = new ArrayList<LocalizedMessage>(); 
//      protected long maxSize;
//      private Locale defaultLocale = Locale.ENGLISH; 
        /**
         * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
         * multipart classes (see class description).
         * @param saveDir the directory to save off the file
         * @param request the request containing the multipart
         * @throws java.io.IOException is thrown if encoding fails.
         */
        public void parse(HttpServletRequest request, String saveDir) throws IOException {
            try {
                setLocale(request);
                processUpload(request, saveDir);
            } catch (FileUploadBase.SizeLimitExceededException e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Request exceeded size limit!", e);
                }
                LocalizedMessage errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});
                if (!errors.contains(errorMessage)) {
                    errors.add(errorMessage);
                }
            } catch (Exception e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Unable to parse request", e);
                }
                LocalizedMessage errorMessage = buildErrorMessage(e, new Object[]{});
                if (!errors.contains(errorMessage)) {
                    errors.add(errorMessage);
                }
            }
        } 
        protected void setLocale(HttpServletRequest request) {
            if (defaultLocale == null) {
                defaultLocale = request.getLocale();
            }
        } 
        protected LocalizedMessage buildErrorMessage(Throwable e, Object[] args) {
            String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
            LOG.debug("Preparing error message for key: [{}]", errorKey); 
            return new LocalizedMessage(this.getClass(), errorKey, e.getMessage(), args);
        } 
        private void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
            for (FileItem item : parseRequest(request, saveDir)) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Found item " + item.getFieldName());
                }
                if (item.isFormField()) {
                    processNormalFormField(item, request.getCharacterEncoding());
                } else {
                    processFileField(item);
                }
            }
        } 
        private void processFileField(FileItem item) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Item is a file upload");
            } 
            // Skip file uploads that don't have a file name - meaning that no file was selected.
            if (item.getName() == null || item.getName().trim().length() < 1) {
                LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
                return;
            } 
            List<FileItem> values;
            if (files.get(item.getFieldName()) != null) {
                values = files.get(item.getFieldName());
            } else {
                values = new ArrayList<FileItem>();
            } 
            values.add(item);
            files.put(item.getFieldName(), values);
        } 
        private void processNormalFormField(FileItem item, String charset) throws UnsupportedEncodingException {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Item is a normal form field");
            }
            List<String> values;
            if (params.get(item.getFieldName()) != null) {
                values = params.get(item.getFieldName());
            } else {
                values = new ArrayList<String>();
            } 
            // note: see http://jira.opensymphony.com/browse/WW-633
            // basically, in some cases the charset may be null, so
            // we're just going to try to "other" method (no idea if this
            // will work)
            if (charset != null) {
                values.add(item.getString(charset));
            } else {
                values.add(item.getString());
            }
            params.put(item.getFieldName(), values);
            item.delete();
        } 
        private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
            DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
            ServletFileUpload upload = new ServletFileUpload(fac);
            upload.setSizeMax(maxSize);
            // 设置监听器
            FileUploadListener progressListener = new FileUploadListener(servletRequest);
            upload.setProgressListener(progressListener);
            return upload.parseRequest(createRequestContext(servletRequest));
        } 
        private DiskFileItemFactory createDiskFileItemFactory(String saveDir) {
            DiskFileItemFactory fac = new DiskFileItemFactory();
            // Make sure that the data is written to file
            fac.setSizeThreshold(0);
            if (saveDir != null) {
                fac.setRepository(new File(saveDir));
            }
            return fac;
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileParameterNames()
         */
        public Enumeration<String> getFileParameterNames() {
            return Collections.enumeration(files.keySet());
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
         */
        public String[] getContentType(String fieldName) {
            List<FileItem> items = files.get(fieldName); 
            if (items == null) {
                return null;
            } 
            List<String> contentTypes = new ArrayList<String>(items.size());
            for (FileItem fileItem : items) {
                contentTypes.add(fileItem.getContentType());
            } 
            return contentTypes.toArray(new String[contentTypes.size()]);
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
         */
        public UploadedFile[] getFile(String fieldName) {
            List<FileItem> items = files.get(fieldName); 
            if (items == null) {
                return null;
            } 
            List<UploadedFile> fileList = new ArrayList<>(items.size());
            for (FileItem fileItem : items) {
                File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
                if (fileItem.isInMemory() && storeLocation != null && !storeLocation.exists()) {
                    try {
                        storeLocation.createNewFile();
                    } catch (IOException e) {
                        LOG.error("Cannot write uploaded empty file to disk: {}", storeLocation.getAbsolutePath(), e);
                    }
                }
                fileList.add(new StrutsUploadedFile(storeLocation));
            } 
            return fileList.toArray(new UploadedFile[fileList.size()]);
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(java.lang.String)
         */
        public String[] getFileNames(String fieldName) {
            List<FileItem> items = files.get(fieldName); 
            if (items == null) {
                return null;
            } 
            List<String> fileNames = new ArrayList<String>(items.size());
            for (FileItem fileItem : items) {
                fileNames.add(getCanonicalName(fileItem.getName()));
            } 
            return fileNames.toArray(new String[fileNames.size()]);
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
         */
        public String[] getFilesystemName(String fieldName) {
            List<FileItem> items = files.get(fieldName); 
            if (items == null) {
                return null;
            } 
            List<String> fileNames = new ArrayList<String>(items.size());
            for (FileItem fileItem : items) {
                fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
            } 
            return fileNames.toArray(new String[fileNames.size()]);
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
         */
        public String getParameter(String name) {
            List<String> v = params.get(name);
            if (v != null && v.size() > 0) {
                return v.get(0);
            } 
            return null;
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterNames()
         */
        public Enumeration<String> getParameterNames() {
            return Collections.enumeration(params.keySet());
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterValues(java.lang.String)
         */
        public String[] getParameterValues(String name) {
            List<String> v = params.get(name);
            if (v != null && v.size() > 0) {
                return v.toArray(new String[v.size()]);
            } 
            return null;
        } 
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
         */
        public List<LocalizedMessage> getErrors() {
            return errors;
        } 
        /**
         * Returns the canonical name of the given file.
         *
         * @param filename the given file
         * @return the canonical name of the given file
         */
//      private String getCanonicalName(String filename) {
//          int forwardSlash = filename.lastIndexOf("/");
//          int backwardSlash = filename.lastIndexOf("\\");
//          if (forwardSlash != -1 && forwardSlash > backwardSlash) {
//              filename = filename.substring(forwardSlash + 1, filename.length());
//          } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
//              filename = filename.substring(backwardSlash + 1, filename.length());
//          }
//          return filename;
//      } 
        /**
         * Creates a RequestContext needed by Jakarta Commons Upload.
         *
         * @param req the request.
         * @return a new request context.
         */
        private RequestContext createRequestContext(final HttpServletRequest req) {
            return new RequestContext() {
                public String getCharacterEncoding() {
                    return req.getCharacterEncoding();
                } 
                public String getContentType() {
                    return req.getContentType();
                } 
                public int getContentLength() {
                    return req.getContentLength();
                } 
                public InputStream getInputStream() throws IOException {
                    InputStream in = req.getInputStream();
                    if (in == null) {
                        throw new IOException("Missing content in the request");
                    }
                    return req.getInputStream();
                }
            };
        } 
        /* (non-Javadoc)
        * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#cleanUp()
        */
        public void cleanUp() {
            Set<String> names = files.keySet();
            for (String name : names) {
                List<FileItem> items = files.get(name);
                for (FileItem item : items) {
                    LOG.debug("Removing file {} {}", name, item );
                    if (!item.isInMemory()) {
                        item.delete();
                    }
                }
            }
        } 
}

以上就是关于“Struts2漏洞修复方案”的介绍,大家如果想了解更多相关知识,可以关注一下赢咖4的Java视频,里面的课程内容细致全面,从入门到精通,适合没有基础的小伙伴学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>