Arbitrary code execution from pip's "—extra-index-url"

Once upon a time I made a python library, and gave it a very common name. Let's say the name was "foo". I also created a package that depended on foo, lets call it "bar". Both packages were in in my own private PyPI server, but something was wrong. When I installed bar the wrong dependency was being installed for foo. The package with the name foo from the public PyPI was being installed, not the one from my private PyPI.

I had inadvertently installed a package that could have run arbitrary code on my computer.

The problem occurs when --extra-index-url is used to point to a private PyPI that has packages with names shadowed on the public PyPI. When then this happens pip is needs to choose which PyPI to take the package from. It simply chooses the one with the higher version number.

This is a problem when: someone is using a private PyPI, with the --extra-index-url, and they are using a package on the private PyPI with a name they have not claimed on the public PyPI.

Going back to our original scenario, if an attacker controlled the name foo on the public PyPI, they could replace it with a malicious payload. The attacker could get control of the public foo name if it wasn't taken, or even if it was taken but unused (see PEP 541).

I think many people who have private python packages are vulnerable to having their packages hijacked like this.

I went looking around the internet. Here is one vulnerable PyPI instance I found.

CERN's vulnerable PyPI

CERN hosts many of it's own python packages here. Many of these packages names were not taken on the public PyPI, so I took them. Note that they also provide instructions to their users that they should use --extra-index-url.

I notified CERN that I had taken the names for their packages on the public PyPI and transferred ownership to them.

They offered to give me a tour if I was ever in Geneva :)

Upstream disclosure

I disclosed this to the security@python.org list. Unfortunately they said there is currently no path to fix this.

They recommended using "version-pinning and hash-pinning for deployments" to avoid this.

They also discussed shadowing the names of your own private packages on the public PyPI. This has problems because it reveals the names of packages you use, and forces you to effectively squat those names.

CVE-2018-20225

I reported this as a CVE. The link is here.

A Sketch of Trusted WiFi - Open, Authenticated, Encrypted

With the rise of Letsencrypt, the costs of TLS certificates has become essentially nothing. This opens up new possibilities for authenticated encryption for things other than https by leveraging the existing Internet Publick Key Infrastructure (PKI) and Domain Name System (DNS). Here I'll explain how we might use Letsencrypt to make WiFi safer.

When a WiFi network is setup for public use, there is trade off made between offering an unencrypted open access network vs an encrypted but password protected network. And neither of these options offers the ability for the client to authenticate that they have connected to the correct access point (AP).

We can leverage the Internet PKI to provide an open, authenticated, encrypted connection to the WiFi AP, just like we leverage PKI to get an open, authenticated, encrypted connection to https://wikipedia.com/

To clarify, we want 3 properties. Openness, meaning the client does not need to authenticate itself (e.g. it should not need to enter a password, or provide a client certificate). Authentication, meaning the AP's identity is verified. Encryption, meaning the connection between the client and AP is encrypted.

Protocol

The following protocol meets these requirements:

Alice, the WiFi provider, owns the domain name "alice.net". She creates a subdomain "wifi.alice.net" and obtains a signed TLS certificate from some certificate authority (CA) in the Internet PKI (Any CA can be used, not just Letsencrypt).

The AP then needs three things to be configured:

  • the AP should have the SSID "wifi.alice.net".
  • the AP should have the signed certificate for "wifi.alice.net", along with the corresponding private key.
  • the AP should use EAP-TLS with no client certificate (called EAP-UNAUTH-TLS?)

Alice turns on the WiFi.

Bob connects to the WiFi network named "wifi.alice.net", this establishes a connection with EAP-TLS. Additionally he checks that the X.509 certificate he received is for the domain "wifi.alice.net", and that it has a valid signature from a trusted CA.
QED

How'd that work?

We get openness by ensuring that the variant of the EAP-TLS protocol does not require a client certificate.

We get encryption with EAP-TLS.

