Merge pull request #32 from Dan-Q/master

Fix the fix to path traversal attack, refactor
This commit is contained in:
Christian Haschek 2021-08-12 23:17:40 +02:00 committed by GitHub
commit 21cb765dc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 21 deletions

View file

@ -8,7 +8,16 @@ ini_set('display_errors', 1);
include_once(ROOT.DS.'inc'.DS.'core.php'); include_once(ROOT.DS.'inc'.DS.'core.php');
$action = strtolower($_REQUEST['a']); $action = strtolower($_REQUEST['a']);
$email = basename(realpath(strtolower($_REQUEST['email']))); $email = strtolower($_REQUEST['email']);
if(!empty($email)){
if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
// email param provided, but invalid: skip action and show invalid email error
$o = array('status'=>'err','reason'=>'Invalid Email address');
unset($action);
}
$dir = getDirForEmail($email);
$email = basename($dir);
}
switch($action) switch($action)
{ {
@ -18,12 +27,10 @@ switch($action)
$o = explode(',',$settings['DOMAINS']); $o = explode(',',$settings['DOMAINS']);
break; break;
case 'attachment': case 'attachment':
$id = $_REQUEST['id']; $id = intval($_REQUEST['id']);
$filename = basename(realpath($_REQUEST['filename'])); $filename = basename(realpath($_REQUEST['filename']));
$filepath = ROOT.DS.'..'.DS.'data'.DS.$email.DS.'attachments'.DS.$id.'-'.$filename; $filepath = $dir.DS.'attachments'.DS.$id.'-'.$filename;
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) if(!is_dir($dir))
$o = array('status'=>'err','reason'=>'Invalid Email address');
else if(!is_dir(ROOT.DS.'..'.DS.'data'.DS.$email))
$o = array('status'=>'err','reason'=>'No emails received on this address'); $o = array('status'=>'err','reason'=>'No emails received on this address');
else if(!is_numeric($id) || !emailIDExists($email,$id)) else if(!is_numeric($id) || !emailIDExists($email,$id))
$o = array('status'=>'err','reason'=>'Invalid Email ID'); $o = array('status'=>'err','reason'=>'Invalid Email ID');
@ -38,10 +45,10 @@ switch($action)
break; break;
case 'load': case 'load':
$id = $_REQUEST['id']; $id = intval($_REQUEST['id']);
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) if(empty($email))
$o = array('status'=>'err','reason'=>'Invalid Email address'); $o = array('status'=>'err','reason'=>'No email address provided');
else if(!is_dir(ROOT.DS.'..'.DS.'data'.DS.$email)) else if(!is_dir($dir))
$o = array('status'=>'err','reason'=>'No emails received on this address'); $o = array('status'=>'err','reason'=>'No emails received on this address');
else if(!is_numeric($id) || !emailIDExists($email,$id)) else if(!is_numeric($id) || !emailIDExists($email,$id))
$o = array('status'=>'err','reason'=>'Invalid Email ID'); $o = array('status'=>'err','reason'=>'Invalid Email ID');
@ -58,14 +65,12 @@ switch($action)
break; break;
case 'list': case 'list':
$settings = loadSettings(); $settings = loadSettings();
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) if($settings['ADMIN'] && $settings['ADMIN']==$email)
$o = array('status'=>'err','reason'=>'Invalid Email address');
else if($settings['ADMIN'] && $settings['ADMIN']==$email)
{ {
$o['status'] = 'ok'; $o['status'] = 'ok';
$o['type'] = 'admin'; $o['type'] = 'admin';
$o['dateformat'] = $settings['DATEFORMAT']; $o['dateformat'] = $settings['DATEFORMAT'];
$emails = listEmailAdresses(); $emails = listEmailAdresses();
$emaillist = array(); $emaillist = array();
@ -86,7 +91,7 @@ switch($action)
$o['emails']=$data; $o['emails']=$data;
} }
else if(!is_dir(ROOT.DS.'..'.DS.'data'.DS.$email)) else if(!is_dir($dir))
$o = array('status'=>'ok','emails'=>[]); $o = array('status'=>'ok','emails'=>[]);
else else
{ {

View file

@ -1,5 +1,10 @@
<?php <?php
function getDirForEmail($email)
{
return realpath(ROOT.DS.'..'.DS.'data'.DS.$email);
}
function startsWith($haystack, $needle) function startsWith($haystack, $needle)
{ {
$length = strlen($needle); $length = strlen($needle);
@ -18,22 +23,22 @@ function endsWith($haystack, $needle)
function getEmail($email,$id) function getEmail($email,$id)
{ {
return json_decode(file_get_contents(ROOT.DS.'..'.DS.'data'.DS.$email.DS.$id.'.json'),true); return json_decode(file_get_contents(getDirForEmail($email).DS.$id.'.json'),true);
} }
function emailIDExists($email,$id) function emailIDExists($email,$id)
{ {
return file_exists(ROOT.DS.'..'.DS.'data'.DS.$email.DS.$id.'.json'); return file_exists(getDirForEmail($email).DS.$id.'.json');
} }
function getEmailsOfEmail($email) function getEmailsOfEmail($email)
{ {
$o = false; $o = false;
if ($handle = opendir(ROOT.DS.'..'.DS.'data'.DS.$email)) { if ($handle = opendir(getDirForEmail($email))) {
while (false !== ($entry = readdir($handle))) { while (false !== ($entry = readdir($handle))) {
if (endsWith($entry,'.json')) { if (endsWith($entry,'.json')) {
$time = substr($entry,0,-5); $time = substr($entry,0,-5);
$json = json_decode(file_get_contents(ROOT.DS.'..'.DS.'data'.DS.$email.DS.$entry),true); $json = json_decode(file_get_contents(getDirForEmail($email).DS.$entry),true);
$o[$time] = array('from'=>$json['parsed']['from'],'subject'=>$json['parsed']['subject']); $o[$time] = array('from'=>$json['parsed']['from'],'subject'=>$json['parsed']['subject']);
} }
} }
@ -66,4 +71,4 @@ function loadSettings()
if(file_exists(ROOT.DS.'..'.DS.'config.ini')) if(file_exists(ROOT.DS.'..'.DS.'config.ini'))
return parse_ini_file(ROOT.DS.'..'.DS.'config.ini'); return parse_ini_file(ROOT.DS.'..'.DS.'config.ini');
return false; return false;
} }