We publish the translation of the Installing XSS Hunter article and check the instructions with our own example.
Spoiler: Everything works!
Why XSS Hunter?
Many readers probably already know that you can register at https://xsshunter.com/ and use xsshunter for free. In a nutshell, this is a tool used primarily for blind XSS searches . Why then deploy your own service for this task, you ask.
- Everything's under control. If something goes wrong, you can check and investigate the problem.
- Stability. You know for sure whether the service is working or not. You can decide for yourself when to stop it. Imagine that you have hundreds of data sets ready for execution, and the owner of the service suddenly turns it off. It would be sad!
- You are in control of the data. Companies usually do not like bug hunters using third-party solutions, because in this case they cannot verify whether the data has been deleted or not.
Bonus: Thanks to the article, you will find out how everything works.
If this article is not enough for you, we recommend reading the work of our colleagues from Jet Infosystems.
How to use?
A guide to using XSS Hunter can be found on the XSS Hunter GitHub site .
This is a great start, but this guide is a little out of date. The situation is the same with the codebase, so I had to change a few things to work on Ubuntu 18.04. In this article I will tell you how to work with XSS Hunter after all.
The first steps
At this point, I am using the official guide as a basis.
We also assume that you have a working server and basic server management experience. Despite this, I will still try to go deeper. Feel free to ask questions!
We will need:
- VPS or other place to host the service
We repeated the author's instructions using the example of VDS Timeweb: timeweb.com/ru/services/vds . Further in the article, we share what we got at each stage, in hidden spoilers.
We have: timeweb.com/ru/services/domains .
:
XSS Hunter
mailgun
1. Register a mailgun account here . Don't forget to uncheck the box, noted below in the screenshot.
2. Follow the instructions to verify your email address and phone number.
3. Go to the submit tab and select your mail domain.
4. At the top right of the screen, add the email addresses where you want to receive alerts. This should be your real and current address. For example john.doe@gmail.com.
5. After completing the above, press the "Select" button in the block highlighted by the API label.
6. Make a note of the API key and email domain. You will need them soon!
The email domain is the last part of the base API URL: sandboxe678 .
Using VDS Timeweb as an example
: sandbox82f7e729ed934d1189bcc6bd32aaa977.
7. Open mail and find the letter from mailgun.
8. Confirm your email address by clicking on the link in the email.
(The letter will be sent to the address you specified in step 4, that is, in our case, to john.doe@gmail.com).
Make sure everything works
Use the following command to send email from your server to make sure the service is running.
Replace:
[API_KEY] : your API key
[API_BASE_URL] : your base URL API
[YOUR_EMAIL] : your real email
For example: john.doe@gmail.com .
curl -s --user 'api:[API_KEY]' \
https://api.mailgun.net/v3/[API_BASE_URL]/messages \
-F from='Excited User <mailgun@[API_BASE_URL]>' \
-F to=[YOUR_EMAIL] \
-F subject='Hello' \
-F text='Testing some Mailgun awesomeness!'
Note : The EU version of the service has a different URL. A quick Google search or checking your mailgun account will tell you exactly what to change.
Note from the Timeweb expert
curl:
:
curl -s --user 'api:67ee2b8a922268ac335eb00262b33711-9b1bf5d3-919027d8' \https://api.mailgun.net/v3/sandbox82f7e729ed934d1189bcc6bd32aaa977.mailgun.org/messages \
-F from='Excited User <mailgun@sandbox82f7e729ed934d1189bcc6bd32aaa977.mailgun.org>' \
-F to=r.tkach@timeweb.ru \
-F subject='' \
-F text=' MailGun'
:
{
"id": "<20201029124602.1.C81E1E4029FB7DC4@sandbox82f7e729ed934d1189bcc6bd32aaa977.mailgun.org>",
"message": "Queued. Thank you."
}
Check your account to make sure you received an email like in the example below. If there is no email, you need to troubleshoot before proceeding to the next step.
Setting up dependencies
Install the required packages first:
# install dependencies
sudo apt-get install nginx && sudo apt-get install postgresql postgresql-contrib
Using VDS Timeweb as an example
root@372526-twosa:~# apt-get install nginx && apt-get install postgresql postgresql-contrib
Next, set up the postgres user and database for the XSS Hunter. Change EXAMPLE_PASSWORD to a more secure password. I highly recommend using a password manager!
sudo -i -u postgres
psql template1
CREATE USER xsshunter WITH PASSWORD 'EXAMPLE_PASSWORD';
CREATE DATABASE xsshunter;
\q
exit
Using VDS Timeweb as an example
root@372526-twosa:~# sudo -i -u postgres
postgres@372526-twosa:~$ psql template1
psql (10.14 (Ubuntu 10.14-0ubuntu0.18.04.1))
Type "help" for help.
template1=# create user xsshunter with password '6fhQg18YFrna2LbX2EDWHfLoewy32i';
CREATE ROLE
template1=# create database xsshunter;
CREATE DATABASE
template1=# \q
Service installation
First, we clone the repository:
git clone https://github.com/mandatoryprogrammer/xsshunter
cd xsshunter
Using VDS Timeweb as an example
root@372526-twosa:~# git clone https://github.com/mandatoryprogrammer/xsshunter
root@372526-twosa:~# cd xsshunter
Please note : Python2 required! The repository does not support Python3.
To run the configuration script, we need to add an additional dependency:
# install yaml support for python
sudo apt-get install pyyaml
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# apt install python-pip
root@372526-twosa:~/xsshunter# pip install pyyaml
Thanks to user xYantix for providing a working solution in this pull request .
Service setup
Ok, let's get started! We are ready to run the configuration script.
# generate yaml config file
./generate_config.py
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# ./generate_config.py
I'll show you the process step by step. To see an example of the output, see the example below. I've added numbers for easy navigation. Otherwise, everything should look the same.
1. Enter your domain name. I used mydomain.com as an example.
Using VDS Timeweb as an example
372526-twosa.tmweb.ru.
2. Enter your Mailgun API Key that you found and saved earlier.
3. Enter your Mailgun domain name, which you also wrote down earlier. (What starts with a sandbox).
4. I think it could be anything @ [Mailgun domain name] , but I have followed the standard naming from mailgun since the name doesn't really matter here. I suggest using: mailgun @ [Mailgun domain name]. Remember to replace [Mailgun domain name] with your own.
5. This is to get people to report suspected abuse of the tool. Your real and current email should be indicated here. For example: john.doe@gmail.com .
6. If you have followed all the steps in this article, simply enter xsshunter.
7. Enter the password you chose when creating the database. Listed above as EXAMPLE_PASSWORD . Replace the text [YOUR_REALLY_SECURE_PASSWORD] with your password EXAMPLE_PASSWORD .
8. As in step # 6, if you followed this tutorial, just enter xsshunter.
Oops! The setup is complete!
If you ever need to change these values, you can edit them directly in the config.yaml file.
__ __ _____ _____ _ _ _
\ \ / // ____/ ____| | | | | | |
\ V /| (___| (___ | |__| |_ _ _ __ | |_ ___ _ __
> < \___ \\\\___ \ | __ | | | | '_ \| __/ _ \ '__|
/ . \ ____) |___) | | | | | |_| | | | | || __/ |
/_/ \_\_____/_____/ |_| |_|\__,_|_| |_|\__\___|_|
Setup Utility
(1)
What is the base domain name you will be using?
(ex. localhost, www.example.com)
Domain? mydomain.com
Great! Now let's setup your Mailgun account to send XSS alerts to.
(2)
Enter your API key:
(ex. key-8da843ff65205a61374b09b81ed0fa35)
Mailgun API key: 92740xxxxxxxxxxxxxxxxxxxxxxxxxxx-65bxxx58-8ffxxxxx
(3)
What is your Mailgun domain?
(ex. example.com)
Mailgun domain: sandboxe6784d1f69d9486484bb8db10ab02380.mailgun.org
(4)
What email address is sending the payload fire emails?:
(ex. no-reply@example.com)
Sending email address:
mailgun@sandboxe6784d1f69d9486484bb8db10ab02380.mailgun.org
(5)
Where should abuse/contact emails go?:
(ex. yourpersonal@gmail.com)
Abuse/Contact email: xsshunter@mydomain.com
(6)
What postgres user is this service using?
(ex. xsshunter)
Postgres username: xsshunter
(7)
What is the postgres user's password?
(ex. @!$%@^%UOFGJOEJG$)
Postgres password: [YOUR_REALLY_SECURE_PASSWORD]
(8)
What is the postgres user's DB?
(ex. xsshunter)
Postgres DB: xsshunter
Generating cookie secret...
Minting new nginx configuration file...
Setup complete! Please now copy the 'default' file to
/etc/nginx/sites-enabled/default
This can be done by running the following:
sudo cp default /etc/nginx/sites-enabled/default
Also, please ensure your wildcard SSL certificate and key are available at
the following locations:
/etc/nginx/ssl/mydomain.com.crt; # Wildcard SSL certificate
/etc/nginx/ssl/mydomain.com.key; # Wildcard SSL key
Good luck hunting for XSS!
Using VDS Timeweb as an example
Setup Utility
What is the base domain name you will be using?
(ex. localhost, www.example.com)
Domain? 372526-twosa.tmweb.ru
Great! Now let's setup your Mailgun account to send XSS alerts to.
Enter your API key:
(ex. key-8da843ff65205a61374b09b81ed0fa35)
Mailgun API key: 67ee**************************-9b*******-919*****
What is your Mailgun domain?
(ex. example.com)
Mailgun domain: sandbox82f7e729ed934d1189bcc6bd32aaa977.mailgun.org
What email address is sending the payload fire emails?:
(ex. no-reply@example.com)
Sending email address: mailgun@sandbox82f7e729ed934d1189bcc6bd32aaa977.mailgun.org
Where should abuse/contact emails go?:
(ex. yourpersonal@gmail.com)
Abuse/Contact email: r.tkach@timeweb.ru
What postgres user is this service using?
(ex. xsshunter)
Postgres username: xsshunter
What is the postgres user's password?
(ex. @!$%@^%UOFGJOEJG$)
Postgres password: [EXAMPLE_PASSWORD]
What is the postgres user's DB?
(ex. xsshunter)
Postgres DB: xsshunter
Generating cookie secret...
Minting new nginx configuration file...
Setup complete! Please now copy the 'default' file to /etc/nginx/sites-enabled/default
This can be done by running the following:
sudo cp default /etc/nginx/sites-enabled/default
Also, please ensure your wildcard SSL certificate and key are available at the following locations:
/etc/nginx/ssl/xsshunter.timeweb.ru.crt; # Wildcard SSL certificate
/etc/nginx/ssl/xsshunter.timeweb.ru.key; # Wildcard SSL key
Good luck hunting for XSS!
-mandatory
You should now have 2 new files in your xsshunter folder:
- config.yaml (contains API keys and credentials)
- default (contains nginx config)
NGINX configuration
Change the location of the SSL certificate
If you are using Let's Encrypt like me, you will need to modify the default .
For the configuration to work with the default Let's Encrypt settings, we must comment out all entries:
/etc/nginx/ssl/mydomain.com.crt; # Wildcard SSL certificate
/etc/nginx/ssl/mydomain.com.key; # Wildcard SSL key
and replace with
ssl_certificate /etc/letsencrypt/live/mydomain.com-0001/fullchain.pem ; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com-0001/privkey.pem; # managed by Certbot
Notes:
1. Replace mydomain.com with your domain name!
2. Everything after the # symbol is comments. You can delete them if you like.
Your default file should now look like this:
server {
# Redirect HTTP to www
listen 80;
server_name mydomain.com;
location / {
rewrite ^/(.*)$ https://www.mydomain.com/$1 permanent;
}
}
server {
# Redirect payloads to HTTPS
listen 80;
server_name *.mydomain.com;
proxy_set_header X-Forwarded-For $remote_addr;
return 307 https://$host$request_uri;
client_max_body_size 500M; # In case we have an extra large payload capture
}
server {
# Redirect HTTPS to www
listen 443;
ssl on;
# New conf
ssl_certificate /etc/letsencrypt/live/mydomain.com-0001/fullchain.pem; #
managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com-0001/privkey.pem; #
managed by Certbot
# Original conf
#ssl_certificate /etc/nginx/ssl/mydomain.com.crt; # Wildcard SSL certificate
#ssl_certificate_key /etc/nginx/ssl/mydomain.com.key; # Wildcard SSL
certificate key
server_name mydomain.com;
location / {
rewrite ^/(.*)$ https://www.mydomain.com/$1 permanent;
}
}
server {
# API proxy
listen 443;
ssl on;
# New conf
ssl_certificate /etc/letsencrypt/live/mydomain.com-0001/fullchain.pem; #
managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com-0001/privkey.pem; #
managed by Certbot
# Original conf
#ssl_certificate /etc/nginx/ssl/mydomain.com.crt; # Wildcard SSL certificate
#ssl_certificate_key /etc/nginx/ssl/mydomain.com.key; # Wildcard SSL
certificate key
server_name *.mydomain.com;
access_log /var/log/nginx/mydomain.com.vhost.access.log;
error_log /var/log/nginx/mydomain.com.vhost.error.log;
client_max_body_size 500M;
location / {
proxy_pass http://localhost:8888;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
server {
# Redirect api to HTTPS
listen 80;
server_name api.mydomain.com; # Subdomain for API server
proxy_set_header X-Forwarded-For $remote_addr;
return 307 https://api.mydomain.com$request_uri;
client_max_body_size 500M; # In case we have an extra large payload capture
}
server {
# Redirect www to HTTPS
listen 80;
server_name www.mydomain.com;
location / {
rewrite ^/(.*)$ https://www.mydomain.com/$1 permanent;
}
}
server {
# GUI proxy
listen 443;
server_name www.mydomain.com;
client_max_body_size 500M;
ssl on;
# New conf
ssl_certificate /etc/letsencrypt/live/mydomain.com-0001/fullchain.pem; #
managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com-0001/privkey.pem; #
managed by Certbot
# Original conf
#ssl_certificate /etc/nginx/ssl/mydomain.com.crt; # Wildcard SSL certificate
#ssl_certificate_key /etc/nginx/ssl/mydomain.com.key; # Wildcard SSL
certificate key
location / {
proxy_pass http://localhost:1234;
proxy_set_header Host $host;
}
}
Using VDS Timeweb as an example
server {
# Redirect HTTP to www
listen 80;
server_name 372526-twosa.tmweb.ru;
location / {
rewrite ^/(.*)$ https://www.372526-twosa.tmweb.ru/$1 permanent;
}
}
server {
# Redirect payloads to HTTPS
listen 80;
server_name *.372526-twosa.tmweb.ru;
proxy_set_header X-Forwarded-For $remote_addr;
return 307 https://$host$request_uri;
client_max_body_size 500M; # In case we have an extra large payload capture
}
server {
# Redirect HTTPS to www
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/372526-twosa.tmweb.ru/fullchain.pem; # Wildcard SSL certificate
ssl_certificate_key /etc/letsencrypt/live/372526-twosa.tmweb.ru/privkey.pem; # Wildcard SSL certificate key
server_name 372526-twosa.tmweb.ru;
location / {
rewrite ^/(.*)$ https://www.372526-twosa.tmweb.ru/$1 permanent;
}
}
server {
# API proxy
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/372526-twosa.tmweb.ru/fullchain.pem; # Wildcard SSL certificate
ssl_certificate_key /etc/letsencrypt/live/372526-twosa.tmweb.ru/privkey.pem; # Wildcard SSL certificate key
server_name *.372526-twosa.tmweb.ru;
access_log /var/log/nginx/372526-twosa.tmweb.ru.vhost.access.log;
error_log /var/log/nginx/372526-twosa.tmweb.ru.vhost.error.log;
client_max_body_size 500M;
location / {#
proxy_pass http://localhost:8888;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
server {
# Redirect api to HTTPS
listen 80;
server_name api.372526-twosa.tmweb.ru; # Subdomain for API server
proxy_set_header X-Forwarded-For $remote_addr;
return 307 https://api.372526-twosa.tmweb.ru$request_uri;
client_max_body_size 500M; # In case we have an extra large payload capture
}
server {
# Redirect www to HTTPS
listen 80;
server_name www.372526-twosa.tmweb.ru;
location / {
rewrite ^/(.*)$ https://www.372526-twosa.tmweb.ru/$1 permanent;
}
}
server {
# GUI proxy
listen 443;
server_name www.372526-twosa.tmweb.ru;
client_max_body_size 500M;
ssl on;
ssl_certificate /etc/letsencrypt/live/372526-twosa.tmweb.ru/fullchain.pem; # Wildcard SSL certificate
ssl_certificate_key /etc/letsencrypt/live/372526-twosa.tmweb.ru/privkey.pem; # Wildcard SSL certificate key
location / {
proxy_pass http://localhost:1234;
proxy_set_header Host $host;
}
}
Let's apply the NGINX configuration
The next step is to move the file to the nginx folder. It is considered good practice to have configuration files in the ... / sites-available folder and then create symbolic links to the configurations you are using to ... / sites-enabled . We will do just that.
I name the configuration file so that it is clear from the name which service it belongs to.
Here's how to do it!
# move file and give proper name
cp xsshunter/default /etc/nginx/sites-available/xsshunter-mydomain.com
# symlink the file to sites-enabled to make it active
ln -s /etc/nginx/sites-available/xsshunter-mydomain.com
/etc/nginx/sites-enabled/xsshunter-mydomain.com
# test for errors in the configuration
sudo nginx -t
# if no errors, restart nginx for changes to take effect
sudo systemctl restart nginx
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# cp default /etc/nginx/sites-available/372526-twosa.tmweb.ru
root@372526-twosa:~/xsshunter# ln /etc/nginx/sites-available/372526-twosa.tmweb.ru /etc/nginx/sites-enabled/372526-twosa.tmweb.ru
root@372526-twosa:~/xsshunter# nginx -t
root@372526-twosa:~/xsshunter# systemctl restart nginx
If you've never started nginx before, the last command should be:
sudo systemctl start nginx
Installing the API Server
First, the API server needs certain dependencies as well.
The manual says to run the following command:
sudo apt-get install python-virtualenv python-dev libpq-dev libffi-dev
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# apt-get install python-virtualenv python-dev libpq-dev libffi-dev
, python-virtualenv pip.
Try again!
Unfortunately I was unable to run the virtualenv command , so I installed the API server with
pip install virtualenv
Problem solved, I was able to continue!
Let's go to the desired directory.
Once in the right directory, you need to create a virtual environment.
Here's how to do it:
# change folder - you know that already!
cd xsshunter/api
# find your Python2 executable path
which python2
# create a python2 virtual environment in the env folder
virtualenv -p MY/EXECUTABLE/PATH env
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# cd xsshunter/api
root@372526-twosa:~/xsshunter/api# which python2
/usr/bin/python2
root@372526-twosa:~/xsshunter/api# virtualenv -p /usr/bin/python2 env
Running virtualenv with interpreter /usr/bin/python2
New python executable in /root/xsshunter/api/env/bin/python2
Also creating executable in /root/xsshunter/api/env/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
Make sure you change MY / EXECUTABLE / PATH in the last command to what python2 command output . For me this is: / usr / bin / python2 .
After we have created the virtual environment, activate it with the following command. You should notice a change in your command line.
# activate environment
. env/bin/activate
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter/api# . env/bin/activate
(env) root@372526-twosa:~/xsshunter/api# ls
apiserver.py env logs models probe.js requirements.txt templates
There are also dependency issues as the repository is not actively maintained.
Thus, we must make the following changes to the file requirements.txt :
1. psycopg2 2.6.1 == => psycopg2 == 2.7.3.1
2. bcrypt 2.0.0 == => bcrypt == 3.1.7
Use your favorite text editor for this. I am using VIM.
Once that's done, it's time to install all dependencies and start the API server to make sure everything is working as expected. Let's try!
# install requirements
pip install -r requirements.txt
# run the API server
./apiserver.py
Using VDS Timeweb as an example
(env) root@372526-twosa:~/xsshunter/api# pip install -r requirements.txt
(env) root@372526-twosa:~/xsshunter/api# ./apiserver.py
The install command should output the data. The api server shouldn't output anything. No withdrawal is good news!
We want to make one more change before we finish configuring the api server. Initially it listens on interface 0.0.0.0 , but we proxied through NGINX. This means it doesn't make sense. We will configure the server to listen on localhost . This will avoid confusion and problems.
Using a text editor, change line 684 in apiserver.py from
app.listen (8888) to app.listen (8888, "localhost") .
Thanks to swarley7 for sharing the solution in this pull request .
Finally: Bug where uploads don't work as expected if the / uploads folder doesn't exist. This is shared by sampsonc in this pull request .
Let's create a folder and continue!
# create uploads folder
mkdir xsshunter/api/uploads
Installing the GUI Server
This process is very similar to the process on the api server, only simpler.
Go to the gui folder, create a virtual environment, activate it and install the dependencies.
# change folder - you know that already!
cd xsshunter/gui
# find your Python2 executable path
which python2
# create a python2 virtual environment in the env folder
virtualenv -p MY/EXECUTABLE/PATH env
# activate environment
. env/bin/activate
# install requirements
pip install -r requirements.txt
# run the GUI server
./guiserver.py
Using VDS Timeweb as an example
root@372526-twosa:~/xsshunter# cd xsshunter/gui
root@372526-twosa:~/xsshunter/gui# which python2
/usr/bin/python2
(env) root@372526-twosa:~/xsshunter/gui# virtualenv -p /usr/bin/python2 env
(env) root@372526-twosa:~/xsshunter/gui# . env/bin/activate
(env) root@372526-twosa:~/xsshunter/gui# pip install -r requirements.txt
(env) root@372526-twosa:~/xsshunter/gui# ./guiserver.py
Again, the same as when installing the API server:
Make sure you change MY / EXECUTABLE / PATH in the last command to what python2. For me this is: / usr / bin / python2 .
Here, too, the lack of output when running ./guiserver is good news.
Also, just like with the API server, we want to proxy all connections through NGINX, so the server doesn't need to listen on interface 0.0.0.0 .
Using a text editor, change line 70 in guiserver.py from
app.listen (1234) to app.listen (1234, "localhost").
Final touches
The first step is to start both servers. The original blog post suggests using tmux. It's not perfect for production, but we are hackers, so let's do it anyway! If you want a more stable service, I'll leave that to you as an exercise.
Here's how to get it up and running with tmux. If you need help, there's a great cheat sheet here !
# start a session
tmux session -new xsshunter
# change to api directory
cd xsshunter/api
#run api server
./apiserver
# open new pane
[ctrl]+[b] -> [c]
# change to gui directory
cd xsshunter/gui
# run gui server
./guiserver
# detach from session
[ctrl]+[b] -> [d]
# extra: if you want to open the session again
tmux attach-session -t xsshunter
And the last one!
Open your domain and see if the xsshunter page greets you!
It should look the same as the first page on xsshunter.com .
Happened? Congratulations!
Time to pour beer by the glass!
Check the performance
(https://www.372526-twosa.tmweb.ru/signup) .
www.372526-twosa.tmweb.ru/app Payload - . :
html- .
: js , , js_callback .
XSS Hunter:
:
It works! !
www.372526-twosa.tmweb.ru/app Payload - . :
"><script src=https://tw.372526-twosa.tmweb.ru></script>
html- .
: js , , js_callback .
XSS Hunter:
:
It works! !
: www.372526-twosa.tmweb.ru.
If you haven't watched Entourage yet, you can get started now!
Conclusion
I don't like running something as root or as a normal user, so to run it as www-data, I made the following script to make it a little easier.
Replace apiserver.py with guiserver.py so you have one script per server. I will be glad if you use this technique.
Shell script for using the virtual environment and starting the API server:
#!/bin/sh
. env/bin/activate && python apiserver.py
Running the script as www-data for security reasons:
# execute script above as www-data user
sudo -u www-data ./run.sh
Done!
Thanks for attention. Hope it was helpful!