The authentications is a little more subtle. We get authentication by checking that the certificate the AP serves us is the same as the SSID. This passes the work of "Authentication" to the CA who issues the certificate. Implicit here is that Bob, not his WiFi client, chooses "wifi.alice.net" because he knows that Alice owns that domain. Maybe he knows this because he is at Alice's house, or he's at Alice's internet cafe, or Alice.com is a know ISP for public WiFi etc.

Moving Forward

The pieces to implement this mostly exist. Only minor modifications are required to AP's and Clients. The only novel idea is comparing the SSID with the domain of the certificate to get authentication.

To get a proof of concept working, there are a few things to consider:

  • EAP-TLS with no client certificate is not well supported. There is interest and work in changing this. PoC's exist.
  • I don't know if you can simply "install" a certificate originally intended for TLS in place of a certificate intended for WiFi. They are both X.509 certificates.
  • Clients (wpa_supplicant) would need to be modified to compare the SSID with the domain in the certificate.

I'm working on it.

Adding Account Deactivation to Certbot

The recent ACME spec included a way for users to deactivate their accounts. This post describes adding this feature to certbot. This feature touches almost every level of certbot, so it gives an instructive look at Certbot's architecture.

An account in this case means the identity associated some key pair. Accounts control identifiers (domain names).

All the code describing the ACME protocol is in the acme/ package. The messages between the client and server are defined in certbot/acme/acme/messages.py So we can add the deactivation method here. From the ACME spec we see:

6.2.2.  Account deactivation

   A client may deactivate an account by posting a signed update to the
   server with a status field of "deactivated."  Clients may wish to do
   this when the account key is compromised.

   POST /acme/reg/asdf HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "jwk": {...},
       "nonce": "ntuJWWSic4WVNSqeUmshgg",
       "url": "https://example.com/acme/reg/asdf"
     })
     "payload": base64url({
       "status": "deactivated"
     }),
     "signature": "earzVLd3m5M4xJzR...bVTqn7R08AKOVf3Y"
   }

   The server MUST verify that the request is signed by the account key.
   If the server accepts the deactivation request, it should reply with
   a 200 (OK) status code and the current contents of the registration
   object.

   Once an account is deactivated, the server MUST NOT accept further
   requests authorized by that account's key.  It is up to server policy
   how long to retain data related to that account, whether to revoke
   certificates issued by that account, and whether to send email to
   that account's contacts.  ACME does not provide a way to reactivate a
   deactivated account.

Adding protocol messages in messages.py

So we crack open messages.py to add this message. In the module is the UpdateRegistration class which represents messages to the reg endpoint. And deactivating an account is actually just updating the "status" field to "deactivated". So deactivation is just a kind of updating. So all that is needed is to make UpdateRegistration accept a "status" field. We do this by adding an attribute to the class like:

status = jose.Field('status', omitempty=True)

Not so bad right?

Deactivation with the client in client.py

Now we need to use this thing we added. The acme package has a notion of a client, which is a thing that speaks the acme protocol. This is done in acme/client.py. Fortunately we already have code that sends update messages, so we use this to make a new function:

class Client(object):
    ...

    def deactivate(self, regr):
        """Deactivate registration."""
        update = {'status': 'deactivated'}
        body = messages.UpdateRegistration(**dict(update))
        ...
        # code for checking the response
        ...
        return new_regr

Testing the client

We have to mock out what we response from the CA. So we'd expect the current contents of the registration to be returned. It's pretty simple

    def test_deactivate_account(self):
        self.response.headers['Location'] = self.regr.uri
        self.response.json.return_value = self.regr.body.to_json()
        self.assertEqual(self.regr, self.client.deactivate(self.regr))

Adding a deactivate command to certbot

We are done in acme/. Now we move to certbot/ where all the non-protocol specific code lives. We have to add the pieces the user will interact with on the command line so cli.py is the place to start.

