I'm tryng to find a solution for upload data on a remote mysql database using a python daemon.
My base script use a simple query "INSERT INTO...." but in top of the script there are in clear the credentials to connect on database:
conn = MySQLdb.connect(host="192.168.1.123", user="root", passwd="Pa$$w0rd", db="mydb")
I do not want anyone reading the python script can access the database directly.
I need to use python scripts on clients
The server with mysql db is on cloud
The clients are Raspberry pi
In the server I can use php
Several ways
1. Use mysql.cnf file
Mysql cnf files is a config file storing MySQL credentials, if this server or client executing the script has one, you can use it like:
db=_mysql.connect(host="outhouse",db="thangs",read_default_file="~/.my.cnf")
Credentials are not in your Python script anymore, but they are clear in cnf file anyway and you must have this file in the same place everywhere you want to use your script.
source: http://mysql-python.sourceforge.net/MySQLdb.html
2. Command line argument
You can parse command line arguments to get credentials from it like:
import sys
user = sys.argv[1]
password = sys.argv[2]
conn = MySQLdb.connect(host="192.168.1.123", user=user, passwd=password, db="mydb")
And so execute your script with:
python myscript "root" "pa$$w0rd"
With this method credentials can't be found in any config file, but you have to execute it with arguments, if it's a deamon it can be ok, but if you want to use it as cron (by example), you will have to write credentials in crontab, so not so safe.
3. Environment variables
Another way is to use environment variables
import os
conn = MySQLdb.connect(host="192.168.1.123", user=os.environ['MYSQL_USER'], passwd=os.environ['MYSQL_PASSWORD'], db="mydb")
But you will have to set these variables somewhere. In ~/.bash_profile, /etc/profile or by command line. So if somebody access to user that can execute script, he can read password.
4. Encoding
Encoding seems to be a good way to hide password, but in fact you can not really hide from someone who can access to the right user in the right server.
Encoded string without salt is easy to decode, some encoding methods are easy to spot and can be decoded by anyone.
Using a salt will make work more harder, but if somebody can access to you code, it will be easy to locate salt phrase (no matter if salt is stored in environment var, in a file or directly in code).
Using .pyc files can be an idea too, but first, it's not recommended and anybody can read content by creating a python script importing this pyc file and print what stored in.
Encoding credentials still is still a good thing, but encoded string can always be decoded, if your code can, somebody with access to it can too. A simple print password added in your code and regardless of the used method the password will be accessible.
So you have to secure your python code, but Unix users & groups too and mysql config too.
Related
I want to call php using vba or vbs. The php file is stored on a server.
I am able to do it if the php file is stored locally:
Sub asasdsad
Call Shell("C:\xampp\php\php.exe C:\path\file.php", 1)
End Sub
This calls the php which executes a code for me. My problem is, the .php file I want to call is stored on a server, for which I've got username and password of course. Copying file to local directory is not an option as it's got a lot of includes.
My idea is to use PuTTY to connect to the server, and use it to execute above command, all from cmd using vba/vbs.
UserName = "un"
Passwrd = "pw"
'this would need additional parameters at the end to call php.exe like above
Call Shell("""C:\Program Files (x86)\PuTTY\putty.exe"" " & "-ssh " & UserName & "#ip address -pw " & Passwrd, 1)
As you can imagine there will be a lot of parameters so it just get complicated, not ever sure if this would work. I've never used PuTTY and all of this is quite new to me. I'm sure there's a better way?
First, do not use PuTTY, use Plink (PuTTY connection tool). It's a console application designed for automation (contrary to PuTTY, what is GUI application, designed for an interactive use).
Plink (again contrary to PuTTY) can accept a command to be executed on its command-line (it has a similar command-line syntax as OpenSSH ssh):
"C:\...\plink.exe" -ssh username#ip_address -pw password /path/to/php /path/to/script.php
I have a web server running Apache 2 on Raspbian Stretch. It is going to be a programming contest website, where users can send code via a HTML form, that sends their source code to PHP via a POST request. PHP then runs (using exec()) a Python script with arguments such as the submitted code path. The script then executes the code (using subprocess.run()) with a custom input and compares it to an expected output. All of that works just fine.
However, I want to make sure no one is going to send malicious code to overwrite files such as index.php, or read the expected outputs, for example. I'd like to know if there is any way to prevent an application that is being executed by subprocess.run() from reading, creating and writing to files other than stdin, stdout and stderr.
I have tried using Docker but didn't have success, as when I build and run the Dockerfile using PHP's exec() it reaches step 2/4 and just stops. My Dockerfile should copy the script, the code and the expected outputs to an image, cd to the new location and execute the code, but that is not very relevant since I want to avoid Docker as it isn't working properly.
I am considering using a chroot jail, but I am still looking for other less-complicated ways of doing that.
This is the PHP code I'm using. It calls the Python 3 code verifier (variables are retrieved from a HTML form and from a SQL query, those are not relevant):
$cmd = "python3 verify.py $uploadedFile $questionID $uploadedFileExtension $questionTimeLimit 2>&1";
And this is the Python 3 code that executes the submitted code:
def runCmd(args, vStdin, timelimit = 10):
p = subprocess.run(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE, input = vStdin, encoding = 'utf-8', timeout=timelimit)
vStdout = p.stdout
vStderr = p.stderr
if vStdout.endswith('\n'):
vStdout = vStdout[:-1]
if vStderr.endswith('\n'):
vStderr = vStderr[:-1]
return vStdout, vStderr
...
# Assuming it is a .py file
# Its path is given by PHP's exec.
runCmd(['python3', sys.argv[1], 'simulatedinput.in', int(sys.argv[4]))
The combination of both programs works just fine. It runs the code with a simulated input, compares the stdout with the expected output and returns a status string to the PHP code. However, if the code sent has a malicious bit of code, such as
open('/var/www/html/contest/index.php', 'w').write('oops!')
the index.php file will be overwritten.
All I need is a way of executing the user-sent code in a way that its attempts to read or write to files (other than stdin, stdout and stderr) are denied.
Any thoughts?
doing this securely, to put it simply, is difficult. it's relatively easy to escape even a chroot jail if you're not really careful about how you set it up. basically the Unix security model isn't built to make this sort of thing easy and it's assumed that things are mostly cooperative
docker would probably be my suggestion, but there are other lighter weight solutions like chroot (but they'd probably still have the ability to do naughty things with the web server's network connection) or maybe something like firejail
with docker you'd probably want to create a single minimal docker image/container containing Python and whatever libraries are appropriate. you'd then use volumes to make the user supplied code appear inside the VM at runtime. you don't want to be creating containers all the time, that would entail lots of cleanup work
see https://security.stackexchange.com/q/107850/36536 for some more info on using docker as a sandbox, basically there are still lots ways out of it unless you're careful
Currently I have a shell script within my application that depending on what argument you pass it, it will log you into either the live or development MySQL database shell. It works fine, no problem there.
The issue/challenge I am having is that if in the case my MySQL credentials (host / port) change for either the live or development database then I will manually have to edit this shell script, updating it will the new arguments. Problem is, I have done this before but I never want to have to do it again.
What I would like to do is have a PHP script (mysql.sh.php) that when executed, depending on the argument passed to it will log you into either the live or development database shell. How it will differ from the shell script is that it will pull the current credentials (and even host and port) from a PHP configuration class and pass those as arguments to a shell command that will log into the respective database.
Below gives you an illustration of what I am attempting.
#!/usr/bin/php
<?php
include ('common.php');
//Pull info from PHP class right here
exec("mysql --host={$myhostnotyours} --user={$myusernotyours} -p{$mypassnotyours} {$thedatabase}");
What I expect or would like is
mysl>
However, the command just hangs and I am not presented with the MySQL shell.
I would like to know if there is a way to accomplish what I am trying.
Thanks!
If I do shell_exec('mysqldump DATABASE_NAME') from a php script, is there any danger?
Is there a way to get this to work in Windows?
I am going to use mysqldump for database backup from a web page
Also should I do set_time_limit(0) when running this?
Yeah, there is danger: If database name comes from an untrusted source hackers could try to inject shell commands in the database name. For example:
$dbname = 'test; cat /etc/shadow';
might being used to obtain user names and encrypted passwords from the system (depends on the system)..
To avoid that, you should use escapeshellarg() to quote the database name (and possible other arguments):
shell_exec('mysqldump ' . escapeshellarg($database_name));
set_time_limit() isn't required if you are following my hints here
Needless to say, that you'll have to secure the page using login.
I'm brand new to ruby and Watir, here's my issue...
I have a MySQL DB with test data that I need. I've done a lot in the past with this data and so I have a whole library of PHP tools for accessing this data, marking data as in use/used/bad/etc, and in general I have a lot of time invested in the PHP framework. So I'd really like to use the PHP framework as a wrapper around the Watir script - for example, use PHP to grab test user login data from the DB and pass it to the ruby script for processing.
I now have sites with javascript that need work/testing and PHP & cURL can't deal with this. So I'm working with Watir-WebDriver on Ubuntu 10.10 (Maverick, Desktop not Server) for these sites. The problem I'm having is with the use of PHP's shell_exec of the ruby script with all the Watir code.
The PHP shell_exec is executing the file - I can see it because I have some puts lines in the file which are being displayed. However, the code appears to be failing on the line
ff = Watir::Browser.new :firefox
I'm not getting an error from PHP.
The PHP line is:
echo shell_exec('ruby /var/www/watir_test.rb');
The ruby script works fine when I call it from a terminal window with the line:
ruby /var/www/watir_test.rb
I originally expected this was a permissions issue since it worked from the command line but not from a browser. However, since it can call the file well enough to return the hardcoded data I've provided for the test then ruby file permissions don't seem to be the issue. Could there be a permissions issue with opening a Firefox window from the www-data user?
When I run
ruby -d -v /var/www/watir_test.rb
I get:
{:extension=>:webdriver} {"app.update.enabled"=>"false"} {"browser.link.open_newwindow"=>"2"} {"browser.shell.checkDefaultBrowser"=>"false"} {"extensions.update.enabled"=>"false"} {"security.warn_entering_secure.show_once"=>"false"} {"webdriver_assume_untrusted_issuer"=>true} {"startup.homepage_welcome_url"=>"\"about:blank\""} {"browser.tabs.warnOnClose"=>"false"} {"extensions.update.notifyUser"=>"false"} {"toolkit.networkmanager.disable"=>"true"} {"security.warn_entering_weak.show_once"=>"false"} {"webdriver_firefox_port"=>"7055"} {"browser.download.manager.showWhenStarting"=>"false"} {"extensions.logging.enabled"=>"true"} {"network.manage-offline-status"=>"false"} {"network.http.max-connections-per-server"=>"10"} {"security.warn_submit_insecure"=>"false"} {"security.warn_entering_weak"=>"false"} {"security.warn_leaving_secure"=>"false"} {"prompts.tab_modal.enabled"=>"false"} {"security.warn_viewing_mixed.show_once"=>"false"} {"dom.max_script_run_time"=>"30"} {"webdriver_accept_untrusted_certs"=>true} {"browser.safebrowsing.enabled"=>"false"} {"security.warn_leaving_secure.show_once"=>"false"} {"signon.rememberSignons"=>"false"} {"javascript.options.showInConsole"=>"true"} {"app.update.auto"=>"false"} {"browser.EULA.3.accepted"=>"true"} {"browser.tabs.warnOnOpen"=>"false"} {"dom.disable_open_during_load"=>"false"} {"network.http.phishy-userpass-length"=>"255"} {"security.warn_entering_secure"=>"false"} {"browser.startup.homepage"=>"\"about:blank\""} {"browser.EULA.override"=>"true"} {"browser.dom.window.dump.enabled"=>"true"} {"browser.startup.page"=>"0"} {"browser.link.open_external"=>"2"} {"browser.search.update"=>"false"} {"browser.sessionstore.resume_from_crash"=>"false"} {"security.warn_viewing_mixed"=>"false"} {"dom.report_all_js_exceptions"=>"true"} {"webdriver_enable_native_events"=>false} {"devtools.errorconsole.enabled"=>"true"}
How do I get PHP to execute the shell_exec properly? The script works and my initial tests were run using firewatir (which shell_exec ran fine) but I am really wanting to use Watir-WebDriver instead of FireWatir - WatirWebDriver should be capable of running a Chrome browser (and IE on a Windows machine) while FireWatir can only run Firefox.
Thanks
Gabe
Here's my "Create Browser" code:
# Include the RubyGems file
require 'rubygems'
# Include the Watir-WebDriver file.
require 'watir-webdriver'
# Create the necessary objects
def create_browser(proxy)
# Setup the proper Firefox Profile
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = Selenium::WebDriver::Proxy.new :http => proxy
puts "<br>Using proxy " + proxy + "..."
#ff=FireWatir::Firefox.new :profile => profile
ff = Watir::Browser.new :firefox #, :profile => profile
puts "<br>Firefox ready..."
return ff
end
If the server is headless, you should install the headless gem so that Firefox can work.
require 'watir-webdriver'
require 'headless'
headless = Headless.new
headless.start
b = Watir::Browser.start 'www.google.com'
puts b.title
b.close
headless.destroy
See: http://watirwebdriver.com/headless/
It't a permission problem, the PHP script runs with the permissions of the server, normally apache.
You can do a sudo www and try to run the script then with rb to see if there is a problem when running ruby with the server user.
Put the two lines of code that is below at the very top of your PHP script. The result of this is that when you browse to your PHP page with your browser it will display exactly what the errors are, including any permission errors.
ini_set("display_errors",1);
error_reporting(E_ALL);
So a recent update to Firefox killed it's support for Watir (no JSSH update if I remember). As a result I rewrote what little code I had for Selenium::WebDriver. But I'm thinking that isn't particularly relevant (its included in case it is relevant I don't know it).
My ultimate solution was to use phpseclib. This allows me to SSH into the machine via their SSH2 PHP class. Once logged in as my typical username (with typical password) I was able to fire off a headless version of my script no problem. The only real issues this creates is that I now have to view everything that's going on through log files and screenshots but that was likely to be true no matter what solution I came up with.
phpseclib needs your username and password for the server (at least until you set some form of public private key pair). So I wouldn't want to do this on a publicly available machine without a couple of layers of security - like setting .htaccess to deny read access to the file with the login data, encrypting the password stored in the file, etc. However, for my purposes I'm logging into one machine on my LAN from another machine on my LAN. The password is only good on my LAN (not my web servers) and while my LAN can see out it should not be (easily) available to the rest of the world (to the best of my knowledge). So the security concerns are minimal.
I never did figure this out. Headless isn't the answer to getting PHP to exec the script. I'm pretty sure it is a permissions issue with Firefox's executable but I can't be positive until I find an actual fix.
Ultimately I've had to break up the tool where PHP manages the DB and task scheduling. Then PHP creates text files with all the data necessary for ruby to run the browser to right site, login, etc, etc... Then ruby moves the data file to one of a few different folders (success, failure, bad login, etc) and adds some text to the data file. Finally PHP parses all this info in the moved text files and updates the DB with that info.
It's less than ideal but it is getting the job done. Now I just need to figure out how to run all of this with mutliple threads...
Thanks for the help