Thursday, June 25, 2020

Detecting HTTP Basic Authentication Brute Force Attacks via packets with TShark

In this post, we are looking at what the packets look like when unencrypted HTTP basic authentication is targeted.

First up, let's see what types of packets are in the PCAP

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -q -z io,phs
===================================================================
Protocol Hierarchy Statistics
Filter: 

sll                                      frames:3162 bytes:1168718
  ip                                     frames:3162 bytes:1168718
    tcp                                  frames:3162 bytes:1168718
      vssmonitoring                      frames:870 bytes:53940
      http                               frames:570 bytes:207928
        data-text-lines                  frames:285 bytes:121331
          tcp.segments                   frames:285 bytes:121331
===================================================================

From above, we see about 570 frames are HTTP.

First let's identify the HTTP version:

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.request.version  -E header=y | sort | uniq --count | sort --numeric --reverse
   2877 
    285 HTTP/1.1
      1 http.request.version

Now that we know the version is HTTP/1.1, let's see the types of HTTP methods being used in this PCAP. The idea is since, we know we are analyzing HTTP, then there is more than likely going to be a method of GET, POST, etc.

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.request.method | sort | uniq --count | sort --numeric --reverse
   2877 
    285 POST

Now that we know above the method is PUT, let's now see the host and URI which was accessed.

To see the host being accessed and the source, we execute:

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e ip.src -e http.host -E header=y | sort | uniq --count | sort --numeric --reverse
   1452 192.168.0.4
   1425 10.0.2.15
    285 10.0.2.15       lab.securitynik.local
      1 ip.src              http.host

Let's learn a little bit more about the source. Maybe we look at the User-Agent:

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e ip.src -e http.user_agent | sort | uniq --count | sort --numeric --reverse
   1452 192.168.0.4
   1425 10.0.2.15
    285 10.0.2.15       Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)
    1   ip.src          http.user_agent

Looks like the device at 10.0.2.15 is using NMAP to target our host at lab.securitynik.local.

So at this point, we know the HTTP version, the source IP, the destination being targeted and the user agent of the device attacking us. Let's now identify the URI which is being targeted.

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.request.uri  -E header=y | sort | uniq --count | sort --numeric --reverse
   2877 
    285 /lab/webapp/basicauth
      1 http.request.uri

We now know that "POST" method was used against the URI above. Let's take a glance at the server responses. While the request being made is good to know, we are more interested in the server response.

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.response.code | sort | uniq --count | sort --numeric --reverse
   2877 
    284 401
      1 200

Above we see 284, "401" errors status codes and 1 "200" status code. Seems strange. 

Researching error status code 401, RFC 2616 identifies this status code as "Unauthorized". The RFC further states this "request requires user authentication". It also states that "the response MUST include a WWW-Authenticate header field"

Let's verify this WWW-Authenticates header exist. 

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.www_authenticate | sort | uniq --count | sort --numeric --reverse
   2878 
    284 Basic realm="SecurityNik Realm!"

Looks like it does. Would it be safe now to conclude that the user failed authentication 284 times and then ultimately was successful with that 1 "200" status code.

Taking a look at the Authorization requests being made:

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.authorization | sort | uniq --count | sort --numeric --reverse | more
   2878 
      1 Basic YWRtaW46YXNzYXM=
      1 Basic YWRtaW46YXNzYWQ=
      1 Basic YWRtaW46YXNzYWE=
      1 Basic YWRtaW46YXNhZHM=
      1 Basic YWRtaW46YXNhZGQ=
      1 Basic YWRtaW46YXNhZGE=
      1 Basic YWRtaW46YXNhYXM=
      1 Basic YWRtaW46YXNhYWQ=
      1 Basic YWRtaW46YXNhYWE=
        ....

Looks like lots of Basic Authorization. Since the above looks like base 64 encoded content, let's continue to use TShark to find the actual credentials being used.

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -T fields -e http.authbasic  | sort | uniq --count | sort --numeric --reverse | more
   2878 
      1 nick:sssss
      1 nick:ssssd
      1 nick:ssssa
      1 nick:sssds
      1 nick:sssdd
      1 nick:sssda
      1 nick:sssas
      1 nick:sssad
      1 nick:sssaa
        ....


Looks like a password based attack with the username being "nick" and the password changing as show above. 