cli.py is where all the command line flags are parsed, including --update-registration. Which is similar to deactivation. So we add a thing:

    helpful.add(
        "register", "--deactivate", action="store_true",
        help="Irrevocably deactivate your account. Certificates associated "
             "with your account can still be revoked, but they can not be "
             "renewed.")

Now when certbot register --deactivate is entered, the python function certbot.main.main gets called which eventually calls certbot.main.register. The register function takes a config parameter. And because we used the --deactivate flag, this parameter has config.deactivate == True. So we can add the following code.

def register(config, unused_plugins):
    ...
    if config.deactivate:
        if len(accounts) == 0:
            add_msg("Could not find existing account to deactivate.")
        else:
            yesno = zope.component.getUtility(interfaces.IDisplay).yesno
            prompt = ("Are you SURE you would like to irrevocably deactivate "
                      "your account? You will lose access to the domains "
                      "associated with it.")
            wants_deactivate = yesno(prompt, yes_label='Deactivate',
                                     no_label='Abort', cli_flag='--deactivate',
                                     default=False)
            if wants_deactivate:
                acc, acme = _determine_account(config)
                acme_client = client.Client(config, acc, None, None, acme=acme)
                acme_client.acme.deactivate(acc.regr)
                add_msg("Account deactivated.")
            else:
                add_msg("Deactivation aborted.")
        return

This song and dance needed to get the deactivate method we made earlier isn't obvious. I basically copied part of this from other places in the code.

Next, this thing we added needs to be tested. So in certbot/tests/cli_test.py we add:

    @mock.patch('certbot.main._determine_account')
    @mock.patch('certbot.main.account')
    @mock.patch('certbot.main.client')
    @mock.patch('certbot.main.zope.component.getUtility')
    def test_registration_deactivate(self, mock_utility, mocked_client,
                                     mocked_account, mocked_det):
        mocked_storage = mock.MagicMock()
        mocked_account.AccountFileStorage.return_value = mocked_storage
        mocked_storage.find_all.return_value = ["an account"]
        mocked_det.return_value = (mock.MagicMock(), "foo")
        acme_client = mock.MagicMock()
        mocked_client.Client.return_value = acme_client

        x = self._call_no_clientmock(["register", "--deactivate"])
        self.assertTrue(x[0] is None)
        self.assertTrue(acme_client.acme.deactivate.called)
        m = "Account deactivated."
        self.assertTrue(m in mock_utility().add_message.call_args[0][0])

This isn't very pretty either. certbot/tests/cli_test.py is a big monolith, there is currently an issue for this.

Being Homeless at UCLA

I recently came across this video and article about a homeless PhD student at UCLA. I found it interesting because I was homeless at UCLA too. This post is about my problems with the story, and my experience being homeless at UCLA. You should go watch that video and read the article first.

What is wrong with the story?

While Louis explicitly says he doesn't want people to feel sorry for him, a lot of it is about how sorry his life is. Which is concerning considering how privileged Louis really is compared to most homeless people. They (Louis or the authors) should emphasize this distinction. And the larger harder, more complicated issue is glossed over, why is Louis homeless? There is not criticism or critique of the financial systems that are driving up tuition. No one asks why this is happening. Why is UCLA increasing tuition, in the face of mass student unrest?

It silences the struggles of the majority of homeless people by omitting their stories. It also belittles their struggle by casting Louis' homelessness as a somewhat heroic fight for the American dream of going to college and getting a job. And then it deliberately avoids confronting changes to tuition policy that are driving people to such desperate measures.

Louis isn't like moste homeless people. Louis is educated, able to keep a job, not battling addiction, has no obvious mental health issues, a car, a family, etc. On top of that he must have access to support systems in the school to help him finance housing, like all students do. However he would incur more debt, which isn't something to take lightly.

Why was I homeless?

Louis and I were both in the same situation, be homeless, or incur more debt. We made the same decision. And for both of us it was probably the right thing to do.

