7

I need to exclude some sensitive details in my apache log, but I want to keep the log and the uri's in it. Is it possible to achieve following in my access log:

127.0.0.1 - - [27/Feb/2012:13:18:12 +0100] "GET /api.php?param=secret HTTP/1.1" 200 7600 "http://localhost/api.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"

I want to replace "secret" with "[FILTERED]" like this:

127.0.0.1 - - [27/Feb/2012:13:18:12 +0100] "GET /api.php?param=[FILTERED] HTTP/1.1" 200 7600 "http://localhost/api.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"

I know I probably should have used POST to send this variable, but the damage is already done. I've looked at http://httpd.apache.org/docs/2.4/logs.html and LogFormat, but could not find any possibilities to use regular expression or similar. Any suggestions?

[edit]

Do NOT send sensitive variables as GET parameters if you have the possibility to choose.

kvaale
  • 604
  • 7
  • 15

2 Answers2

13

I've found one way to solve the problem. If I pipe the log output to sed, I can perform a regex replace on the output before I append it to the log file.

Example 1

CustomLog "|/bin/sed -E s/'param=[^& \t\n]*'/'param=\[FILTERED\]'/g >> /your/path/access.log" combined

Example 2

It's also possible to exclude several parameters:

exclude.sh

#!/bin/bash
while read x ; do
    result=$x
    for ARG in "$@"
    do
        cleanArg=`echo $ARG | sed -E 's|([^0-9a-zA-Z_])|\\\\\1|g'`
        result=`echo $result | sed -E s/$cleanArg'=[^& \t\n]*'/$cleanArg'=\[FILTERED\]'/g`
    done
    echo $result
done

Move the script above to the folder /opt/scripts/ or somewhere else, give the script execute rights (chmod +x exclude.sh) and modify your apache config like this:

CustomLog "|/opt/scripts/exclude.sh param param1 param2 >> /your/path/access.log" combined

Documentation

http://httpd.apache.org/docs/2.4/logs.html#piped

http://www.gnu.org/software/sed/manual/sed.html

BorisHajduk
  • 326
  • 2
  • 8
kvaale
  • 604
  • 7
  • 15
  • When I try the same thing, I get an error saying "/bin/sed: can't read >>: No such file or directory". Did you see this too? – Debajit Mar 11 '15 at 20:54
  • did you change the path to a existing file? '/your/path/access.log' – kvaale Mar 16 '15 at 12:36
  • Unfortunately this doesn't work for me. It just doesn't log anything when using this script... – Tarator Sep 23 '17 at 12:08
  • Same issue here, fixed by using "|$/bin/sed .." instead of "|/bin/sed". As the documentation states, this executes the command inside a shell. Note that this was the default behavior of "|" in the past, but that was changed at some point. Nevertheless, this doesn't solve all the problems of the line for me, as the regular expressions tends to not be correctly passed to sed... I'm using apache 2.4.39. – nimai Sep 09 '19 at 10:19
2

If you want to exclude several parameters, but don't want to use a script, you can use groups like that :

CustomLog "|$/bin/sed -E s/'(email|password)=[^& \t\n]*'/'\\\\\1=\[FILTERED\]'/g >> /var/log/apache2/${APACHE_LOG_FILENAME}.access.log" combined
Fouss
  • 21
  • 1