The WPScan role

The first role we are going to create is one that runs WPScan. WPScan is a tool that performs a scan of a WordPress site; it tries to figure out the version of WordPress that is running as well as checking for any plugins that have known vulnerabilities. It can also try and brute force the admin user account; however, we are going to skip that.

As always, we can bootstrap the role using this:

$ ansible-galaxy init roles/wpscan

Once the files are in place, we need to add the following to roles/wpscan/defaults/main.yml:

image: "wpscanteam/wpscan"
log:
remote_folder: /tmp/wpscan/
local_folder: "generated/"
file: "{{ ansible_date_time.date }}-{{ ansible_date_time.hour }}-{{ ansible_date_time.minute }}.txt"

This sets the image we want to download from the Docker Hub; in this case, it is the official WPScan image from the WPScan team. We then set the variables we wish to use for the logs; you may notice that we are defining a folder and file name for the logs.

Next up, we need to add the tasks to roles/wpscan/tasks/main.yml, the first of which uses the docker_image module to pull a copy of the wpscanteam/wpscan image:

- name: pull the image
docker_image:
name: "{{ image }}"

Next up, we need to create the folder where the logs will be written to our Vagrant box:

- name: create the folder which we will mount inside the container
file:
path: "{{ log.remote_folder }}"
state: "directory"
mode: "0777"

The reason we are doing this is that we will be mounting this folder inside of the container we are going to be launching in the next task. As the logs are the only bits of data we want to keep from each scan, we will write them to the mounted folder, meaning that the logs will be available for us to copy to our Ansible controller once the container has exited and removed.

Before we look at the next task, let's take a quick look at the command we would need to run to launch the scan if we were using Docker directly on the command line:

$ docker container run -it --rm --name wpscan -v /tmp/wpscan/:/tmp/wpscan/ wpscanteam/wpscan 
-u http://10.20.30.41.nip.io/ --update --enumerate --log /tmp/wpscan/10.20.30.41.nip.io-2018-05-19-12-16.txt

The first line of the command is where all of the Docker logic happens; what we are asking Docker to do is to launch (run) a container called wpscan (--name) in the foreground (-it), mounting /tmp/wpscan/ from the host to /tmp/wpscan/ inside the container (-vusing the specified image (wpscanteam/wpscan). Once the process exits, we remove the container (--rm).

Everything on the second line is passed to the container's default entry point, which in the case of the wpscanteam/wpscan image is  /wpscan/wpscan.rb, meaning that the command we are using to run the scan within the container is actually this:

$ /wpscan/wpscan.rb -u http://10.20.30.41.nip.io/ --update --enumerate --log /tmp/wpscan/10.20.30.41.nip.io-2018-05-19-12-16.txt

Now we have an idea of the command we would run using Docker, we can look at how that would look in our task:

- name: run the scan
docker_container:
detach: false
auto_remove: true
name: "wpscan"
volumes: "{{ log.remote_folder }}:{{ log.remote_folder }}"
image: "{{ image }}"
command: "--url http://{{ hostvars[item]['ansible_host'] }} --update --enumerate --log {{ log.remote_folder }}{{ hostvars[item]['ansible_host'] }}-{{ log.file }}"
register: docker_scan
failed_when: docker_scan.rc == 0 or docker_scan.rc >= 2
with_items: "{{ groups['wordpress'] }}"

The options in the task are in the same order as they were written in the Docker command:

  • detach: false is similar to passing -it in that it will run the container in the foreground; by default the docker_container module runs containers in the background. This introduces a few challenges, which we will discuss shortly.
  • auto_remove: true is the same as --rm.
  • name: "wpscan" is exactly the same as running --name wpscan.
  • volumes:"{{ log.remote_folder }}:{{ log.remote_folder }}" is the same as what we would pass using the -v flag in Docker.
  • image: "{{ image }}" is the equivalent of just passing the image name, for example, wpscanteam/wpscan.
  • Finally, command contains everything we want to pass to the entry-point; as you can see we have passed a few dynamic variables here.

As mentioned, the docker_container module by default runs the containers in the background; typically that would be great in most cases; however, as we are just running the container as a one-off job to perform our scan, then we need to run it in the foreground. 

Doing this will actually cause an error as we are instructing Ansible to remain attached to a container, which then terminates and is removed once the scan process completes. To get around this, we are registering the results of the task and, rather than using ignore_errors, we are telling the task to fail when ( failed_when) the return code (rc) is equal to 0 or equal or more than 2, as our task should always have a return code of 1.

So why not just let the container run in the background? As the next task copies the log file from the Vagrant box to the Ansible Controller, if we were to let the container run in the background, Ansible would immediately move on to the next task and copy a partly written file.

Attaching to the container and waiting for it to exit means that we are waiting for the scan to complete before progressing to the next task, which looks like this:

- name: download the html report
fetch:
src: "{{ log.remote_folder }}{{ hostvars[item]['ansible_host'] }}-{{ log.file }}"
dest: "{{ log.local_folder }}{{ hostvars[item]['ansible_host'] }}-{{ log.file }}"
flat: yes
with_items: "{{ groups['wordpress'] }}"

Now we have our tasks written, we can try running our role.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.244.153