I barely graduated high school, I never thought I'd go to college. But after working a full time job, with no benifits, at $8/hr I decided to try to look into it. I went to San Jacinto Community College for two years, taking all of my lower division classes, and had no debt going into the University of Texas at Austin. I graduated from UTexas with above a 3.5, a bachelors of science in math, and a bachelors of science in physics (I was a double major). I did this whith zero financial help from my single mother, or anyone else in my family. I worked really hard and still graduated with 38k in debt.

So I made it to grad school at UCLA. The social narrative for a physics PhD student is that you get paid a meager salary, but it is enough to pay rent and tuition. And you are pursuing you passion so you can put up with being broke. When I showed up at UCLA I wanted to live at the UCHA housing co-op. It was pretty much the only place I could afford to live a $555 a month (this is ridiculously cheap for the area). It was near campus so I didn't need a car. And it included food! And co-ops are cool! But UCHA didn't have space available. So I decided to just sleep in my hammock on campus or in my office until a space opened up there. This didn't happen for a whole quarter (3 months).

Telling people you are homeless

Louis said he doesn't tell people he's homeless. I can relate to that. At first I was just honest about it. This would always bring a torrent of questions, and a lot of concern for my well being, which was hard to deal with.

People would offer me a couch. I always felt obligated to turn it down because my homelessness was self imposed and indefinite. So I imagined the situation would be awkward for both my host and I when I would eventually wear their generosity thin, but have no where to go. I just wanted to avoid that. My only social connections were other first year graduate students and I didn't want to alienate myself by mooching off of them.

Eventually I just stopped telling people about it.

How to be homeless at UCLA

Some things Louis describes about his life which I had some questions about. He says he should parks where he does for the free WiFi, but there is free WiFi at UCLA. Why is he showering on the beach? I used the UCLA gym every day, they even had FREE towel service. Maybe the expensive parking near campus was too expensive.

He said he was preparing all his food in his car. I couldn't cook either but I found it was very cost effective to eat Chipotle every day, and split a bowl across lunch and dinner. At Chipotle you are allowed to ask for as many extra rice and beans as will fit in your bowl for free. When not chipotle out I'd have a protein shake, make pb&j, or eat fruit.

There are a lot of logistics you have to figure out to make it more bearable. For the first month or so I slept in a camping hammock at night on the trail between intramural fields and sunset Blvd. Eventually I bought an air mattress and would sleep in my cubicle after my office mates had left. But if they were working late, I'd just sleep outside. I was hiding this from my office mates, but they caught me a few times. I'm not sure how suspicious they were.

I kept all my possessions in my cubicle. I had arrived in LA from a bicycle tour up through Mexico, so I didn't have a lot of stuff.

When I slept outside I'd have to wake up at sunrise, so campus police would not find me, and so I would not scare people on their way to class. When I slept in my office I'd have to wake up before my office mates came in. So about 7am everyday. Then I'd go to the gym and shower. Then proceed like a mostly normal school day.

I'd do my laundry at a nearby laundromat. Or a friend would let me use theirs. I didn't have a car, so I'd ride my bicycle everywhere.

Since I was spending 95% percent of my time on campus, I figured I would be super productive with school work. But I wasn't. I think this whole situation stressed me out more than I realized. Which affected my grades. Otherwise I led a mostly normal life.

Reach out

If you are homeless at a university, or considering it, reach out to me. I'm happy to tell my little story because it isn't a narrative I see discussed openly. And maybe the LA times story helps lessen the taboo.

At the end of they day, I'm glad I didn't add another $5000 to my debt for my adventure in grad school. I dropped out in my second quarter.

Notes from Berlin - January 2016

I arrived in Berlin in time for New Years Eve. Two things that are not illegal: public alcohol consumption and setting off fireworks. Supplies for these activities can be purchased at any corner store. The city is it a lot like a warzone on New Years Eve.

Lodging

Don't stay it A&O Berlin Mitte Hostel. I did this for one night and it was terrible.

My plan was to stay at an AirB&B for a few nights, and if it seemed okay, negotiate staying longer term in person. This worked out great for me and I found a nice place in Friedrichshain for around €17.5 a night.

