I am writing a web app and I need to pass some url parameters as command line arguments to another script. What should I do to avoid security problems? I am using Sympfony's Process to execute the bash command and Laravel to build the app.
Here is some of the code, look into the buildScreenshotCommand to see how I am building the command string and also note that the $urlRequest is filled in using the Laravel's Request $request class:
<?php
namespace App\Logic;
use App\Logic\TimeHelper;
use App\UrlRequest;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
class Screenshot {
static function take(UrlRequest $urlRequest)
{
$name = self::generateName($urlRequest);
$command = self::buildScreenshotCommand($name, $urlRequest);
$startTime = TimeHelper::milliseconds();
$process = new Process($command);
$process->run();
$endTime = TimeHelper::milliseconds();
if (!$process->isSuccessful())
{
throw new ProcessFailedException($process);
}
$output = $process->getOutput();
if (trim($output) === '')
{
$urlRequest->successful = 1;
$file = self::uploadToS3($name);
$urlRequest->image_url = $file['url'];
$urlRequest->file_size = $file['size'];
$urlRequest->file_name = $name;
$urlRequest->time_it_took_to_take_screenshot_ms = $endTime - $startTime;
if ($urlRequest->save())
{
return $urlRequest;
}
}
else
{
$urlRequest->error = $output;
$urlRequest->save();
}
return false;
}
static function uploadToS3($name)
{
$name = 'screenshots/' . $name;
Storage::disk('s3')->put($name, Storage::disk('local')->get($name), ['visibility' => 'public']); // upload to S3
$fileSize = Storage::disk('local')->size($name);
Storage::disk('local')->delete($name);
return [
'url' => Storage::disk('s3')->url($name),
'size' => $fileSize
];
}
static function generateName($urlRequest)
{
$name = time() . rand(10000, 99999);
$extension = '.png';
if (isset($urlRequest->pdf) AND $urlRequest->pdf == 1)
{
$extension = '.pdf';
}
while (UrlRequest::where('file_name', '=', $name . $extension)->first())
{
$name = time() . rand(10000, 99999);
}
return $name . $extension;
}
static function buildScreenshotCommand($name, $urlRequest)
{
$command = 'cd ' . base_path() . ' && node puppeteer-screenshots-init.js ';
$command .= "--url={$urlRequest->url} ";
$fullPath = storage_path('app') . '/screenshots/' . $name;
$command .= "--path={$fullPath} ";
if (isset($urlRequest->pdf))
{
$command .= "--pdf=true ";
}
if (isset($urlRequest->viewport_width))
{
$command .= "--viewportWidth={$urlRequest->viewport_width} ";
}
if (isset($urlRequest->mobile))
{
$command .= '--mobile=true ';
}
if (isset($urlRequest->media_type_print))
{
$command .= '--mediaTypePrint=true ';
}
if (isset($urlRequest->user_agent))
{
$command .= '--userAgent="' . $urlRequest->user_agent . '" ';
}
$command .= '2>&1 &';
return $command;
}
}
I think this is a really bad idea. What if $urlRequest->url was:
// urlencoded
http%3A%2F%2Fgoogle.com%3F%3Brm+-Rf+%2F%3B
http://google.com?;rm -Rf /;
What kind of input sanitization are you doing?
Related
I have problem with file upload. Now I have something like this (part of Controller):
if($request->has('photos')) {
foreach ($request->photos as $photo) {
$filename = $photo->getClientOriginalName();
$tmp_name = $filename;
if ($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
} else {
$name = $filename;
}
$uniq_no = 0;
while (file_exists($filename)) {
$tmp_name = $name .'_'. $uniq_no . $ext;
$uniq_no++;
}
$photo->storeAs('public/photos/',$tmp_name);
Photo::create([
'page_id' => $page->id,
'filename' => $tmp_name
]);
}
}
but saves to the database without adding a unique number: filename_0, filename_1 etc. It just saves the value of $tmp_name.
What am I doing wrong?
I did something like this:
if($request->has('photos')) {
foreach ($request->photos as $photo) {
$file = $photo->getClientOriginalName();
$filename = pathinfo($file, PATHINFO_FILENAME).'_'.Str::random(6);
$extension = pathinfo($file, PATHINFO_EXTENSION);
$fullfilename = $filename .'.'. $extension;
$photo->storeAs('public/photos/',$fullfilename);
Photo::create([
'page_id' => $page->id,
'filename' => $fullfilename
]);
}
}
Schenario :
1) suppose that i have a database called myDataBase
2) Assume that myDataBase have some tables like A,B,C,D
3) i have to download the schema of the table A,B from the database with name myDataBase
Hope you have done the migration of all the table of your project . If you are using a xampp server then goto http://localhost/phpmyadmin and select your database and then goto export tab on the top tab bar and simply export with go button
<?php
//ENTER THE RELEVANT INFO BELOW
$mysqlUserName = "root";
$mysqlPassword = "";
$mysqlHostName = "localhost";
$DbName = "ukkoteknik";
$backup_name = "mybackup.sql";
$tables = array("admin", "sample");
Export_Database($mysqlHostName,$mysqlUserName,$mysqlPassword,$DbName, $tables, $backup_name=false );
function Export_Database($host,$user,$pass,$name, $tables=false, $backup_name=false )
{
$mysqli = new mysqli($host,$user,$pass,$name);
$mysqli->select_db($name);
$mysqli->query("SET NAMES 'utf8'");
$queryTables = $mysqli->query('SHOW TABLES');
while($row = $queryTables->fetch_row())
{
$target_tables[] = $row[0];
}
if($tables !== false)
{
$target_tables = array_intersect( $target_tables, $tables);
}
foreach($target_tables as $table)
{
$result = $mysqli->query('SELECT * FROM '.$table);
$fields_amount = $result->field_count;
$rows_num=$mysqli->affected_rows;
$res = $mysqli->query('SHOW CREATE TABLE '.$table);
$TableMLine = $res->fetch_row();
$content = (!isset($content) ? '' : $content) . "\n\n".$TableMLine[1].";\n\n";
for ($i = 0, $st_counter = 0; $i < $fields_amount; $i++, $st_counter=0)
{
while($row = $result->fetch_row())
{ //when started (and every after 100 command cycle):
if ($st_counter%100 == 0 || $st_counter == 0 )
{
$content .= "\nINSERT INTO ".$table." VALUES";
}
$content .= "\n(";
for($j=0; $j<$fields_amount; $j++)
{
$row[$j] = str_replace("\n","\\n", addslashes($row[$j]) );
if (isset($row[$j]))
{
$content .= '"'.$row[$j].'"' ;
}
else
{
$content .= '""';
}
if ($j<($fields_amount-1))
{
$content.= ',';
}
}
$content .=")";
//every after 100 command cycle [or at last line] ....p.s. but should be inserted 1 cycle eariler
if ( (($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num)
{
$content .= ";";
}
else
{
$content .= ",";
}
$st_counter=$st_counter+1;
}
} $content .="\n\n\n";
}
//$backup_name = $backup_name ? $backup_name : $name."___(".date('H-i-s')."_".date('d-m-Y').")__rand".rand(1,11111111).".sql";
$date = date("Y-m-d");
$backup_name = $backup_name ? $backup_name : $name.".$date.sql";
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"".$backup_name."\"");
//echo $content; exit;
}
?>
once guest user click on button "add to cart1", we are doing below things:
we are creating simple product programmatically
we are assigning custom image to that product.
Display one more pop up to Login to site by click on "login" button
once user click on "login button, we are doing below things:
we are creating simple product programmatically
we are not assigning custom image to that product.
but here we need to assign custom image to that product.
public function thisSimpleProductAndRedirectAction()
{
$originalProductId = $this->getRequest()->getParam("id");
// $productNameArray = explode(" - ",$this->getRequest()->getParam("id"));
// $originalProductId = $productNameArray[0];
$newImagePath = $this->getRequest()->getParam("image");
$originalProduct = Mage::getModel('catalog/product')->setStoreId(Mage::app()->getStore()->getId())->load($originalProductId);
if ($product = $this->_createProduct(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, true, $originalProduct, $newImagePath)) {
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode("custom image saving"));
}
else{
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode("custom image not saving"));
}
}
protected function _thisImage($type, $doSave = true, $originalProduct, $newImagePath = "")
{
// code for Guest
Mage::register('isSecureArea',true);
$session = Mage::getSingleton('customer/session');
$result = array(
'success' => false
);
$login ="";
$productId ="";
if ($this->getRequest()->isPost()) {
$login = $this->getRequest()->getPost('login');
$productId = $this->getRequest()->getPost('product_id');
}
// echo $login['product_id'];die;
// if (!empty($login['username']) && !empty($login['password'])) {
try {
if(isset($login) && (is_array($login) && !empty($login)) || ($login!="")){
$session->login($login['username'], $login['password']);
$result['redirect'] = $this->_getRefererUrl() ? $this->_getRefererUrl() : Mage::getUrl('customer/account', array(
'_secure' => true
));
$result['success'] = true;
$customerId = Mage::getSingleton('customer/session')->getCustomerId();
}
else{
$customerId = "";
}
// code for guest end
$product->setName($originalProduct->getName());
// add images
$images = array(
'thumbnail' => 'image.png', // displaying under cart page
'image' => 'image.png' // displaying under my design
);
foreach ($images as $imageType => $imageFileName) {
if ($newImagePath != "") {
$dir = Mage::getBaseDir('media') . DS . 'custom_product_preview/quote/';
$path = $dir . $newImagePath;
} else {
$dir = Mage::getBaseDir('media') . DS . 'example/amasty/';
$path = $dir . $imageFileName;
}
//echo $path."<br>";
if (file_exists($path)) {
try {
$product->addImageToMediaGallery($path, $imageType, false);
}
catch (Exception $e) {
echo $e->getMessage();
}
} else {
echo "Can not find image by path: `{$path}`<br/>";
}
}
$emailimage = Mage::helper('catalog/image')->init($product, 'thumbnail');
if ($doSave)
$product->save();
return $product;
// code for guest
}
catch (Mage_Core_Exception $e) {
switch ($e->getCode()) {
case Mage_Customer_Model_Customer::EXCEPTION_EMAIL_NOT_CONFIRMED:
$message = Mage::helper('customer')->__('This account is not confirmed. Click here to resend confirmation email.', Mage::helper('customer')->getEmailConfirmationUrl($login['username']));
break;
case Mage_Customer_Model_Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD:
$message = $e->getMessage();
break;
default:
$message = $e->getMessage();
}
$result['error'] = $message;
$session->setUsername($login['username']);
}
catch (Exception $e) {
$result = "ERROR :".$e->getMesage();
Mage::unregister('isSecureArea');
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
// code for guest end
}
You need to replace your code :
if ($newImagePath != "")
{
$dir = Mage::getBaseDir('media') . DS . 'custom_product_preview/quote/';
$path = $dir . $newImagePath;
}
else
{
$dir = Mage::getBaseDir('media') . DS . 'example/amasty/';
$path = $dir . $imageFileName;
}
with this code :
$path = '';
if ($newImagePath != "")
{
$dir = Mage::getBaseDir('media') . DS . 'custom_product_preview/quote/';
$path = $dir . $newImagePath;
}
else
{
$dir = Mage::getBaseDir('media') . DS . 'example/amasty/';
$path = $dir . $imageFileName;
}
In Code igniter Model I am using like query to fetch all the products having first name rice which is not working controller while using get_where('name') it works fine.
public function fetchdeal_products($id) {
$this->db->select('*');
$this->db->from('products');
$q = $this->db->like("name", $id);
if ($q->num_rows() > 0) {
foreach (($q->result()) as $row) {
$data[] = $row;
}
return $data;
}
}
I am using like query to fetch all the products having first name rice which is not working controller while using get_where('name') it works fine.
//Controller
function ajaxdealcategorydata($id = NULL) {
$this->sma->checkPermissions('index');
$id = $this->input->get('id');
$subcategories = $this->pos_model->getdealcategory($id);
$scats = '';
foreach ($subcategories as $category) {
$scats .= "<button id=\"subcategory-" . $category->id . "\" type=\"button\" value='" . $category->id . "' class=\"btn-prni subcategory\" ><img src=\"assets/uploads/thumbs/" . ($category->image ? $category->image : 'no_image.png') . "\" style='width:" . $this->Settings->twidth . "px;height:" . $this->Settings->theight . "px;' class='img-rounded img-thumbnail' /><span>" . $category->name . "</span></button>";
}
$products = $this->ajaxdealproducts($id);
if (!($tcp = $this->pos_model->products_count($id))) {
$tcp = 0;
}
echo json_encode(array('products' => $products, 'subcategories' => $scats, 'tcp' => $tcp));
}
I am using like query to fetch all the products having first name rice which is not working controller while using get_where('name') it works fine.
function ajaxdealproducts() {
$this->sma->checkPermissions('index');
if ($this->input->get('id') ) {
$id = $this->input->get('id');
} else {
$category_id = $this->pos_settings->default_category;
}
if ($this->input->get('subcategory_id')) {
$subcategory_id = $this->input->get('subcategory_id');
} else {
$subcategory_id = NULL;
}
if ($this->input->get('per_page') == 'n') {
$page = 0;
} else {
$page = $this->input->get('per_page');
}
$this->load->library("pagination");
$config = array();
$config["base_url"] = base_url() . "pos/ajaxdealproducts";
$config["total_rows"] = $subcategory_id ? $this->pos_model- >products_count($id, $subcategory_id) : $this->pos_model->products_count($id);
$config["per_page"] = $this->pos_settings->pro_limit;
$config['prev_link'] = FALSE;
$config['next_link'] = FALSE;
$config['display_pages'] = FALSE;
$config['first_link'] = FALSE;
$config['last_link'] = FALSE;
$this->pagination->initialize($config);
$products = $this->pos_model->fetchdeal_products($id, $config["per_page"], $page);
$pro = 1;
$prods = '<div>';
foreach ($products as $product) {
$count = $product->id;
if ($count < 10) {
$count = "0" . ($count / 100) * 100;
}
if ($category_id < 10) {
$category_id = "0" . ($category_id / 100) * 100;
}
$prods .= "<button id=\"product-" . $category_id . $count . "\" type=\"button\" value='" . $product->code . "' title=\"" . $product->name . "\" class=\"btn-prni btn-" . $this->pos_settings->product_button_color . " product pos-tip\" data-container=\"body\"><img src=\"" . base_url() . "assets/uploads/thumbs/" . $product->image . "\" alt=\"" . $product->name . "\" style='width:" . $this->Settings->twidth . "px;height:" . $this->Settings->theight . "px;' class='img-rounded' /><span>" . character_limiter($product->name, 15) . "</span></button>";
$pro++;
}
$prods .= "</div>";
if ($this->input->get('per_page')) {
echo $prods;
} else {
return $prods;
}
}
The database LIKE function only creates a LIKE in the SQL statement. You'll still need to call the GET mothod afterwards; Like this;
$this->db->like('name', $id);
$q = $this->db->get();
You are using $this->db_like() incorrectly.
$this->db->like('title', 'match');
// Produces: WHERE title LIKE '%match%'
(from documentation)
In your case the usage would be
$this->db->like('name', 'rice')
More info
public function fetchdeal_products($id)
{
$query = $this->db->query("Select products.* From products Where (products.name Like '%$id%')");
$result = $query->result_array();
return $result;
}
you have to write it as bellow.
public function fetchdeal_products($id) {
$this->db->like("name", $id);
$q = $this->db->get('products');
if ($q->num_rows() > 0) {
foreach (($q->result()) as $row) {
$data[] = $row;
}
return $data;
}
}
While i run a component i am getting 500 - An error has occurred error reading db in joomla.
My configuration file is perfect.
I don't know what else to change..
Any guidance will be helpful
Thanks in advance...
//No direct acesss
defined('_JEXEC') or die();
jimport('joomla.application.component.model');
class DealsModelDeals extends JModel {
function getDeals(){
$db = $this->getDBO();
$db->setQuery('SELECT * from #__todaysdeal');
$deals = $db->loadObjectList();
if ($deals === null)
JError::raiseError(500, 'Error reading db');
return $deals;
}
function getDeal($id){
$query = ' SELECT * FROM #__todaysdeal '. ' WHERE id = '.$id;
$db = $this->getDBO();
$db->setQuery($query);
$deal = $db->loadObject();
if ($deal === null)
JError::raiseError(500, 'Deal with ID: '.$id.' not found.');
else
return $deal;
}
/**
* Method that returns an empty greeting with id 0
*
* #access public
*/
function getNewDeal(){
$dealTableRow =& $this->getTable('deals');
$dealTableRow->id=0;
$dealTableRow->clientName='';
return $dealTableRow;
}
/**
* Method to store a greeting in the DB
*
* #access public
*/
function saveDeal($deal)
{
//Parameter not necessary because our model is named DealsModelDeals (used to ilustrate that you can specify an alternative name to the JTable extending class)
$dealTableRow =& $this->getTable('deals');
//print_r($dealTableRow);
//print_r($_FILES); exit;
// Bind the form fields to the todaysdeal table
if (!$dealTableRow->bind($deal)) {
JError::raiseError(500, 'Error binding data');
}
// Make sure the deal record is valid
if (!$dealTableRow->check()) {
JError::raiseError(500, 'Invalid data');
}
// Insert/update this record in the db
if (!$dealTableRow->store()) {
$errorMessage = $dealTableRow->getError();
JError::raiseError(500, 'Error binding data: '.$errorMessage);
}
$id = $dealTableRow->id;
if(!empty($_FILES['dealImage']))
{
$file = $_FILES['dealImage'];
$id = $dealTableRow->id;
if ((($_FILES["dealImage"]["type"] == "image/gif") || ($_FILES["dealImage"]["type"] == "image/jpeg") || ($_FILES["dealImage"]["type"] == "image/pjpeg")) && ($_FILES["dealImage"]["size"] < 150000))
{
if ($_FILES["dealImage"]["error"] > 0)
{
echo "Return Code: " . $_FILES["dealImage"]["error"] . "<br />";
}
else
{
if (file_exists("components/com_deals/dealImages/" . $_FILES["dealImage"]["name"])) {
$_FILES["dealImage"]["name"] . " already exists. ";
} else {
move_uploaded_file($_FILES["dealImage"]["tmp_name"], "components/com_deals/dealImages/" .$id."_".$_FILES["dealImage"]["name"]);
echo "Stored in: " . "dealImages/" . $_FILES["dealImage"]["name"];
}
}
}
else
{
}
}
$dealImage = $_FILES['dealImage']['name'];
$dealImage .= (!empty($_FILES['dealImage']['name'])) ? ' ' . $_FILES['dealImage']['name'] : '';
$query = "UPDATE #__todaysdeal SET dealImage='".$id."_".$_FILES['dealImage']['name']."' WHERE id='".$id."'";
$db = $this->getDBO();
$db->setQuery($query);
$db->query();
//If we get here and with no raiseErrors, then everythign went well
}
function deleteDeals($arrayIDs)
{
$query = "DELETE FROM #__todaysdeal WHERE id IN (".implode(',', $arrayIDs).")";
$db = $this->getDBO();
$db->setQuery($query);
if (!$db->query()){
$errorMessage = $this->getDBO()->getErrorMsg();
JError::raiseError(500, 'Error deleting Deals: '.$errorMessage);
}
}
function dealsUploadPhoto($file, $id)
{
//UPLOAD FILE
$config = & JComponentHelper::getParams('com_deals');
$allowed = array('image/pjpeg', 'image/jpeg', 'image/jpg', 'image/png', 'image/x-png', 'image/gif', 'image/ico', 'image/x-icon');
$pwidth = $config->get('pwidth');
$pheight = $config->get('pheight');
$maxsize = $config->get('maxsize');
if($file['size'] > 0 && ($file['size'] / 1024 < $maxsize)){
if(!file_exists(JPATH_SITE . DS. 'images' . DS . 'deals'))
{
if(mkdir(JPATH_SITE . DS . 'images' . DS . 'deals')) {
JPath::setPermissions(JPATH_SITE . DS . 'images' . DS . 'deals', '0777');
if(file_exists(JPATH_SITE . DS . 'images' . DS . 'index.html')) {
copy(JPATH_SITE . DS . 'images' . DS . 'index.html', JPATH_SITE . DS . 'images' . DS . 'deals/index.html');
}
}
}
if($file['error'] != 0){
tpJobsMsgAlert('Upload file photo error.');
exit ();
}
if($file['size'] == 0){
$file = null;
}
if(!in_array($file['type'], $allowed)) {
$file = null;
}
if ($file != null){
$dest = JPATH_SITE.DS.'images'.DS.'deals'.DS.$id.'.jpg';
if(file_exists($dest))
{
$del = unlink($dest);
}
$soure = $file['tmp_name'];
jimport('joomla.filesystem.file');
$uploaded = JFile::upload($soure,$dest);
$fileAtr = getimagesize($dest);
$widthOri = $fileAtr[0];
$heightOri = $fileAtr[1];
$type = $fileAtr['mime'];
$img = false;
switch ($type)
{
case 'image/jpeg':
case 'image/jpg':
case 'image/pjpeg':
$img = imagecreatefromjpeg($dest);
break;
case 'image/ico':
$img = imagecreatefromico($dest);
break;
case 'image/x-png':
case 'image/png':
$img = imagecreatefrompng($dest);
break;
case 'image/gif':
$img = imagecreatefromgif($dest);
break;
}
if(!$img)
{
return false;
}
$curr = #getimagesize($dest);
$perc_w = $pwidth / $widthOri;
$perc_h = $pheight / $heightOri;
if(($widthOri<$pwidth) && ($heightOri<$height))
{
return;
}
if($perc_h > $perc_w)
{
$pwidth = $pwidth;
$pheight = round($heightOri * $perc_w);
}
else
{
$pheight = $pheight;
$pwidth = round($widthOri * $perc_h);
}
$nwimg = imagecreatetruecolor($pwidth, $pheight);
imagecopyresampled($nwimg, $img, 0, 0, 0, 0, $pwidth, $pheight, $widthOri, $heightOri);
imagejpeg($nwimg, $dest, 100);
imagedestroy($nwimg);
imagedestroy($img);
}
}else{
if($file['size'] / 1024 > $maxsize){
dealsMsgAlert('Size of file photo is too big. Maximum size".$maxsize." KB');
exit ();
}
}
}
function dealsMsgAlert($msg)
{
if (!headers_sent())
{
while(#ob_end_clean());
ob_start();
echo "<script> alert('".$msg."'); window.history.go(-1); </script>\n";
$out = ob_get_contents();
ob_end_clean();
echo $out;
exit();
}
echo "<script> alert('".$msg."'); window.history.go(-1); </script>\n";
exit();
}
}
?>
The problem that causes the red screen with 500 Error is happening because you are raising an exception if the requested quote is does not exist. You should not use JError::raiseError().
Use one of the following instead:
// This will set error to the model. You can get the errors from
// the model by your controller $model->getErrors() and output them to the screen.
$this->setError('ERROR MESSAGE GOES HERE');
OR
// This will output errors to the screen right the way
JFactory::getApplication()->enqueueMessage('ERROR MESSAGE GOES HERE', 'message');
Model already has _db property, you do not need to get db into variable. You can access it like this $this->_db. You can read about Joomla Model class here.
Also within your model you are using
$db = $this->getDBO();
$db->setQuery('SELECT * from #__todaysdeal');
$deals = $db->loadObjectList();
Model has simplified method to load list of object, like so
$deals =& $this->_getList('SELECT * from #__todaysdeal');