Let's now take a look at the one entry which has status code "200" to see what we get. Because there are a number of packets in this PCAP and the fact that the packet with "200 OK" implies success, let's extract the source IP, source port, destination IP, destination port and the stream number. The stream number we will later use.

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -Y "(http.response.code == 200)" -T fields -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e tcp.stream -E header=y
ip.src      tcp.srcport     ip.dst     tcp.dstport     tcp.stream
192.168.0.4  80            10.0.2.15       35028         60

With above, we can now follow the TCP stream. This allows us to see the full session. Most importantly, it allows us to see the full client request.

===================================================================
kali@securitynik:~$ tshark -r nmap-http-brute.pcap -Y "(http.response.code == 200)" -T fields -e ip.src -e tcp.srcport -z follow,tcp,ascii,192.168.0.4:80,10.0.2.15:35028 | more
192.168.0.4  80

===================================================================
Follow: tcp,ascii
Filter: ((ip.src eq 192.168.0.4 and tcp.srcport eq 80) and (ip.dst eq 10.0.2.15 
and tcp.dstport eq 35028)) or ((ip.src eq 10.0.2.15 and tcp.srcport eq 35028) and (
ip.dst eq 192.168.0.4 and tcp.dstport eq 80))
Node 0: 10.0.2.15:35028
Node 1: 192.168.0.4:80
248
POST /lab/webapp/basicauth HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/n
se.html)
Host: lab.securitynik.local
Content-Length: 0
Authorization: Basic YWRtaW46YWFkZGQ=
Connection: close


        2840
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
X-Cloud-Trace-Context: 96b68704d4489f3c80ee15e704876ce5
Date: Sun, 31 May 2020 01:24:00 GMT
Server: Google Frontend
Accept-Ranges: none
Content-Length: 3827
Via: HTTP/1.1 forward.http.proxy:3128
Connection: close

..................


Awesome!  At this point, we see "Authorization: Basic YWRtaW46YWFkZGQ=". We can now use TShark to find this packet. Alternatively, we can easily plug this value into an online base64 decoder to find the result.


Let's take a bit of Python for this.

kali@securitynik:~$ python -c "import base64;print(base64.decodestring('YWRtaW46YWFkZGQ='))"
admin:aaddd

Let's now wrap this up by looking at the time this activity started.


kali@securitynik:~$ tshark -r nmap-http-brute.pcap -Y '((http) && (ip.src  ==  10.0.2.15) && (http.request.method == POST) && (http.request.uri == http.request.uri == "/lab/webapp/basicauth"))' -t ad | more
   28 2020-05-30 21:23:57.541751    10.0.2.15 → 192.168.0.4 HTTP 265 POST /lab/w
ebapp/basicauth HTTP/1.1 
   50 2020-05-30 21:23:57.715894    10.0.2.15 → 192.168.0.4 HTTP 300 POST /lab/w
ebapp/basicauth HTTP/1.1 
   52 2020-05-30 21:23:57.716791    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
   54 2020-05-30 21:23:57.717297    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
   56 2020-05-30 21:23:57.717872    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
   58 2020-05-30 21:23:57.719344    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
....
 3097 2020-05-30 21:24:02.422018    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
 3098 2020-05-30 21:24:02.422234    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
 3099 2020-05-30 21:24:02.422609    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
 3100 2020-05-30 21:24:02.422823    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
 3101 2020-05-30 21:24:02.423343    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 
 3102 2020-05-30 21:24:02.423554    10.0.2.15 → 192.168.0.4 HTTP 304 POST /lab/w
ebapp/basicauth HTTP/1.1 

From above we can conclude this activity started on May 30, 2020 at 21:23:57 local time.

Looking at the time the time the login was successful from the server perspective, we see:

kali@securitynik:~$ tshark -r nmap-http-brute.pcap -Y '((http) && (ip.dst == 10.0.2.15) && (http.response.code == 200))' -t ad
  741 2020-05-30 21:23:58.779688 192.168.0.4 → 10.0.2.15    HTTP 1347 HTTP/1.1 200 OK  (text/html)

At this point we can say the successful login occurred within a second of of the initial attempt.

Ok At this point I believe we are good to go with detecting the issue. 


References:

2 comments:

  1. Can you please share a link to the PCAP?

    ReplyDelete