Working

I got a membership at Betahaus while I was in Berlin, but I don't recommend it, mostly because it is just so overpriced. I ended up paying €219 for one month of 24/7 access to the space. The cost breakdown was €159 base monthly fee for unlimited access during regular hours + €25 initial sign up fee + €25 for adding 24/7 access. I also had to pay a €50 deposit to get a key to the building, but I got this back. But they didn't even have free coffee.

There are other much cheaper coworking spaces in Berlin, for ~€100 a month you should be able to get the same deal. I should have shopped around more.

I found this nice site for searching for coworking spaces, sharedesk.net. And another site for finding cofee shops to work from, workfrom.co. There are a lot coffee shops in Berlin with wifi where you can work for the cost of coffee. I recommend Saint Oberholtz and I've heard that the FabLab is a good place leech wifi.

Food

It was really cheap and easy to be vegan in Berlin. Most döner places also sell falafel döners, which should be vegan if you get the spicy red sauce. You can't really beat €3.00 falafel döners. There are also tons of awesome exclusively vegan restraunts around the city. Most grocery stores carry imitation meats too. And I heard there is a vegan grocery store, and a vegan shoe store...

There are also many squat/housing co-op/intentional community like places throughout the city that offer (usually vegan) dinners for really cheap. These are indexed at Stress Faktor's Küche für Alle.

Berlin Strength

Berlin Strength is a vegan power/weight lifting gym in friedrichshain. "vegan gym" means all the supplements they sell are vegan. And all the gym equipment is vegan, so the lifting belts, shoes, medicine balls, benches, etc. are leather free. A membership for all of January was €30, it is usually slightly more expensive, but still cheap. It had a really great "no bros allowed" vibe, leftist stickers everywhere, and unisex lockerroom. I love this place and wish there was something like it in Austin.

Stuff

Every Tuesday there is a cryptography stammtisch (a stammtisch is like a German meetup).

There are many tours around the city, I was lucky enough to be show around by a friend who is a tour guide. I got the "street art" and "general Berlin history" tours, there are also cold-war, WW2, and other tours which you can sign up for at most hostels. There are is also a Refugee Voices Solidarity Tour, which is a tour given by refugees of the places that have been central to the current refugee crisis.

Of course, there are clubs. I visited Berhgain, KitKat club and a few other places. If you want to get in to Berhgain, wear lots of black, dress down, and just try to look really cool, but not like you're trying too hard. Also, a warning, they will search you thoroughly upon entry. KitKat's gegen night is supposed to be interesting, but I missed it.

You should also visit the legendary hackerspace c-base. It is actually inside of an excavated alien space craft that crashed in Berlin 5,000 years ago.

Getting Around

On this visit, I tried to be a good German train rider and not skip the fares. There were only a few days where I had invalid tickets, but I was never asked to present my ticket a single time while I was in Germany, and I rode the U/S-bahn multiple times every day. The previous time I was in Germany in 2013 I only bought one U-bahn ticket the whole 20ish days I was there, but I got caught on my last ride to the airport. This time I was buying the 7-day tickets because they seemed like the best deal.

There is no Uber in Berlin, but you can use the Uber app to get taxis. The driver is paid through the app so you don't need to give them money. A 15 minute ride cost me about €15, it is expensive.

Hacker Trip to China 2015 - Hong Kong

Every year Mitch Altman goes to China to visit the Manufacturer he uses for TV-B-Gone. And for the last 5 years he has brought people with him to meet and mingle with the Chinese hacker community, visit factories, and generally just be tourists. I was lucky enough to go this year.

Our rough itinerary started in Hong Kong October 1st, then Shenzen, then Shanghai, and finally Beijing. Spending around 5 days in each city.

There is no way I begin to convey everything, especially because I'm writing this 2 months later. But I have pictures, and reconceived conceptions, and new friends.

I'll start by writing about Hong Kong, then add the other cities later.

Hong Kong

