How secure (hardened) is this script (part 2) - php

In my previous question on this topic, what would the implications be if I removed the dynamic variable and instead replaced it with a static one like you see below...
$source = 'http://mycentralserver.com/protected/myupdater.zip';
I've included the code below for convenience...
<?php
// TEST.PHP
$source = 'http://mycentralserver.com/protected/myupdater.zip';
$target = '.';
$out_file = fopen(basename($source), 'w');
$in_file = fopen($source, 'r');
while ($chunk = fgets($in_file)) {
fputs($out_file, $chunk);
}
fclose($in_file);
fclose($out_file);
$zip = new ZipArchive();
$result = $zip->open(basename($source));
if ($result) {
$zip->extractTo($target);
$zip->close();
}
?>

You should at least be hashing the zip with SHA-1 and checking it against a digest to ensure it hasn't changed. These digests should be extremely hard to replace.
I still think automated updates are a bit iffy.

PHP 5.2.6 and older had a vulnerability that allowed writing to arbitrary locations via Zip's extractTo() -method.
See: http://www.securityfocus.com/bid/32625
So, if the contents of the zip are untrustworthy, you must use PHP 5.2.7 or newer (or use your own Zip parser).

Related

How do I retrieve text from a doc file php

I am trying to retrieve text from a doc file using php. This is the code that I am using:
function read_doc() {
foreach (glob("*.doc") as $filename) {
$file_handle = fopen($filename, "r"); //open the file
$stream_text = #fread($file_handle, filesize($filename));
$stream_line = explode(chr(0x0D),$stream_text);
$output_text = "";
foreach($stream_line as $single_line){
$line_pos = strpos($single_line, chr(0x00));
if(($line_pos !== FALSE) || (strlen($single_line)==0)){
$output_text .= "";
}else{
$output_text .= $single_line." ";
}
}
$output_text = preg_replace("/[^a-zA-Z0-9\s\,\.\-\n\r\t#\/\_\(\)]/", "", $output_text);
echo $output_text;
}
}
I get this result:
HYPERLINK mailtoAnother#email.us Another#email.us Y, dXiJ(x(I_TS1EZBmU/xYy5g/GMGeD3Vqq8K)fw9 xrxwrTZaGy8IjbRcXI u3KGnD1NIBs RuKV.ELM2fiVvlu8zH (W uV4(Tn 7_m-UBww_8(/0hFL)7iAs),Qg20ppf DU4p MDBJlC5 2FhsFYn3E6945Z5k8Fmw-dznZxJZp/P,)KQk5qpN8KGbe Sd17 paSR 6Q
Is there some solution which would clear this up so it returns just a string of text from the doc file?
Doc files are hard to handle with vanilla php.
Using https://github.com/alchemy-fr/PHP-Unoconv I did acomplish what you need. It will acutally detect different formats and produce you with a nice xml. Docs can be found here
There are also a lot of examples on the web if you search for "unoconv" + "php"
Parsing an MS Word doc is tough to do with code.
This is because MS embeds a lot of data into their format, making it look like gibberish as you echo out the parsed words/paragraphs.
I recommend you try a package library (from packagist) to help you with this Word-Doc-Parser
Can be easily installed via composer if you have it on your system.

Change pointer for file_put_contents()

