I spent the last week and a few days at my family's summer place on the island of Gotland. To get there and back, we usually take the 3-4 hour ferry between Nynäshamn and Visby. On the ferry there is a paid wifi. For fun, I attempted to hack past it. I succeeded. Here is how I did it.
First connect to the wifi network. For the Gotland ferry, it was the "Internet@Sea" network. If you try to connect to any website, it will redirect you to the proxy's login page. If you'd paid for access, this is where you'd enter your username and password.
Then start up wireshark. Make sure you have your network card in promiscous mode so that you can see other clients' traffic. Filtering on http helps, because that's what most "normal" users will be using to access the web. Once you see that a client manages to communicate with an external server copy its MAC and internal ip address. This way you know that the client has likely paid for the wifi access.
Now all we have to do is spoof being that client. We do that by changing the internal ip address and mac address. Ifconfig allows us to do this. My guess is that the proxy guarding the wifi authorizes paid clients this way.
ifconfig wlan0 down ifconfig wlan0 10.21.81.167 ifconfig wlan0 hw ether 3c:a9:f4:<not sure I should include the whole hw address of the victim here...>
Then reconnect to the wifi. After this, I was able to use the internet and access external webpages.
I'm not sure how this affected the original paying client, so I made sure to disconnect once I was done.
I used my network manager to reconnect, and honestly it was a bit of a fluke that it worked when it did. I didn't know how to set the gateway by way of terminal-fu, but I'm guessing the following commands would work too.
route add wlan0 gw 10.21.81.1 ifconfig wlan0 up
Given the wireshark snooping I could just as easily snatch a login and password. The login page was redirected to in http by default, although they had a https page available too. Trying to find the login/password combinations is what I looked for first.
Another idea might be to use ARP spoofing, but I noticed that pretty much all TCP traffic seemed to go to the proxy when not connected.
Finally, I noticed that DNS requests still worked while unauthenticated. I could use _dig_ to query for hosts and get back external ip addresses. This suggests to me that UDP traffic, at least on port 53 (domain) is open. I think you could set up a VPN and tunnel the traffic via it. This was actually my original plan of attack, but I never had the time to set up the VPN.
I'm not sure how you would go about mitigating this. I guess one way would be to put the authentication before actually connecting to the network, but that would require more sophisticated protocols (WAP-business? Client certificates?). I'm not well read into business wifi protocols, so I can't really say.
The biggest problem of implementing something more secure is usability. Having a web portal makes it very easy for the average user to authorize and connect.
Lesson learned: public wifi is terribad security.