My photos

People in Hong Kong (Hongkongers 香港人) generally do not consider themselves as "Chinese".

The de facto language is Cantonese. Which is different from Mandarin, the language most spoken throughout China. The "Chinese language" is actually a group of languages which are un-intelligible in many cases. Cantonese and Mandarin are in this group and they are mutually un-intelligible.

They also write in Traditional Chinese, while the official script of mainland China is Simplified Chinese.

Hong Kong is a "Special Administrative Region" of China. Which among other things means that HK is not necessarily beholden to Chinese laws. So the internet is not censored, they have their own currency, and their own passports, etc.

This special status is because HK is a former British colony that is currently in a 100 year process of being handed over. China however would like to have more control over HK. And Chinese attempts to exert this control inspired the Umbrella Revolution. Basically China told HK that elected officials would have to be approved by China.

When you get to Hong Kong

  • Immediately buy an Octopus card. This is your ticket to the amazing public transportation system. Hong Kong has the best subway system I've ever used - period. Some subway systems in China come close, but they all have the annoying x-ray your bags every time thing. Hong Kong doesn't have this.

  • Visit Dim Sum Labs.

  • Wander the markets, buy some used electronics you don't need.

  • Take the trolley up to Victoria Peak. Go in the morning when the line is short. Hike up to the radar towers on top of the mountain and enjoy the view. Take the trail down through the city.

  • Eat at a cat cafe.

  • Go to the top of the ICC building. Enter the OZONE bar for $120 HKD, this goes toward a drink ticket which is required for entry. The bar is a bourgeois shit hole, but the view is of the city is amazing. When I went the patio was closed due to a typhoon, but the view was still good.

  • Note that sneezing in public is very rude.

Turning Around

Candace and I woke up at sunrise ready to continue further down the Texas coast to Matagorda bay. The forecast was chance of showers and 2 to 3 foot seas, this sounded optimal.

Motoring through the Freeport jetties we accidentally cut off an enormous tanker under tow. A tug gave us 6 short horn blasts, basically saying "our movement is restricted, what are you doing".

The seas go big pretty fast, the waves were so large I was afraid to go to the bow of the boat (especially with no jacklines) to unfurl the foresail. We kept motoring further out hoping the seas would get better, but they didn't. Even if we could get the foresail up, the sailing in this would slow pounding endeavor. The boat was too small to cut through the 3 foot seas. The Matagorda bay entrance was 70 miles away. Which could easily take 12 + hours. Not wanting to enter an unfamiliar harbor at night, we decided head back into the jetties and take the ICW.

A few miles into the ICW the boat slowed from 6 knots to 2. With seemingly no explanation. No amount of fiddling with it on the water would make it work. This was bad. Not only could we not sail, we could not motor. I started calling places in Freeport asking about docking while we got the engine looked at by a mechanic. Repairs could take several days so squatting did not seem practical. We chose The Freeport municipal marina and it only cost us sixtyish bucks until the end of July. We limped over there. Recovering the ground we covered in the ICW took around 3 hours. Once we were in Freeport harbor I sailed up toward the marina. Navigating through the guillotine storm gate and around the industrial activity under full sail was awesome.

We berthed at the marina and met the local liveaboarders.

We were pretty stumped about what to do next. Some of the friendly folks at the marina gave us the number of an outboard mechanic. We got a ride to Houston, and scheduled an appointment with the mechanic. Two days later he got back to us and told us all it was, was a "spun prop". Basically there is a plastic bushing between the rotating axle and the prop itself. He didn't charge us because this was a pretty simple thing he could diagnose on inspection. We went back to Freeport the next day, removed the prop and had the bushing replaced for a grand total of $44. The next day we returned to the marina.

