Let's say the user has installed a python interpreter on their machine/browser, for example, using something like https://github.com/iodide-project/pyodide. I understand not allowing someone to enter in arbitrary code when they don't own the resources, for example doing something like:
exec('while 1: os.fork()')
However, if the user is executing the code on their own machine, is there anything wrong with allowing them to run arbitrary evals and execs, and just telling them "Please use at your own risk"? The use case is we give the user an environment to work with a spreadsheet, and they can enter in formulas using python, and we just 'pass-through' the entered string (in the spreadsheet cell) to their python environment.
If you are OK with the user being able to run arbitrary Javascript code client side (which is true for all websites), it should be also OK for them to run arbitrary code with Pyodide. Both are sandboxed by the browser.
For instance, they won't be able to interact with their actual file system, nor generally make any system calls that don't pass through the Webassembly VM. See https://webassembly.org/docs/security/ for more details.
Related
I am currently in the process of developing a python code that connects to a remote brocade switch using the fabric module and issue some configuration commands. The problem I am facing is when it comes to commands that require an input from the user (i.e. yes/no).
I read several posts that have advised to use Fabric's native settings methods as well as wexpect but none have been successful.
I checked the following links but none were able to help with my code:
how to handle interactive shell in fabric python
How to answer to prompts automatically with python fabric?
Python fabric respond to prompts in output
Below is an example of the command output that requires to be automated:
DS300B_Autobook:admin> cfgsave
You are about to save the Defined zoning configuration. This
action will only save the changes on Defined configuration.
If the update includes changes to one or more traffic isolation
zones, you must issue the 'cfgenable' command for the changes
to take effect.
Do you want to save the Defined zoning configuration only? (yes, y, no, n): [no]
The code that I have written for this is show below (tried to make it exactly the same as the output the command provides):
with settings(prompts={"DS300B_Autobook:admin> cfgsave\n"
"You are about to save the Defined zoning configuration. This\n"
"action will only save the changes on Defined configuration.\n"
"If the update includes changes to one or more traffic isolation\n"
"zones, you must issue the 'cfgenable' command for the changes\n"
"to take effect.\n"
"Do you want to save the Defined zoning configuration only? (yes, y, no, n): [no] " : "yes"}):
c.run('cfgsave')
If there is a way to have it display the output of the command to the screen and prompt me to provide the input that would also be reasonable solution.
I am trying to kill a task but in order to do it I need admin privileges.
And so far I was not able to find a functional code that would bypass the need for admin. And when I found one than it was filled with errors or was made for python 2.
I was not able to find a functional code that would bypass the need for admin
Assuming that you have admin privileges on your system, you can run your script with evaluated privileges as detailed in this answer. Otherwise, aside from exploits specific to your version of Windows, it is not possible to "bypass" the need for admin.
As for not being able to use code written in Python 2, you can always convert code between between Python versions. This can be done manually or using an automated tool such as the standard 2to3 program that ships with CPython.
One other side note: the infinite loop in the sample of code that you posted would normally be written as
while True:
# body statements
Using 1 in place of True still works as non-zero integers are "truthy" when evaluated in a context where a boolean expression is expected.
We're working with an older zope version (2.10.6-final, python 2.4.5) and working with a database adapter called ZEIngresDA. We have an established connection for it, and the test function shows that it is totally functional and can connect and run queries.
My job is to change the way that the queries are actually executing, so that they're properly parameterizing variables to protect against sql injection. With that said, I'm running into a security issue that I'm hoping someone can help with.
connection = container.util.ZEIngresDAName()
#returning connection at this point reveals it to be of type ZEIngresDA.db.DA,
#which is the object we're looking for.
connection.query("SELECT * from data WHERE column='%s';", ('val1',))
#query is a function that is included in class DA, functions not in DA throw errors.
Here we run into the problem. Testing this script brings up a login prompt that, when logged into, immediately comes up again. I recognize that this is likely some type of security setting, but I've been unable to find anything online about this issue, though this old of zope documentation isn't spectacular online anyways. If this sounds familiar to you or you have any ideas, please let me know.
I have some experience using Zope2 but it's hard to give a good answer with the limited information you've posted. I'm assuming here that you're using a Python script within the ZMI
Here's a list of things I would check:
Are you logged into the root folder rather than a sub folder in the ZMI? This could cause a login prompt as you're requesting a resource that you do not have access to use
In the ZMI double check the "security" tab of the script you're trying to run to ensure that your user role has permission to run the script
Whilst you're there check the "proxy" tab to ensure that the script itself has permission to call the functions within it
Also worth checking that the products you're trying to use were installed by a user which is still listed in the root acl_user folder - from memory this can cause issues with the login prompt
Best of luck to you - happy (also sad) to hear that there's at least one other Zope user out there!
I would like users of my program to be able to define custom scripts in python without breaking the program. I am looking at something like this:
def call(script):
code = "access modification code" + script
exec(code)
Where "access modification code" defines a scope such that script can only access variables it instantiates itself. Is it possible to do this or something with similar functionality, such as creating a new python environment with its own scope and then receiving output from it?
Thank you for your time :)
Clarification Edit
"I want to prevent both active attacks and accidental interaction with the program variables outside the users script (hence hiding all globals). The user scripts are intended to be small and inputted as text. The return of the user script needs to be immediate, as though it were native to the program."
There's two separate problems you want to prevent in this scenario:
Prevent an outside attacker from running arbitrary code in the context of the OS user executing your program. This means preventing arbitrary code execution and privilege escalation.
Preventing a legitimate user of your program from changing the program behavior in unintended ways.
For the first problem, you need to make sure that the source of the python code you execute is the user. You shouldn't accept input from a socket, or from a file that other users can write to. You need to make sure, somehow, that it was the user who is running the program that provided the input.
Actual solutions will depend on your OS, but you may want to consider setting up restrictive file permissions, if you're storing the code in a file.
Don't ignore or downplay this problem, or your users will fall victim to virus/malware/hackers thanks to your program.
The way you solve the second problem depends on what exactly constitutes intended behaviour in your program. If you're happy with outputting simple data structures, you can run your user-inputted code in a separate process, and pass the result over a pipe in a serialization format such as JSON or YAML.
Here's a very simple example:
#remember to set restrictive file permissions on this file. This is OS-dependent
USER_CODE_FILE="/home/user/user_code_file.py"
#absolute path to python binary (executable)
PYTHON_PATH="/usr/bin/python"
import subprocess
import json
user_code= '''
import json
my_data= {"a":[1,2,3]}
print json.dumps(my_data)
'''
with open(USER_CODE_FILE,"wb") as f:
f.write(user_code)
user_result_str= subprocess.check_output([PYTHON_PATH, USER_CODE_FILE])
user_result= json.loads( user_result_str )
print user_result
This is a fairly simple solution, and it has significant overhead. Don't use this if you need to run the user code many times in a short period of time.
Ultimately, this solution is only effective against unsophisticated attackers (users). Generally speaking, there's no way to protect any user process from the user itself - nor would it make much sense.
If you really want more assurance, and want to mitigate the first problem too, you should run the process as a separate ("guest") user. This, again, is OS-dependent.
Finally a warning: avoid exec and eval to the best of your abilities. They don't protect either your program or the user against the inputted code. There's a lot of information about this on the web, just search for "python secure eval"
I have successfully achieved this using the method documented at Run IPython Notebook in Iframe from another Domain . However, this required editing the user config file. I was really hoping to be able to set this up via the command-line instead (for reasons).
http://ipython.org/ipython-doc/1/config/overview.html indicates that configuration via the command line is possible. However, all the examples are for simple true/false value assignment. To set the server up to allow embedding, it is necessary to set a value inside a dictionary. I can't work out how to pass a dictionary in through the command-line.
Another acceptable option would be a configuration overrides file.
Some people will wonder -- why all this trouble!?!
First of all, this isn't for production. I'm trying to support non-developers by writing a web-based application which integrates Ipython notebooks within it using iframes. Despite being on the same machine, it appears that the different port number used is enough to mean that I can't do simple iframe embedding without setting the x-frame insecurity bit.
Being able to do this via the command line lets me set the behaviour in the launch script rather than having to bundle a special configuration file inside my app, and also write an installer.
I really hope I've make the question clear enough! Thanks for any and all suggestions and help!
Looking over the IPython source for the loaders, it seems like it will execute whatever python code you put on the right hand side. I've not tested it, but based on the link you provided, you can probably pass something like
--NotebookApp.webapp_settings=dict('headers'=dict('X-Frame-Options'='ALLOW-FROM https://example.com/'))