0

I found vulnerable end-points in my university's old portal. It should not be accessible but I found it somehow.

-> First end-point allows me to upload any kind of file on following path : /home/oracle/Oracle/uploads/candidate/

-> Second end-point allows me to download jpg files from server, but it can be bypassed by using null bytes (%00), so it lets me download any file from server. I downloaded files i.e /etc/passwd and /home/oracle/.bash_history. /etc/shadow is not accessible.

I am not java developer, I don't know how java applications work, their structure or anything.

What I tried

I can't traverse directories but from .bash_history, I found:

  /u01/app/oracle/product/Middleware/Weblogic1035/user_projects/domains/base_domain/bin/

By searching internet, and by exploring different log files such as :

  /u01/app/oracle/product/Middleware/Weblogic1035/user_projects/domains/base_domain/servers/AdminServer/logs/base_domain.log

In this log file I found path to EAR file, which from internet search seemed like source code, so I downloaded it from following path :

  /u01/app/oracle/product/Middleware/Weblogic1035/user_projects/domains/base_domain/servers/AdminServer/upload/Portal/app/Portal.ear

  /u01/app/oracle/product/Middleware/Weblogic1035/user_projects/domains/base_domain/servers/AdminServer/upload/Portal/Portal.xml

From here I found source code to upload file and download file, There are tons of file in Portal.ear, so I found these class files which were encoded in view folder, after deceypting them using online decryptor, following is code:

Download

package view;

import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.File;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;

public class imgServlet extends HttpServlet
{
    private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
    
    public void init(final ServletConfig config) throws ServletException {
        super.init(config);
    }
    
    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
        final String candid = request.getParameter("id");
        final OutputStream os = (OutputStream)response.getOutputStream();
        File f = new File(candid + ".jpg");
        if (f.exists()) {
            f = null;
            try {
                final InputStream is = new BufferedInputStream(new FileInputStream(candid + ".jpg"));
                final BufferedInputStream in = new BufferedInputStream(is);
                final byte[] buffer = new byte[10240];
                int b;
                while ((b = in.read(buffer, 0, 10240)) != -1) {
                    os.write(buffer, 0, b);
                }
                is.close();
                os.flush();
                os.close();
            }
            catch (Exception e) {
                System.out.println(e);
            }
        }
        else {
            f = null;
        }
    }
}

Upload

package view;

import oracle.adf.share.ADFContext;
import javax.faces.component.UIComponent;
import oracle.adf.view.rich.context.AdfFacesContext;
import javax.faces.event.ActionEvent;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.File;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.application.ViewHandler;
import javax.faces.context.FacesContext;
import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;
import java.io.InputStream;
import java.io.IOException;
import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.model.BindingContext;
import oracle.adf.view.rich.component.rich.output.RichImage;
import oracle.adf.view.rich.component.rich.input.RichInputFile;
import org.apache.myfaces.trinidad.model.UploadedFile;

public class ImageBean
{
    private UploadedFile upFile;
    private String fileName;
    private RichInputFile imageFile;
    private String user_img;
    private String notFoundInd;
    private String fileURL;
    private RichImage img;
    
    public ImageBean() {
        this.upFile = null;
        this.fileName = " ";
        this.notFoundInd = "";
    }
    
    public void setUpFile(final UploadedFile upFile) {
        this.upFile = upFile;
        InputStream inputStream = null;
        try {
            final BindingContext bindingContext = BindingContext.getCurrent();
            final OperationBinding op = this.getBindings().getOperationBinding("getEnviornmentValue");
            op.getParamsMap().put("var_nme", "IMG_DIR");
            this.fileURL = (String)op.execute();
            inputStream = upFile.getInputStream();
            final BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
            final DCIteratorBinding acdIter = (DCIteratorBinding)bindings.get((Object)"CandidateView2Iterator");
            final String candid = acdIter.getCurrentRow().getAttribute("CandId").toString();
            this.fileName = candid + ".jpg";
            if ("image/jpeg".equalsIgnoreCase(upFile.getContentType()) || "image/png".equalsIgnoreCase(upFile.getContentType())) {
                this.uploadFile(inputStream, this.fileURL, this.fileName);
                showADFDefaultPopup("Your Image has been uploaded");
                this.refreshPage();
            }
            else {
                showADFDefaultPopup("Invalid file format. Only JPG or PNG Files are allowed");
            }
        }
        catch (IOException e) {
            e.getMessage();
            showADFDefaultPopup("There is a problem picture is not uploaded");
        }
    }
    
    protected void refreshPage() {
        final FacesContext fc = FacesContext.getCurrentInstance();
        final String refreshpage = fc.getViewRoot().getViewId();
        final ViewHandler ViewH = fc.getApplication().getViewHandler();
        final UIViewRoot UIV = ViewH.createView(fc, refreshpage);
        UIV.setViewId(refreshpage);
        fc.setViewRoot(UIV);
    }
    
    public UploadedFile getUpFile() {
        return this.upFile;
    }
    
    private static void showADFDefaultPopup(final String text) {
        final FacesContext fcntx = FacesContext.getCurrentInstance();
        final FacesMessage popup = new FacesMessage(FacesMessage.SEVERITY_INFO, "", text);
        fcntx.addMessage((String)null, popup);
    }
    
