How to create a file in the root dir with perl? - perl

I have an error with perl while trying to CREATE a file called .envfile in the root dir / (only for UNIX). Permission denied, which is understood. But, is there a way to write this file? I need to do it without any modules, just with a built-in functions. I expect for using chmod, but... honestly, have no idea of how to implement it in the same thread SAFELY.
I need this file to write in it my own ENVs for my software (as it is a big project with many dirs and needs to operate with many own ENVs).
Trying simple:
my $filename = '.envfile';
open FH, '>', $filename or die $!;
print FH "some data\n";
close(FH);
Apache says: Permission denied at /var/www/cgi-bin/env.cgi line 41.
Any help appreciated!
Thanks!

If I understand the question correctly, it appears that you also control the software which will ultimately read the file you're trying to create. Is that accurate? If so, change the program to get its environment from somewhere else. Where else? Preferably a new directory, so that you can make it writable by your web server without affecting anything else. I'd probably use /etc/myprogram (because /etc is the standard place for configuration files) or /var/local/myprogram (because /var is the standard place for persistent data files). But not an existing directory which is and should remain writable solely by root.
Short of exploiting a security flaw, Perl does not allow you to sidestep filesystem security (permissions). And that is a Good Thing. If it were allowed, it would mean that anyone who finds an exploit in your Perl code could then change any file on your computer, potentially replacing it with the most malicious code ever written.
Thus, the only way that your Perl can create a file in / is if it runs as root or uses su/suid to run some other program as root. And you really, really, really do not want CGI scripts or web applications running as root because, unless you do everything absolutely perfectly in your code, and there are no exploitable bugs in perl itself, or apache, or the kernel, then, by running your web code as root, you're potentially handing root access to any random script kiddie on the internet.
If you really, truly, absolutely have no choice other than to have web-accessible code write arbitrary files to /, then the least-bad, least-insecure way to do it would be to create a very tiny helper program which takes a file name and file contents as inputs, checks to verify that the named file does not already exist (so that an attacker can't use it to overwrite, say, your kernel), and then creates the named file with the provided contents. Aside from maybe a little additional sanity/security checking, it should do absolutely nothing else because the more complex this helper program is, the more likely it is to contain exploitable flaws. Then have the web code use suid to run the helper program, with suid configured to allow the web user (and only the web user) to run the helper program (and only the helper program) with no password.
But don't do that unless you really, truly, absolutely have no other option. It is not the best way to do it, it is the least bad way. Which means it's still a bad idea.

Create the file 'by hand' and set it's owner to the owner of the apache process, e.g.:
sudo touch /.envfile
sudo chown www-data:www-data /.envfile
sudo chmod u+rw /.envfile

You're executing your Perl program as a user without sufficient privilege. Run the Perl program using a user with sufficient privilege (e.g. using sudo or su).

Related

Locking My Own Perl Script

How can I lock my Perl script, list I have to do
Prevent Others from read or write Perl Script.
They should have only Permission to Executing the Perl script.
This depends on your operating system, which you haven't specified.
Typically, this is not possible.
On a UNIX based system (such as Linux or Mac OS) there are three permissions that can be given to users, groups and everyone: Read, Write, and Execute.
You can remove Write permission easily enough, but Read permission is required to allow the script to be executed.
(I assume you would experience a similar problem on Windows).
The only work around I can think of would be to rewrite the script as a webservice. Then the HTTP server would need to be able to read it, but the users themselves would not.
If the system at hand is Linux/Unix and you have administrative access then you can use sudo.
With the following line in /etc/sudoers, anyone would be able to run, as author1, any executable file in the public_bin folder:
ALL ALL = (author1) /home/author1/public_bin/*
However, take a look at man sudoers to understand implications wrt. environment and command line arguments.
755 is the *nix permission you'll need. This will give the owner full access and other read and execute.
As other has said, there is no way to make your code unreadable. However,can you obfuscate you code so only a reasonably good programmer could decode it. There are online tools, if you search "perl obfuscate" on bing you'll get some good results; these tools will mean no module is required. Or my personal favorite is the module Acme::Bleach.

get user machines current working directory from perl cgi

i am trying to get the current working directory path using Perl
when i execute from ubuntu: $root#ubuntu:/var/test/geek# firefox http:/localhost/test.html, i get /var/cgi-bin as output in perl cgi page instead of /var/test/geek.
used perl code:
my $pwd=cwd();
bla bla
print "<h1> pwd </h1>";
above code gives path of test.pl not users working directory path
Edit: When i run the script alone from the terminal it works fine. for example:
$root#ubuntu:/var/test/geek# /var/cgi-bin/test.pl
i get /var/test/geek. but when i call the script in html page using submit button it gives path of perl script.
Each process has its own working directory that it inherits from its parent when it gets created.
cwd() returns the current process's working directory.
For a CGI script, the browser doesn't pass its working directory to the server as part of the request. To obtain that, you need to have code running on the client system that submits it. That might be an application that the user download, or possibly, but unlikely, some in-browser code, like Javascript / a Java applet (This info is likely hidden from in-browser code for security reasons though).
(The rest assumes Linux, it will likely differ on other operating systems)
The part below assumes that you are looking for the working directory of a user on the server:
In order to get a specific shell for a specific user's working directory, you would need to identify the PID for the shell and get the working directory from the /proc/<pid>/cwd symlink (To read these, the process must belong to the user running the code, or the code must run as root (Which is a bad idea for a CGI script)...). To get the PID of the shell, you likely need to start from the w command output, or its data source, /var/run/utmp. Sys::Utmp might be useful for this... You might then also need to retreive a whole lot of extra info to find all the processes that might have the working directory that you are looking for.
I think you are mixing the web server and the local user. The web server has a working directory when you run the script, and that is the one that cwd() returns.

How is a program in a specific location?

When writing a program, the program is sort of running in a particular directory which is the current working directory.
I'm trying to understand more about the idea of a cwd. How does a program know what its cwd is? Where is that information stored?
I know perfectly well how to use the os module in python, but I don't really understand what it means to have a cwd. Is it simply a data attribute, "this is where we are", that we can change arbitrarily? And we simply look for things and create things on that particular section of the HD? Or is some sort of pathway actually opening and closing actively when we change cwd, like a door getting shut and another being opened?
What happens on the computer when I change cwd in a program?
This may be language-agnostic, I am unsure.
The current working directory is (at least on most operating systems) an attribute of a process, so yes, it is more or less a simple attribute stating "this is where we are". As it's an attribute of a process, it is stored and managed by the OS kernel.
It can be changed arbitrarily by calling e.g. os.chdir in python, and a shell would similarly change its working directory each time you run the builtin cd command. And they both would normally call the same API of the operating system, e.g. chdir(). Changing the cwd is subject to filesystem permissions, so you can only change the working directory to a path that actually exists and you have permissions to.
The cwd may also be involved in file operations, as when a process opens a file path that is not an absolute path, the file name will be resolved relative to the cwd of the process.
On unix systems the cwd is inherited from the parent process, as such the cwd of a process you start from a shell will have its cwd to the directory you are in when you start the process (and not e.g. the directory of the executable you start).

How to open Perl file handle to write data via sudo (or as another user)

I'd like to write data to a file, but the file handle should be opened with access permissions for a specific user.
Thus, the following statement:
open (FH, "> $filename") or die "$#\n";
would allow writing to a file as that particular user.
Is there a way to do this within a Perl script, without the entire script being run with sudo -u $username?
There are two established ways. Stackers, you are invited to edit this answer to fill in the drawbacks for each.
Run the program with sudo. The first thing you do in the program is to open the files you need and keep the handles, and then immediately afterwards drop the root privileges. Any further processing must take place with low privileges. The Apache httpd works likes this, it opens the log files as root, but continues running as nobody or similar.
If you don't like that way, run the program normally, and when you need to elevate, create a new process and have it run with a user configured sudo, su -, kdesu/gksu or whatnot. The CPAN client works likes this, it fetches, unpacks, builds and tests a module as a normal user, but calls sudo make install etc. when it's time to install.
An alternative to daxim's suggestions is to have the script owned by the specific user and have the script permissions include the setuid and/or setgid bits.

How can I make a Perl script executable from everywhere by everyone?

I wrote a very simple perl script, and now I want to make it executable from everywhere.
I know I could just drop it into /bin/, rename it from 'mytest.pl' -> 'mytest', and chmod +x, but is this standard practice? I noticed nothing in /bin/ is a perl script.
Also, I want it to be able to log to /var/logs/mytest/*
Are there any security issues I should be aware of?
It is preferable to put user-made scripts in /usr/local/bin , but it's your call whether it's worth worrying about this. As far as logging to /var/logs/mytest/*, you can try to make the script suid (this is sometimes not allowed for security) with a user that can write to the dir, or just make /var/logs/mytest world-writable.
Instead of worrying about log file permissions issues, why not log to the system logger? That's what it's there for. See Sys::Syslog