Exploiting fopen when input has extension appended - php

For science.
Say I have the following code:
<?php
$filename = $_GET['filename'] . '.csv';
$handle = #fopen($filename);
We know that the null byte exploit is long gone, but is it possible to get around the above appending of .csv, in order to read a file with another extension? Very creative souls exist.
Reading remote files works, filename=http://example.com/some.csv (.csv is appended automatically).

If you query for http://example.com/some.pdf?csv, fopen will try to gather the pdf file...
Rather use regex to validate $_GET (you should always validate your input):
/(\.csv)$/g will help you validate whether the extension is .csv

Related

How to read any of the file type using php7?

I have tried to extract the user email addresses from my server. But the problem is maximum files are .txt but some are CSV files with txt extension. When I am trying to read and extract, I could not able to read the CSV files which with TXT extension. Here is my code:
<?php
$handle = fopen('2.txt', "r");
while(!feof($handle)) {
$string = fgets($handle);
$pattern = '/[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}/i';
preg_match_all($pattern, $string, $matches);
foreach($matches[0] as $match)
{
echo $match;
echo '<br><br>';
}
}
?>
I have tried to use this code for that. The program is reading the complete file which are CSV, and line by line which are Text file. There are thousands of file and hence it is difficult to identify.
Kindly, suggest me what I should do to resolve my problem? Is there any solution which can read any format, then it will be awesome.
Well your files are different. Because of that you will have to take a different approach for each of those. In more general terms this is usually calling adapting and is mostly provided using the Adapter design pattern.
Should you use the adapter design pattern you would have a code inspecting the extension of a file to be opened and a switch with either txt or csv. Based on the value you would retrieve aTxtParseror aCsvParser` respectively.
However, before diving deep into this territory you might want to have a look at the files first. I cannot say this for sure without seeing the structures but you can. If the contents of both the text and csv files are the same then a very simple approach is to change the extension to either txt or a csv for all files and then process them using same logic, knowing files with the same extension will now be processed in the same manner.
But from what I understood the file structures actually differ. So to keep your code concise the adapter pattern, having two separate classes/functions for parsing and another one on top of that for choosing the right parsing function (this top function would actually be a form of a strategy) and running it.
Either way, I very much doubt so there is a solution for the problem you are facing as a file structure is mostly your and your own.
Ok, so problem is when CSV file has too long string line. Based on this restriction I suggest you to use example from php.net Here is an example:
$handle = #fopen("/tmp/inputfile.txt", "r");
if ($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer;
// do your operation for searching here
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}

Using ftp_get() when there are "spaces" in the file path and filename

I need to download a file via PHP ftp_get(), but the foolish provider is using directories and file names contaning whitespace.. The file path I'm dealing with is similar to /product info/more stuff/inventory and stuff.csv
The spaces in the path and in the filename itself is making it difficult to retrieve anything. I already tried the following without success:
$path = "/product\ info/more\ stuff/inventory\ and\ stuff.csv";
$path = "/product%20info/more%20stuff/inventory%20and%20stuff.csv";
$path = '"/product info/more stuff/inventory and stuff.csv"';
Thanks again for taking the time to help me out.
Your third attempt, quoting the complete path, was already the recommended approach. Though it very much depends on the actual server implementation.
FTP per RFC859 is comprised of a terminal session and a data transfer channel. Basically the FTP server provides a mini-shell on the command port. As such, typical shell string escaping rules do apply. URL encoding can be ruled out here.
I'd advise first to use single quotes however. Preferrably use escapeshellarg() to apply them. And try ftp_nb_get() while at it.
$path = "/foo foo/bar bar/baz baz.csv";
ftp_nb_get($con, "save.csv", escapeshellarg($path), 2);
If that doesn't work, further debugging is necessary. While all ftp_* function arguments are left unprocessed, you could as well try to send a ftp_raw request. This won't actually activate the data channel reading, but might return a more concrete error response.
print_r(ftp_raw($con, "RETR '/path to/some file.csv'\r\n"));
And I'm just gonna say it, if you're still getting a file not found error then; it's entirely possible that the file really doesn't exist at the presumed location. In that case manually traverse the directory structure with ftp_nlist and ftp_rawlist with var_dump (in case of extra trailing spaces for subdirs).
Alternatively just use PHPs ftp:// stream wrapper (which also supports PASV mode). Whose implementation is distinct from that of the ext/ftp functions. Here funnily enough, URL encoding is again the correct approach, but quoting still necessary (ftp_fopen_wrapper.c does not quote itself):
= file_get_contents("ftp://user:pw#example.org/'path%20to/file%20and.csv'");
// Inline quotes may likely trip up some FTP server implementations..
A much better alternative though is just using cURL.
// You'll have to use the long-winded PHP curl functions of course.
print curl("ftp://.../file with spaces.csv")->exec();
Last option is just resorting to calling a Unixland client. (If not wget, than a plain ftp client.)
$url = escapeshellarg("ftp://user:pw#ftp.example.org/$path");
$file = `wget $url`;
If you still can't retrieve any files, you'll have to look for an alternative FTP client in PHP for further debugging. Guess who wrote one.
To get a list of files or folders with spaces in the path.
ftp_chdir($conn, $path);
$children = ftp_rawlist($conn,'-a .');
Source

I want to write to a text file at the inputed caret position with PHP

I want to wite to a text file at the inputed text position using PHP. I tried using fseek to point the wite position to the inputed number, but it saves as an empty file instead.
<?php
$testData = "testdata";
$testPosition = 3;
$fileReference = fopen("test.txt", "w");
fseek($fileReference, $testPosition);
fwrite($fileReference, $testData);
fclose($fileReference);
?>
How would I get the script to wite to the text file at the specified position correctly?
The w flag only allows for writing to a file. Try replacing the w flag with a r+ flag. This will allow for read/write to a file without truncating the file. the read /write is needed to allows you to go search for your caret and write to where it is. for more information on the fopen function please see php.net: fopen()
The w flag has this functionality:
'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
This could be why you're getting an empty file.
However, on my local server, this works fine. This makes me think your permissions may not be correct. For example, you might not have write permissions. Try and ensure that you have the correct permissions on this file.

fgetcsv doesn't validate whether or not this is a csv file

This question has been asked several times, but as it turns out all of the answers I have come across have been wrong.
I'm having a problem validating whether a file is a CSV or not. Users upload a file, and the application checks to see if fgetcsv works in order to make sure it's a CSV and not an Excel file or something else. That has been the traditional answer I'm finding via Google.
e.g.:
if ($form->file->receive()) {
$fileName = $form->file->getFileName();
$handle = fopen($fileName, 'r'); // or 'w', 'a'
if (fgetcsv($handle)) {
die('sos yer face');
}
if ($PHPExcelReader->canRead($fileName)) {
die('that\'s what she said');
}
}
What happens with the above is 'sos yer face' because fgetcsv validates as true no matter what you give it if your handle comes from fopen($fileName, 'r') as long as there is a file to read; and fgetcsv always false when using fopen($fileName, 'w') or 'a' because the pointer will be initiated at the EOF. This is according to the php.net documentation.
Maybe what I'm saying is ridiculous and I just don't realize it. Can anyone please fix my brain.
The problem with validating whether or not a file is a CSV file is that CSV is not a well-defined format. In fact, by most definitions of CSV, just about any file would be a valid CSV, treating each line as a row with a single column.
You'll need to come up with your own validation routine specific to the domain you are using it in.

GZ Compressing an XML sitemap file with PHP

I have a PHP script that generates a dynamic PHP sitemap from my site's database to an xml file using fopen() and fwrite().
How can I compress this file using GZ compression dynamically as I write it?
I tried fwrite()-ing strings that I ran through gzcompress() into the file and renaming it ".xml.gz", but it doesn't seem the file it;s creating is a well-fromed archive.
Not using fopen and fwrite but gzopen() and gzwrite() should do the trick for you.
From the manual:
# Sample #1 gzwrite() example
<?php
$string = 'Some information to compress';
$gz = gzopen('somefile.gz','w9');
gzwrite($gz, $string);
gzclose($gz);
?>
If i understood correctly
this is a quote from the php site that we all should keep in mind.
Take Heed 07-Nov-2010 08:50 Read the description of gzwrite() very
carefully. If the 'length' option is not specified, then the input
data will have slashes stripped on systems where magic quotes are
enabled. This is important information to know when compressing
files.
http://php.net/manual/en/function.gzwrite.php

Categories