$iplog = "$time EST - $userip - $location - $currentpage\n";
file_put_contents("iplog.txt", $iplog, FILE_APPEND);
I am trying to write this to the text file, but it puts it at the bottom and I would prefer if the new entries were at the top. How would I change the pointer for where it puts the text?
To prepend at the beginning of a file is very uncommon, as it requires all data of the file copied. If the file is large, this might get unacceptable for performance (especially when it is a log file, which is frequently written to). I would re-think If you really want that.
The simplest way to do this with PHP is something like this:
$iplog = "$time EST - $userip - $location - $currentpage\n";
file_put_contents("iplog.txt", $iplog . file_get_contents('iplog.txt'));
The file_get_contents solution doesn't have a flag for prepending content to a file and is not very efficient for big files, which log files usually are. The solution is to use fopen and fclose with a temporary buffer. Then you can have issues if different visitors are updating your log file at the same time, but's that another topic (you then need locking mechanisms or else).
<?php
function prepend($file, $data, $buffsize = 4096)
{
$handle = fopen($file, 'r+');
$total_len = filesize($file) + strlen($data);
$buffsize = max($buffsize, strlen($data));
// start by adding the new data to the file
$save= fread($handle, $buffsize);
rewind($handle);
fwrite($handle, $data, $buffsize);
// now add the rest of the file after the new data
$data = $save;
while (ftell($handle) < $total_len)
{
$chunk = fread($handle, $buffsize);
fwrite($handle, $data);
$data = $chunk;
}
}
prepend("iplog.txt", "$time EST - $userip - $location - $currentpage\n")
?>
That should do it (the code was tested). It requires an initial iplog.txt file though (or filesize throws an error.

Developing a text editor with PHP

I've started a small project trying to make an online text editor, it WAS going well until the system started overwriting files and adding spaces in unnecessarily. I have one file called editor.php where all the file loading, saving and editing is done.
So this is the opening/closing for the files:
<?php
if(isset($_POST['new'])){
$filer = substr(md5(microtime()),rand(0,26),6);
$file_create = $filer.".txt";
$handle = fopen("files/".$file_create,"w");
fclose($handle);
header("Location: editor.php?e=".$filer);
}
$file = $_GET['e'];
$file = basename($file);
$filename = "files/".$file.".txt";
$file_get = file_get_contents($filename);
if(isset($_POST['save'])){
file_put_contents($filename, $_POST['text']);
}
?>
further down the page I have this in a <textarea> tag:
<?php
echo $file_content;
?>
This uses the string from the file_get_contents();
But when I save, nothing happens, in fact it erases the file, when I load a file there are eight spaces but nothing else.
I know there is another way to do this with fopen() and if someone could give me a method to use that, it would be much appreciated.
You have to verify if the $_POST['text'] actually has a content in it.
if(isset($_GET['e'])){
$file = $_GET['e'];
$file = basename($file);
$filename = $_SERVER['DOCUMENT_ROOT']."/files/".$file.".txt";
$file_get = file_get_contents($filename);
if(isset($_POST['save'])){
if(!empty($_POST['text']) && isset($_POST['text']))
{
$length = strlen($_POST['text']);
if($length > 0)
file_put_contents($filename, trim($_POST['text']));
else
die("No content");
}
}
}
ALso check if the file exists and its writable. You can use chmod,mkdir and file_exists functions.
Have a look at PHP's file modes: http://php.net/manual/en/function.fopen.php
If you are opening all your files using fopen() in w mode then your files are being truncated as they are opened. This is how w mode operates. Try using a+ or c+ modes with fopen().
EDIT
Also, the file_put_contents() will also overwrite file contents unless you sett the FILE_APPEND flag, e.g. file_put_contents($file, $data, FILE_APPEND).

PHP fwrite writing empty file

I'm trying to make this save a file and it creates the file, but it's always empty. This is the code for it:
<?php
$code = htmlentities($_POST['code']);
$i = 0;
$path = 'files/';
$file_name = '';
while(true) {
if (file_exists($path . strval($i) . '.txt')) {
$i++;
} else {
$name = strval($i);
$file_name = $path . $name . '.txt';
break;
}
}
fopen($file_name, 'w');
fwrite($file_name, $code);
fclose($file_name);
header("location: index.php?file=$i");
?>
I echoed out $code to make sure it wasn't empty, and it wasn't. I also tried replacing
fwrite($file_name, $code);
with this:
fwrite($file_name, 'Test');
and it was still empty. I have written to files a couple of times before in PHP, but I'm still really new to PHP and I have no idea whats wrong. Could someone tell me what I'm doing wrong or how to fix this? Thanks
Reading/Writing to/from a file or stream requires a resource handle:
$resource = fopen($file_name, 'w');
fwrite($resource, $code);
fclose($resource);
The resource handle $resource is essentially a pointer to the open file/stream resource. You interact with the created resource handle, not the string representation of the file name.
This concept also exists with cURL as well. This is a common practice in PHP, especially since PHP didn't have support for OOP when these methods came to be.
Take a look of the samples on php.net

very weird issue in html when include PHP function include [duplicate]

I was writing some commented PHP classes and I stumbled upon a problem. My name (for the #author tag) ends up with a ș (which is a UTF-8 character, ...and a strange name, I know).
Even though I save the file as UTF-8, some friends reported that they see that character totally messed up (È™). This problem goes away by adding the BOM signature. But that thing troubles me a bit, since I don't know that much about it, except from what I saw on Wikipedia and on some other similar questions here on SO.
I know that it adds some things at the beginning of the file, and from what I understood it's not that bad, but I'm concerned because the only problematic scenarios I read about involved PHP files. And since I'm writing PHP classes to share them, being 100% compatible is more important than having my name in the comments.
But I'm trying to understand the implications, should I use it without worrying? or are there cases when it might cause damage? When?
Indeed, the BOM is actual data sent to the browser. The browser will happily ignore it, but still you cannot send headers then.
I believe the problem really is your and your friend's editor settings. Without a BOM, your friend's editor may not automatically recognize the file as UTF-8. He can try to set up his editor such that the editor expects a file to be in UTF-8 (if you use a real IDE such as NetBeans, then this can even be made a project setting that you can transfer along with the code).
An alternative is to try some tricks: some editors try to determine the encoding using some heuristics based on the entered text. You could try to start each file with
<?php //Úτƒ-8 encoded
and maybe the heuristic will get it. There's probably better stuff to put there, and you can either google for what kind of encoding detection heuristics are common, or just try some out :-)
All in all, I recommend just fixing the editor settings.
Oh wait, I misread the last part: for spreading the code to anywhere, I guess you're safest just making all files only contain the lower 7-bit characters, i.e. plain ASCII, or to just accept that some people with ancient editors see your name written funny. There is no fail-safe way. The BOM is definitely bad because of the headers already sent thing. On the other side, as long as you only put UTF-8 characters in comments and so, the only impact of some editor misunderstanding the encoding is weird characters. I'd go for correctly spelling your name and adding a comment targeted at heuristics so that most editors will get it, but there will always be people who'll see bogus chars instead.
BOM would cause Headers already sent error, so, you can't use BOM in PHP files
This is an old post and have already been answered, but i can leave you some others resources that i found when i faced with this BOM issue.
http://people.w3.org/rishida/utils/bomtester/index.php with this page you can check if a specific file contains BOM.
There is also a handy script that outputs all files with BOM on your current directory.
<?php
function fopen_utf8 ($filename) {
$file = #fopen($filename, "r");
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
{
return false;
}
else
{
return true;
}
}
function file_array($path, $exclude = ".|..|design", $recursive = true) {
$path = rtrim($path, "/") . "/";
$folder_handle = opendir($path);
$exclude_array = explode("|", $exclude);
$result = array();
while(false !== ($filename = readdir($folder_handle))) {
if(!in_array(strtolower($filename), $exclude_array)) {
if(is_dir($path . $filename . "/")) {
// Need to include full "path" or it's an infinite loop
if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true);
} else {
if ( fopen_utf8($path . $filename) )
{
//$result[] = $filename;
echo ($path . $filename . "<br>");
}
}
}
}
return $result;
}
$files = file_array(".");
?>
I found that code at php.net
Dreamweaver also helps with this, it gives you the option to save the file and not include the BOM stuff
Its a late answer, but i still hope it helps.
Bye
Just so you know, there's an option in php, zend.multibyte, which allows php to read files with BOM without giving the Headers already sent error.
From the php.ini file:
; If enabled, scripts may be written in encodings that are incompatible with
; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such
; encodings. To use this feature, mbstring extension must be enabled.
; Default: Off
;zend.multibyte = Off
In PHP, in addition to the "headers already sent" error, the presence of a BOM can also screw up the HTML in the browser in more subtle ways.
See Display problems caused by the UTF-8 BOM for an outline of the problem with some focus on PHP (W3C Internationalization).
When this occurs, not only is there usually a noticeable space at the top of the rendered page, but if you inspect the HTML in Firefox or Chrome, you may notice that the head section is empty and its elements appear to be in the body.
Of course viewing source will show everything where it was inserted, but the browser is interpreting it as body content (text) and inserting it there into the Document Object Model (DOM).
Or you could activate output buffering in php.ini which will solve the "headers already sent" problem. It is also very important to use output buffering for performance if your site has significant load.
BOM is actually the most efficient way of identifying an UTF-8 file, and both modern browsers and standards support and encourage the use of it in HTTP response bodies.
In case of PHP files its not the file but the generated output that gets sent as response so obviously it's not a good idea to save all PHP files with the BOM at the beginning, but it doesn't mean you shouldn't use the BOM in your response.
You can in fact safely inject the following code right before your doctype declaration (in case you are generating HTML as response):
<?="\u{FEFF}"?> (or before PHP 7.0.0: <?="\xEF\xBB\xBF"?>)
For further read: https://www.w3.org/International/questions/qa-byte-order-mark#transcoding
Adding to #omabena answer use this code to locate and remove bom from your files. Be sure to back up your files first just in case.
function fopen_utf8 ($filename) {
$file = #fopen($filename, "r");
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
{
return false;
}
else
{
return true;
}
}
function file_array($path, $exclude = ".|..|design", $recursive = true) {
$path = rtrim($path, "/") . "/";
$folder_handle = opendir($path);
$exclude_array = explode("|", $exclude);
$result = array();
while(false !== ($filename = readdir($folder_handle))) {
if(!in_array(strtolower($filename), $exclude_array)) {
if(is_dir($path . $filename . "/")) {
// Need to include full "path" or it's an infinite loop
if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true);
} else {
if ( fopen_utf8($path . $filename) )
{
//$result[] = $filename;
echo ($path . $filename . "<br>");
$pathname = $path . $filename; // change the pathname to your target file(s) which you want to remove the BOM.
$file_handler = fopen($pathname, "r");
$contents = fread($file_handler, filesize($pathname));
fclose($file_handler);
for ($i = 0; $i < 3; $i++){
$bytes[$i] = ord(substr($contents, $i, 1));
}
if ($bytes[0] == 0xef && $bytes[1] == 0xbb && $bytes[2] == 0xbf){
$file_handler = fopen($pathname, "w");
fwrite($file_handler, substr($contents, 3));
fclose($file_handler);
printf("%s BOM removed.<br/>n", $pathname);
}
}
}
}
}
return $result;
}
$files = file_array(".");

Categories