Candace took the initiative to install the prop. She dropped a vital component, a special washer that fits between the prop and the shaft, into the water. The water was around five feet deep and zero visibility. There was no way the boat would go anywhere without the washer. What followed was 30 minutes of feeling around in the mud, rocks, and sharp oyster shells. When I finally felt the washer, I was so excited I swam up quickly and hit my head on the bottom of the floating dock. After a panicky moment trying to feel which way I had to go to surface I came up and put the washer on the dock. My head and hands were bloody but I couldn't have been happier to find that stupid washer.

We were still unsure about heading out the next day. The forecast was again 2-3 foot seas. We could head down the ICW. Or we could turn around, put the boat up for sale in clear lake and take a bus to Mexico. We decided to sleep on it.

We woke up before sunrise and decided to shove off towards the ocean. Exiting the storm gate we heard warnings on the radio about a hydrochloric acid spill prohibiting exiting the harbor. We saw a coastguard patrol boat circling and we figured we could just try to leave and play dumb if they stopped us. Which they did immediately. We were told the harbor exit would be blocked for an indefinite amount of time. Of course this meant a late start towards Matagorda bay, which means we would be traveling at night.

It was nearing the end of July. I realize I had made several mistakes. I overestimated how our 24' boat would handle in the ocean. I overestimated our speed. Maybe we could wait for more favorable ocean conditions but that would slow us down even more. Considering this, and after looking at prices for bus tickets to México, we decided to head back to Clear Lake and re-sell the boat.

I was pretty disappointed. I was embarrassed. I would not be living out my daydreams about cruising to California on a shoestring. I would go back and see my friends to and hear a lot of "I told you so - blah blah blah". But I tried, and had a blast, and learned so much. I don't regret trying. And I'll try again. I owe a lot to the folks that helped us out, Tommy and Suzy Granger for food, supplies, and encouragement. And the late WD Granger who was an invaluable source of inspiration and advice.

I was procrastinating this post for a long time, then I read about Grimes' attempt to raft down the Mississippi. We both had nautical wonderlust and no cash. We both failed pretty hard after only a few days. Failure happens to everyone.

Day 3 - squatting at the surfside yacht club

July 19th we woke up in the choppy west bay. We hopped back into barge traffic in the ICW and headed to Freeport. The depthsounder seemed a lot more stable, the problem was probably some debris or seaweed stuck to it. It only took a couple of hours to get to Surfside where we slipped into the yacht club.

After trying a few spots we tie off on the end of a dock next to the boat "Blow me". The dock was caving in or something which is probably why the spot was available. There were not to many people around, which made it easy to not be suspicious.

There were more spots in the back next to some derelict boats, but the spot was fenced off from the rest of the yacht club.

We went on shore to get a feel for the place. I felt a lot more suspect here, but we ordered a burger at the little cafe and used the lavatories and got no trouble from the yuppies. We strung up a tarp over the boom for shade and took a nice nap in the shade with a nice breeze.

The fuel dock was out of gasoline so we had to hike to the nearest gas station over the surfside bridge. However we immediately got a ride when we got on the road. People usually know what's up when they see you on the side of the road with a gas can. We ate a $3 dinner at the Valero, 2 hotdogs and a fountain drink.

Back at the dock we discovered the water, electricity hook-ups. We took full advantage of the facilities to prepare for breaking out into the ocean the next day.

Day 2 of a Small Voyage, into the ICW

Galveston

Candace and I woke up to rain coming through the bow hatch before sunrise. The rain was bad enough to keep us from shoving off, so we put our foul weather gear on and went ashore looking for coffee and a place to dry all our clothes (we hung the up to dry the night before, bad idea).

We stayed on shore, until around noon. The weather was better but still gloomy. So we decided to take the Inter Coastal Waterway (ICW) instead of the ocean to our next destination, Freeport. There were only 7ish hours of sunlight remaining, which wasn't enough to get there. But West Galveston bay looked accessible from the ICW and should be free of traffic. So it would be safe to anchor there overnight.

Through the ICW

The ICW is basically a 50ish yard wide ditch dredged to around 16ft deep. Things were going well but I think we were going to slow. At around 6pm Candace was at the helm and I was below deck. The whole boat lurched. We ran aground. The sides of the ICW can get shallow quickly.

