Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The functionality change image allows access to local ports (SSRF). #1233

Open
Retr02332 opened this issue Jan 14, 2022 · 0 comments
Open

The functionality change image allows access to local ports (SSRF). #1233

Retr02332 opened this issue Jan 14, 2022 · 0 comments
Labels
Bug needs-triage incoming, please sort

Comments

@Retr02332
Copy link

Bug description

In PartKeepr before v1.4.0, the functionality to upload attachments using a URL when creating a part, does not validate that requests can be send to local ports, allowing SSRF attacks and port enumeration.

Steps to reproduce

  1. Go to 'Edit'.
  2. Click on 'Storage Locations'.
  3. Click on 'Add Storage Locations'.
  4. Click on 'Change Image'.
  5. Fill the 'URL' field with an url using a local port "http:///127.0.0.1:8".
  6. You will see a server error indicating that the server did indeed attempt to connect to itself (thus supporting Blind SSRF).

Expected behavior

The application should not allow access to local ports.

Observed behavior

Local ports can be access inside the server.

Vulnerable code

  • public function uploadAction(Request $request)
    {
    $image = new TempImage();
    $imageService = $this->get('partkeepr_image_service');
    if ($request->files->has('userfile') && $request->files->get('userfile') != null) {
    $file = $request->files->get('userfile');
    /*
    * @var $file UploadedFile
    */
    $imageService->replace($image, new File($file->getPathname()));
    $image->setOriginalFilename($file->getClientOriginalName());
    } elseif ($request->request->has('url')) {
    $imageService->replaceFromURL($image, $request->request->get('url'));
    } else {
    throw new \Exception('Error: No valid file given');
    }
    $this->getDoctrine()->getManager()->persist($image);
    $this->getDoctrine()->getManager()->flush();
    /**
    * @var ResourceInterface
    */
    list($resourceType) = $this->extractAttributes($request);
    $serializedData = $this->get('serializer')->normalize(
    $image,
    'jsonld',
    $resourceType->getNormalizationContext()
    );
    return new JsonResponse(new TemporaryImageUploadResponse($serializedData));
    }

  • public function replaceFromURL(UploadedFile $file, $url)
    {
    /* Some sites don't like automated requests. But the internet is meant to be open for anybody,
    * even for scripts. So we are evil and fake the headers.
    *
    * Credit goes to Ryan Rampersad from whom I copied most code.
    * http://blog.ryanrampersad.com/2008/11/07/get-remote-html-with-curl-and-php/
    */
    $curl = curl_init();
    $header[0] = 'Accept: text/xml,application/xml,application/xhtml+xml,';
    $header[0] .= 'text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
    $header[] = 'Cache-Control: max-age=0';
    $header[] = 'Connection: keep-alive';
    $header[] = 'Keep-Alive: 300';
    $header[] = 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7';
    $header[] = 'Accept-Language: en-us,en;q=0.5';
    $header[] = 'Pragma: ';
    $browser = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 ';
    $browser .= 'Ubuntu/8.04 (hardy) Firefox/3.0.3';
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_USERAGENT, $browser);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_AUTOREFERER, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    curl_setopt($curl, CURLOPT_MAXREDIRS, 7);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    $data = curl_exec($curl);
    if ($data === false) {
    $curlError = curl_error($curl);
    // Strip ANY tags from the error message. curl tends to spit out <url> is not valid, which then
    // confuses the error message parser on the client side.
    $curlError = str_replace(['>', '<'], '', $curlError);
    throw new \Exception('replaceFromURL error: '.$curlError);
    }
    curl_close($curl);
    $this->replaceFromData($file, $data, basename($url));
    }

Screenshots

blind_ssrf

POC Video

poc_blind_ssrf.mp4

System Information

PartKeepr Version: v1.4.0
Operating System: Linux
Web Server: Apache
PHP Version: 7.4
Database and version: Mysql
Reproducible on the demo system: Yes.

@Retr02332 Retr02332 added Bug needs-triage incoming, please sort labels Jan 14, 2022
@Retr02332 Retr02332 changed the title The functionality change image to parts allows access to local ports (Blind SSRF). The functionality change image allows access to local ports (Blind SSRF). Jan 14, 2022
@Retr02332 Retr02332 changed the title The functionality change image allows access to local ports (Blind SSRF). The functionality change image allows access to local ports (SSRF). Jan 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug needs-triage incoming, please sort
Projects
None yet
Development

No branches or pull requests

1 participant