Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mask sensitive information of POST body in nginx log?

Tags:

nginx

For the convenience of analyzing we save the $request_body field in access log. However, there are some sensitive information inside the post body, such as password or credit card number, exposed in the logs. How can we mask these information?

password=1234asdf  ->  password=****

If I write a nginx module to mask the data, should I write a new log module or should I manipulate the request body before the original log module called?
Or should I use nginx-lua to achieve this goal?
Or is there any other methods?

like image 215
FrankSu Avatar asked Jun 12 '16 08:06

FrankSu


People also ask

How do I mask sensitive data in logs?

To mask personal data in Log Monitoring, a masking rule and a masking rule scope need to be added to the configuration file for each OneAgent. The masking rule defines what data is masked, while the masking rule scope defines to what log files the rule is applied. The masking is done in the OneAgent.

How do I change the log format in nginx?

The syntax for configuring a log format is: log_format format_name 'set_of_variables_to_define_format'; and the syntax for configuring access log is: access_log /path/to/log_file format_name; #simplest form OR access_log /path/to/log_file [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];

How do I read nginx logs?

The NGINX logs all client requests just after the request is processed in the access logs. In access logs, You will see the files are accessed, how NGINX responded to a request, which browser a client is using, client IP addresses, and more in this section.


2 Answers

Use 'echo_read_request_body' command to get the HTTP POST data and then filter the password using 'map' and regex

map $request_body $req_body_start {
    "~(?<nopwd>.*)\&password=[^\&]*.+"  $nopwd;
    default        $request_body;
}

map $request_body $req_body_end {
    "~.*\&password=[^\&]*(?<nopwd1>.+)"  $nopwd1;
    default        '';
}

 map $request_body $req_body_pwd {
    "~.*\&password=[^\&]*.+"  '&password=****';
    default        '';
}

Then define log_format and use it on a server/location level:

log_format  logreqbody  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" "$req_body_start$req_body_pwd$req_body_end"';

Here is more info: https://www.rstcloud.net/blog/30-how-to-hide-sensitive-post-data-in-nginx-log

like image 102
Yury Sergeev Avatar answered Oct 01 '22 13:10

Yury Sergeev


One Expression Map that can mask the password field regardless of its position in the argument list

    map $request_body $request_body_masked {
            "~(?<pretext>.*)(?<pass0>password)=[^&]+(?<last>.*)$"  '$pretext$pass0=*****$last';
            default  '';
    }

Tested for following patterns

  • password=papaya&id=someuser
  • password=papaya&
  • password=papaya
  • &password=papaya
  • id=someuser&password=papaya&remember=1
  • id=someuser&password=papaya

However, need to benchmark the performance cost of running the regex map over the body of each request.

like image 36
acpmasquerade Avatar answered Oct 01 '22 12:10

acpmasquerade