We were stuck pretty good. I put the motor in reverse and revved it as hard as I could without the prop surfacing. We didn't move. I tried forcing the prop deeper into the water to keep from surfacing. No luck. We tried rocking the boat side to side while I revved the motor. Nope. And then I tried turning the engine in its mount to it would pull at different angle. Slowy this moved us out of the mud. I guess this is one small advantage an outboard has over an inboard. An inboard motor can only push/pull straight. Although it would not of had the surfacing problems.

Turning the engine was not so obvious to me as it should have been since all the steering on the sail boat is done with keel.

After we were back underway we noticed the depth-sounder was acting very erratically. This was pretty scary since knowing the depth in the murky shallow waters of the ICW is pretty crucial. And soon it was dark so, navigating was even more difficult. Some sections of the ICW are open to the bay on both sides but dangerously shallow. So we had to stay in the channel by spotting the unlit bouys at night. With only a $5 LED flashlight. The bouys are probably about 1/3 of a mile apart. This was nerve-wrecking, but we did fine. Eventually we got to west bay and creeped out into the 5ft deep waters and prepared to set anchor.

Anchoring in West Bay

Things were calm, I set the anchor. For an anchor light we hoisted a lantern to the top of the mast with the Jib halyard. I set my Anchor watch app thing and went to sleep. Throughout the night the seas and wind and eventually rain came. I woke up to the anchor watch app alarm twice. I went on deck and everything seemed alright. The boat was probably just swinging in a different direction as the wind and currents picked up.

I had so many nightmares that night about the anchor rope breaking and us drifting into the path of a barge on the ICW. That didn't happen. But sleep was rough, especially once the seas picked up and we were bouncing up and down.

Shoving off (July 17th, 2014)

At sunrise Candace and I shoved off from League city. In our little C&C 24' boat. After motoring out of Clear Lake we put our sail up in dead air. The forecast was bad weather and it came up pretty quickly. It was a close reach up to the entrance into the Houston ship channel. The wind and rain were increasing so we dropped sails and motored as we entered ship channel. Movement there is pretty restricted, even for a small boat. Near redfish island, leaving the ship channel, the depth can go from 35ish feet to less than 5 feet in 20 yards.

The tankers and barges are huge, going really fast, and get really close to you.

big boat

We motored through the ship channel, making way for larger vessels as they came. I'm not sure what the seas were, maybe 2-3 feet. Some waves were washing over our bow. The pounding of the bow into oncoming waves was so loud, It sounded like the waves would just burst through the hull every time we rode up a wave and crashed into the next one. But the little boat held together fine.

The seas calmed down in the lee of galveston island. There is a lot of traffic here where the Inter Coastal Waterway (ICW), Texas City Channel, Houston Ship Channel, and Galveston Channel all come together. With Ferrys running back and forth from Bolivar peninsula to Galveston Island. Navigating through here went mostly okay except for when we accidentally played chicken with a ferry until he gave us one short blast (meaning he was altering his course to starboard). But he went to port instead.

In the Galveston channel we pulled into the yacht club where I ran the boat aground for the first time. We didn't hit the ground very hard. I was able to free the boat just by putting the engine in reverse, it only took a few seconds to get free.

We tied off at the end of a dock in the yacht club which seemed like it was for live aboards but was mostly empty. The dock was gated, but could be easily climbed around. We went onshore to the yacht club office, they said they had transient slips available. Slip E33 was open and it was $2 per foot per night. For some reason I was under the impression they would let us stay for free. So we said no thanks and went back to the boat.

Now we had to decide what to do. Pay for E33? Go to slip E33 and pretend like we paid for it? Stay where we are for the night? Find a new place? We stayed. I asked the guy in the next slip "is it alright if we tie off here for the night" he said "It looks like as good a place as any". So we squatted where we were. To finish the day we jumped in a closed over-chlorinated apartment pool for a shower.