    private void uploadFile(final InputStream inputStream, final String fileURL, final String fileName) throws IOException {
        OutputStream outputStream = null;
        final File outputFile = new File(fileURL + fileName);
        try {
            outputStream = new FileOutputStream(outputFile);
            int read = 0;
            final byte[] bytes = new byte[1024];
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            if (inputStream != null) {
                try {
                    inputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                }
                catch (IOException e2) {
                    e2.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                }
                catch (IOException e2) {
                    e2.printStackTrace();
                }
            }
        }
    }
    
    public void setFileURL(final String fileURL) {
        this.fileURL = fileURL;
    }
    
    public String getFileURL() {
        return this.fileURL;
    }
    
    public void setFileName(final String fileName) {
        this.fileName = fileName;
    }
    
    public String getFileName() {
        return this.fileName;
    }
    
    public void uploadImage(final ActionEvent actionEvent) {
        InputStream inputStream = null;
        try {
            inputStream = this.upFile.getInputStream();
            final BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
            final DCIteratorBinding acdIter = (DCIteratorBinding)bindings.get((Object)"CandidateView2Iterator");
            final String candid = acdIter.getCurrentRow().getAttribute("CandId").toString();
            this.fileName = candid + ".jpg";
            if ("image/jpeg".equalsIgnoreCase(this.upFile.getContentType()) || "image/png".equalsIgnoreCase(this.upFile.getContentType())) {
                this.uploadFile(inputStream, this.fileURL, this.fileName);
                showADFDefaultPopup("Your Image has been uploaded");
                AdfFacesContext.getCurrentInstance().addPartialTarget((UIComponent)this.img);
            }
            else {
                showADFDefaultPopup("Invalid file format. Only JPG or PNG Files are allowed");
            }
        }
        catch (IOException e) {
            e.getMessage();
            showADFDefaultPopup("There is a problem picture is not uploaded");
        }
    }
    
    public void setImageFile(final RichInputFile imageFile) {
        this.imageFile = imageFile;
    }
    
    public RichInputFile getImageFile() {
        return this.imageFile;
    }
    
    public void setNotFoundInd(final String notFoundInd) {
        final String baseURL = this.fileURL;
        final int candid = ADFContext.getCurrent().getSessionScope().get("candID");
        this.fileURL = this.fileURL + candid + ".jpg";
        final File f = new File(this.fileURL);
        if (f.isFile()) {
            this.notFoundInd = "found";
        }
        else {
            this.notFoundInd = "";
        }
    }
    
    public String getNotFoundInd() {
        final String baseURL = this.fileURL;
        final int candid = ADFContext.getCurrent().getSessionScope().get("candID");
        this.fileURL = this.fileURL + candid + ".jpg";
        final File f = new File(this.fileURL);
        if (f.isFile()) {
            this.notFoundInd = "found";
        }
        else {
            this.notFoundInd = "";
        }
        return this.notFoundInd;
    }
    
    public BindingContainer getBindings() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }
    
    public void setImg(final RichImage img) {
        this.img = img;
    }
    
    public RichImage getImg() {
        return this.img;
    }
}

This endpoint only allows image file upload, but there is another end point which is endpoint of universities's new portal that allows upload of all files on /home/oracle/Oracle/uploads/candidate/ but I don't have code for it.

What I want to achieve

I know there is LFI to RCE in PHP, but there is no apache here, so how can I achieve remote code execution in current scenario?. Once I have a valid proof of concept, I will report it to my HOD because for now he thinks, that it cant be further exploited

2 Answers 2

0

LFI (local file include) in PHP leads to RCE because user controlled file content is being parsed and executed via the include() function (https://www.php.net/manual/en/function.include.php) if the file was read via the file_get_contents() function (https://www.php.net/manual/en/function.file-get-contents) instead, it would not lead to RCE.

Since the code you're referencing doesn't eval() the file content like PHP's include() function does there is no direct path to RCE. You would need to use this function to read files and chain additional activities. For example you could leak application source code to identify additional vulnerabilities such as SQL injection or command injection. You could read "sensitive" files like /home/oracle/.ssh/id_rsa and try to login via ssh. However you are limited to files that a low privilege user can read since the web server/application isn't running as root (as it couldn't read /etc/shadow).

1
  • I found another flaw in server that allows me to run bash commands on it. I have questions regarding it but I will ask it new post, thanks
    – Abu Bakar
    Commented Jul 24, 2023 at 15:19
0

First end-point allows me to upload any kind of file on following path

If there's path traversal here (i.e. you can upload ../../foo/bar, then you could upload a JSP, WAR or EAR to the server. Just like you found the portal.ear with the source code, it's sometimes possible to upload your own web application to the server.

If you can only upload to .../candidate/, then there's not much you can do with this.

Second end-point allows me to download jpg files from server

This can be used to download source code and configuration. For Java webapps, the WEB-INF/web.xml file could be interesting. For Linux servers, files in /proc/self could be interesting.

Being able to download arbitrary files don't necessarily lead to RCE. However, in practice it often leads to so much information for an attacker that it makes it easy to exploit some other bug.

With PHP LFI, PHP code in the included file is also executed, but that is not the case here.

1
  • Yep I took same approach, I read all configuration files and logs and from there I found path to ear files, I downloaded them and from there I found another vulnerability in server. I was able to fully compromise that server using it. By the way, thanks
    – Abu Bakar
    Commented Jul 26, 2023 at 15:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .