Modifying a packet capture with Scapy

My motivation was to start from a known good packet capture, for example, a DNS request and reply, and modify that request to create something interesting: an example to examine in Wireshark, or positive and negative test cases for an IDS software (Snort, Suricata).

I haven’t done much with Scapy before, but it seemed like the right tool for the task. My planned steps were as follows:

  1. Take pcap (packet capture)
  2. Import pcap via scapy
  3. Modify pcap
  4. Export pcap
  5. View pcap in Wireshark

Continue reading Modifying a packet capture with Scapy

Notifying a REST API from Icinga2

I wanted to send Icinga2 notifications to Slack. Some hosts and services don’t rise to the level of a PagerDuty notification, but e-mail just doesn’t cut it. A message in a Slack channel seemed an appropriate in-between.

This process is relatively straightforward, although I ran into some issues with SELinux that I will cover in this post.
Continue reading Notifying a REST API from Icinga2

Running WordPress on Docker

Similar to the previous post, Running Joomla on Docker, I was interested in spinning up a temporary WordPress installation so that I could target it with various scanning and reconnaissance tools. There is an official WordPress Docker image at https://hub.docker.com/_/wordpress/.

The steps were more-or-less the same. Note that if you followed the steps in the previous post, you will likely want to stop and remove the existing MySQL container before attempting to start a new one with the same name:

docker stop some-mysql
docker rm some-mysql

Start the MySQL Docker container:

docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=passW0rd -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=wpP455 -d mysql:5

Start the WordPress Docker container:

docker run --name some-wordpress --link some-mysql:mysql -e WORDPRESS_DB_HOST=172.17.0.2 -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wpP455 -e WORDPRESS_DB_NAME=wordpress -p 8080:80 -d wordpress

I was then able to visit http://localhost:8080 and complete the web-based setup tasks.

Note that the MySQL container, as launched, does not have any shared volumes. Everything stored there is ephemeral and will be lost if the container is removed. To my surprise, however, the content survived stopping and restarting the container. The volumes for each container are located in the following directory:

/var/lib/docker/volumes/

Using docker inspect some-wordpress I could see that there was a mounted volume at:

/var/lib/docker/volumes/be3d54591da609e911a1ec3f0615a564990b37da184a67fab0ac0e75cc711c7f/_data

Indeed, the usual WordPress files, such as wp-config.php, were located there.

I did the same for the MySQL container and found the .frm and .ibd files for each of the tables in the WordPress database.

These files persist when the container is stopped, and persist even when the container is removed! In fact, when I removed all containers, I discovered there were still 22 volumes in /var/lib/docker/volumes from previous container projects and experiments.

The command to view these volumes is:

docker volume ls

To remove unused volumes, use:

docker volume prune

Container volumes are not as ephemeral as I originally thought!

Running Joomla on Docker

I was looking for a well-known CMS (Content Management System) that I could easily run in a Docker container as a target for information security reconnaissance tools, such as WhatWeb.

I found an official Docker image for Joomla, a CMS that I had used previously some years ago: https://hub.docker.com/_/joomla
Continue reading Running Joomla on Docker

Python Flask, escaping HTML strings, and the Markup class

As in the previous post, I had created a simple web app using Python Flask to use as a teaching tool. The purpose was to demonstrate SQL injection and XSS (cross-site scripting) vulnerabilities and how to remediate them.

In this case, the remediation step for XSS (escaping output) tripped me up. I tried this:

return '<p>You searched for: ' + escape(user_input) + '</p>'

I expected it to escape only the user_input variable, but instead it escaped all the HTML, returning this:

&lt;p&gt;You searched for: &lt;script&gt;alert(1)&lt;/script&gt;&lt;/p&gt;

Continue reading Python Flask, escaping HTML strings, and the Markup class

Python, tuples, sequences, and parameterized SQL queries

I recently developed a teaching tool using the Python Flask framework to demonstrate SQL injection and XSS (cross-site scripting) vulnerabilities and how to remediate them.

The remediation step for SQL injection tripped me up though when I received the following error message:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 4 supplied.

Continue reading Python, tuples, sequences, and parameterized SQL queries

Blocking WordPress scanners with fail2ban

My web logs are filled with requests for /wp-login.php and /xmlrpc.php, even on sites that aren’t running WordPress. Every one of these attempts is from a scanner trying to find, and possibly exploit, WordPress sites.

Why not put those scanners in a fail2ban jail and block them from further communication with your web server?
Continue reading Blocking WordPress scanners with fail2ban

Linux policy based routing

Problem: I have a host that has 2 active network interfaces. One is used as a management port (eth0), one is used as an FTP dropbox (eth1).

Both can route to the Internet, but all connections other than FTP on eth1 are blocked via iptables. The default route uses the interface for the FTP dropbox, but I have a static route configured for the subnet that includes my management and monitoring hosts so that I can SSH to the host and check on host availability, disk space, mail queue, etc.

However, the static route means that I cannot monitor the FTP dropbox, since FTP connection attempts coming in on one interface and IP address are then routed out via the management interface and IP address.

Solution: Use policy-based routing to direct the system to consult a different routing table for connections coming in on the FTP interface.

It sounds easy enough.
Continue reading Linux policy based routing

cp, mv, ownership and attributes

I had always been under the impressions that when moving a file from one Linux filesystem to another (i.e. a new inode is created), that mv is essentially a cp command followed by an rm command.

That’s not quite correct. It is essentially a cp --archive command followed by an rm command.
Continue reading cp, mv, ownership and attributes

Using Docker to get root access

In my previous post I mentioned that I am learning about Podman, a tool for running containers that does not require a daemon process (like the Docker daemon) or root privileges.

In this post I would like to demonstrate why running containers with root privileges could be dangerous.
Continue reading Using Docker to get root access