piston/readme.md

133 lines
4.3 KiB
Markdown
Raw Normal View History

2018-09-21 20:45:09 +02:00
## Piston
2018-09-22 06:15:24 +02:00
Piston is the underlying engine for running untrusted and possibly malicious code that originates
from from EMKC contests and challenges. It's also used in the Engineer Man Discord server via
[felix bot](https://github.com/engineer-man/felix).
2018-09-21 20:45:09 +02:00
#### Installation
2019-05-31 20:09:47 +02:00
```
# clone and enter repo
git clone https://github.com/engineer-man/piston
cd piston/lxc
# install dependencies
# centos:
2019-05-31 20:59:51 +02:00
yum install -y epel-release
yum install -y lxc lxc-templates debootstrap libvirt
2019-06-17 07:37:41 +02:00
systemctl start libvirtd
2019-05-31 20:09:47 +02:00
2019-06-17 07:37:41 +02:00
# ubuntu server 18.04:
apt install lxc lxc-templates debootstrap libvirt0
2019-05-31 20:09:47 +02:00
2019-06-17 07:37:41 +02:00
# everything else:
# not documented, please open pull requests with commands for debian/arch/macos
2019-05-31 20:09:47 +02:00
# create and start container
lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64
./start
2019-05-31 22:34:48 +02:00
# open a shell to the container
2019-05-31 20:09:47 +02:00
./shell
# install all necessary piston dependencies
2019-06-19 07:09:56 +02:00
export HOME=/opt
2019-05-31 20:59:51 +02:00
echo 'export PATH=/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin' >> /root/.bashrc
echo 'export PATH=$PATH:/root/.cargo/bin' >> /root/.bashrc
2019-05-31 20:14:24 +02:00
sed -i \
's/http:\/\/archive.ubuntu.com\/ubuntu/http:\/\/mirror.math.princeton.edu\/pub\/ubuntu/' \
/etc/apt/sources.list
2019-05-31 20:09:47 +02:00
apt-get update
apt-get -y install git tzdata nano \
dpkg-dev build-essential python python3 \
2019-08-08 18:42:30 +02:00
ruby nodejs npm golang php7.2 r-base mono-complete \
2019-05-31 20:11:28 +02:00
nasm openjdk-8-jdk ubuntu-make bf
2019-08-08 18:42:30 +02:00
npm install -g typescript
2019-05-31 20:09:47 +02:00
umake swift
2019-06-19 07:09:56 +02:00
ln -s /opt/.local/share/umake/swift/swift-lang/usr/bin/swift /usr/bin/swift
curl https://sh.rustup.rs > rust.sh
sh rust.sh -y
ln -s /opt/.cargo/bin/rustc /usr/bin/rustc
2019-05-31 20:09:47 +02:00
rm -rf /home/ubuntu
chmod 777 /tmp
# create runnable users and apply limits
for i in {1..150}; do
useradd -M runner$i
usermod -d /tmp runner$i
echo "runner$i soft nproc 64" >> /etc/security/limits.conf
echo "runner$i hard nproc 64" >> /etc/security/limits.conf
echo "runner$i soft nofile 2048" >> /etc/security/limits.conf
echo "runner$i hard nofile 2048" >> /etc/security/limits.conf
done
# leave container
exit
# optionally run tests
cd ../tests
./test_all_lxc
```
2018-09-21 20:45:09 +02:00
2019-06-17 07:06:38 +02:00
#### CLI Usage
- `lxc/execute [language] [file path] [arg]...`
2018-09-21 20:45:09 +02:00
2019-06-17 07:06:38 +02:00
#### API Usage
2019-06-17 07:09:35 +02:00
To use the API, it must first be started. To start the API, run the following:
```
cd api
./start
```
2019-06-17 07:06:38 +02:00
The Piston API exposes one endpoint at `http://127.0.0.1:2000/execute`.
This endpoint takes the following JSON payload and expects at least the language and source. If
source is not provided, a blank file is passed as the source.
```json
{
"language": "js",
"source": "console.log(process.argv)",
"args": [
"1",
"2",
"3"
]
}
```
A typical response when everything succeeds will be similar to the following:
```json
{
"ran": true,
"output": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]"
}
```
If an invalid language is supplied, a typical response will look like the following:
```json
{
"code": "unsupported_language",
"message": "whatever is not supported by Piston"
}
```
2018-09-21 20:45:09 +02:00
#### Supported Languages
2019-08-08 18:42:30 +02:00
Currently python2, python3, c, c++, go, node, ruby, r, c#, nasm, php, java, swift, brainfuck, rust, bash, and typescript is supported.
2018-09-21 20:45:09 +02:00
2018-09-22 06:15:24 +02:00
#### Principle of Operation
2019-05-31 20:09:47 +02:00
Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Go which takes
in execution requests and executes them in the container. High level, the API writes
a temporary source and args file to `/tmp` and that gets mounted read-only along with the execution scripts into the container.
2018-09-22 18:52:19 +02:00
The source file is either ran or compiled and ran (in the case of languages like c, c++, c#, go, etc.).
2018-09-22 06:15:24 +02:00
#### Security
2019-05-31 20:09:47 +02:00
LXC provides a great deal of security out of the box in that it's separate from the system.
Piston takes additional steps to make it resistant to
2018-09-22 06:15:24 +02:00
various privilege escalation, denial-of-service, and resource saturation threats. These steps include:
- Disabling outgoing network interaction
- Capping max processes at 64 (resists `:(){ :|: &}:;`, `while True: os.fork()`, etc.)
- Capping max files at 2048 (resists various file based attacks)
2018-09-22 06:15:24 +02:00
- Mounting all resources read-only (resists `sudo rm -rf --no-preserve-root /`)
- Running as a variety of unprivileged users
2018-09-22 18:52:19 +02:00
- Capping runtime execution at 3 seconds
2018-09-22 06:15:24 +02:00
- Capping stdout to 65536 characters (resists yes/no bombs and runaway output)
- SIGKILLing misbehaving code
2018-09-21 20:45:09 +02:00
#### License
Piston is licensed under the MIT license.