crmeb/CRMEB

There is a ssrf vulnerability

Nmslgkd opened this issue · 2 comments

1.After downloading the source code, go to the get_image_base64 function in the app/api/controller/v1/PublicController.php file.
`/**

  • 获取图片base64
  • @param Request $request
  • @return mixed
    */
    public function get_image_base64(Request $request)
    {
    [$imageUrl, $codeUrl] = $request->postMore([
    ['image', ''],
    ['code', ''],
    ], true);
    try {
    $code = CacheService::get($codeUrl, function () use ($codeUrl) {
    $codeTmp = $code = $codeUrl ? image_to_base64($codeUrl) : false;
    if (!$codeTmp) {
    $putCodeUrl = put_image($codeUrl);
    $code = $putCodeUrl ? image_to_base64(app()->request->domain(true) . '/' . $putCodeUrl) : false;
    $code ?? unlink($_SERVER["DOCUMENT_ROOT"] . '/' . $putCodeUrl);
    }
    return $code;
    });
    $image = CacheService::get($imageUrl, function () use ($imageUrl) {
    $imageTmp = $image = $imageUrl ? image_to_base64($imageUrl) : false;
    if (!$imageTmp) {
    $putImageUrl = put_image($imageUrl);
    $image = $putImageUrl ? image_to_base64(app()->request->domain(true) . '/' . $putImageUrl) : false;
    $image ?? unlink($_SERVER["DOCUMENT_ROOT"] . '/' . $putImageUrl);
    }
    return $image;
    });
    return app('json')->successful(compact('code', 'image'));
    } catch (\Exception $e) {
    return app('json')->fail($e->getMessage());
    }
    }`

2.The function accepts an image parameter from the front end and assigns it to the variable $imageUrl
[$imageUrl, $codeUrl] = $request->postMore([ ['image', ''], ['code', ''], ], true);

3.Enter the image_to_base64 function by tracking the $imageUrl parameter
$codeTmp = $code = $codeUrl ? image_to_base64($codeUrl) : false;

4.$image_to_base64 function source code:
`/**

  • 获取图片转为base64
  • @param string $avatar
  • @return bool|string
    /
    function image_to_base64($avatar = '', $timeout = 9)
    {
    $avatar = str_replace('https', 'http', $avatar);
    try {
    $url = parse_url($avatar);
    $url = $url['host'];
    $header = [
    'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0',
    'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding: gzip, deflate, br',
    'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,
    /*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Host:' . $url
    ];
    $dir = pathinfo($url);
    $host = $dir['dirname'];
    $refer = $host . '/';
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_REFERER, $refer);
    curl_setopt($curl, CURLOPT_URL, $avatar);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    $data = curl_exec($curl);
    $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);
    if ($code == 200) {
    return "data:image/jpeg;base64," . base64_encode($data);
    } else {
    return false;
    }
    } catch (\Exception $e) {
    return false;
    }
    }`

5.Continue to track the $imageUrl variable ($avatar in the image_to_base64 function), you can find that the parameter $avatar is directly set to the request path of curl, and no filtering is done
curl_setopt($curl, CURLOPT_URL, $avatar);

6.Find the corresponding route in app/api/route/v1.php, and verify it after setting up the environment
Request a domain name in dnslog:
image-20221025000118012
Then construct the corresponding data packet:
image-20221025000311829
Request data received successfully:
image-20221025000346936