Cloudflare TV

Hacker Time

Presented by Evan Johnson
Originally aired on 

Join Evan Johnson as he speaks with security professionals about recent security news!


Transcript (Beta)

Oh my gosh, I have been muted for minutes, you all. That is unbelievable. Welcome to Hacker Time.

I cannot believe I've been muted. And, and, well, I'll just pick up where I left off.

I've been talking for minutes about RSH Honeypot, the amazing things we're going to be doing today on the show.

Thank you for bearing with me here.

And, and, yeah, we're just finishing up this project that we've been working on for weeks.

And, and we're going to finish this up and move on to a next new project in the next week.

But, but I can't believe I was just muted for a few minutes. The show goes on, though.

And we're going to write some go code here. Thanks to the many people who reached out to me and told me I was muted.

I think there was multiple, through text, through, through our, our hosts who help make Cloudflare TV happen.

So things I was saying, let's start there. The things we need to do to actually finish up this project is we need to, we need to make sure that we get notifications when somebody SSHs.

When somebody SSHs to our Honeypot, we actually need a text message to our phone, just like it was working for HTTP.

We want to containerize this as well.

And then there's probably going to be some cleanup and some things to do for cleanup.

It's the, this SSH code that we copy pasted, it probably has more functionality than we need.

We can probably get rid of quite a lot of it.

And, and so a lot of the, the echoing here, we don't really need, we can probably just be really bare bones and, and just terminate the connection.

But one important thing about notifying when an SSH connection comes in, is we don't just want to notify for successful connections, we want to notify for any type of SSH connection that comes in, because it's a Honeypot.

We want to know, I don't think that anybody is going to really guess this password that was Tiger, I think in here.

Where is it?

It's up here. We have a password up here that's Tiger, and nobody's going to try to guess that, but it doesn't matter.

The point of the Honeypot is anybody who connects needs to be, we need to send a notification to, on any connection, not just successful ones.

So that's a very important thing to consider when we build this notification function.

So let's do that. Let us go to our HTTP Honeypot here.

And how did we notify? We just did Twilio notify access from whatever.

So we probably want to make this HTTP. Oh, I have the Vim bindings now in VS Code.

HTTP connection from here, and then we can just copy paste this whole line and move it to SSH.

So there's quite a few places we will want to have this notification.

First, I don't think we actually care about any of this. So let us, so this password callback function gets called in the password flow for SSH.

I don't think we want a notification in there.

I think maybe we do on a failed password, and we want a different notification on a successful password attempt.

Let's try it here. I want us to not have a situation where we're getting notified twice for one connection, which could happen if I put the notify function up here and then further down after this function gets called.

So we should have SSH connection from wherever.

I think this will just work here nicely. And then anything else?

Oh, remote adder does not exist anymore. So we need a, this will probably come from the SSH con metadata and local adder remote adder.

Cool. That seemed to work.

Where's remote adder a function? Remote adder is a function that returns a net adder.

So net adder will have a string attached to it. This should work.

Let's try this, but I'm not sure why we're getting this error.

Since we're just hacking this together, I'm going to remove this error, remove all this, and see what's going on here.

This work?

What's going on here?

Okay. Let's pull up the SSH con remote con docs here. SSH golang remote adder.

This will get us pretty close. There's something that this is angry about, and I'm not sure what.

So we want a con metadata actually.

Type con metadata contains a remote adder function.

Okay. I called that. It's not a string, but it shouldn't get mad at me for that.

What are you trying to tell me?

It returns an SSH permissions and a nil.

This all looks right.

Too few arguments and call to remote adder. That doesn't sound right at all.

What's going on here?

So let's traverse this starting from the SSH dot permissions.

Let's start from the beginning.

So we have a permissions when the password callback function gets called.

No, we don't have a permissions. We have a con metadata. We have a type C. Ah, that's the issue.

Okay. I was using the package name SSH instead of the variable name, which is C, which I don't need this con metadata.

I guess it's just early in the morning that I was tricked by that.

It should just be C dot remote adder and it should work nicely.

Okay. Now let's give it a run. We should be able to get a text message on a failed SSH connection using password off.

So let's make sure that our assumption is true here.

Go run CMD SSH. And then when we SSH local host, ASDF at local host port 22, I should be able to get a text message here when I press enter.

I did. I got a text message SSH connection from port 6,000, 63 ,039.

So it worked. Okay. And now that was on a failed login.

I think we also need a, so I'm kind of curious where else we're going to need to put this notify.

I think we could also do it in the public key callback and we might be able to do it.

We might be able to put the notify here and, and above this authorized key section.

And that might be the two, only two places it's needed.

Let's try it. SSH password off connection from wherever.

And let's do SSH E off connection. Okay. This I believe will also work.

Let's run our program and we will first try to make the one that we just ran work, just regular password based off.

And I've gotten a text that says key off, which is, I guess true because even though I went interesting, interesting.

So I think I have an SSH agent running, which will automatically present a key, which is the wrong key, which will trigger this notify.

And then it will try this password notification thing, which as soon as I type in a password and it's wrong, I got another, I got another text message that says password SSH password off connection.

So I got two texts for one SSH connection, but that might be okay.

Technically we did try both key and, and password based off here.

So maybe that's okay. And the one thing I want to remove here, I want to remove actually successfully logging in.

I don't think that's really necessary. So we can just, I wonder if we can close it.

The channel, as soon as it opens new terminal. Yeah, we don't need this.

I'll just do channel close.


Well, I have a channel up here.

I'm just going to call channel.close and remove a lot of this code and might work.

A lot of stuff going on here that because we copied and pasted, I'm not sure if it's working properly.

Let us add a bunch of comments and this might work.

I think let's give it a try. Okay.

So now request declared and not used on line 115. So we don't actually need that anymore.

This is somewhat major surgery here.

Okay. So let's try ssh -asdf localhost 2022.

I should get a text, multiple texts. I just got two texts. I guess that means I have two keys in my SSH agent.

Okay. I got another text for password-based and let's try to actually log in successfully.

Let's see what happens if the whole thing crashes or not.

Password was, it was test user and then password is tiger.

So test user password is tiger. Connection closed.

Okay. And the whole, the whole server is still running. I think that's actually an improvement then over what this was previously doing.


Okay, cool. So let's put it on verbose mode and see the server close the connection.


And then you'll see, I'm getting so many text messages from myself right now. This is more than I ever get from anybody.

Next authentication method, password authentication succeeded.

So we had the right password and it says entering interactive session, sending environment.

I just think we don't need any of this.

I think I'm just going to change the tiger function that is taking this to always return an error here.

Let's just return nil and an error.

We don't need, this is way too much functionality. So password rejected.

Then config, where does config get used?

We start to listen on 2022. And this seems reasonable.

I don't think anybody can ever log in now. And so it doesn't matter if we use the password tiger.

Let's try one more time. Tiger.

All right. Authentications that can continue. Permission denied. Okay, great. All right.

Well, I think that works. I think we have made the notification system work for this.

The last thing to do, put this in a container. Let's try to do that quickly here.

I'll just use from Debian, Ubuntu, not sure.

We want to use copy.

CMD, honeypot, honeypotd.

So the whole value here of putting this in a container is it's a little bit easier to deploy, even if this is handmade, artisanally crafted Docker container.

We can just move the container around and easily deploy it.

I actually think that it's not such a big win when you have a binary that's completely self-contained like we have now, but it's kind of nice to be able to package up some of the keys and stuff like that.

Honeypotd, then entry point.

Oh, here we go. Here's a challenge. So we run this honeypot thing.

When we run it, honeypotd. When we run it, we pass an argument.

So either SSH or HTTP here, and we need to pass that into the entry point.

So let's see if there's a Golang Docker pass argument to entry point.

Let's see how to do this. I'm not exactly sure off the top of my head, because it's been a while since I've done this.

So it appears they recommend using an environment variable.

Let's try one more time.

Oh, run the image with arguments ABC or XYZ or something else.

They just want to echo the first thing piped in.

This is a little bit of an issue with how we structured our program.

We built the program in a way that it's all self -contained.

And then I wonder if we could instead pass it by run a run from n.

So dictate which honeypot to run based on an environment variable.

We could probably quickly rig that up. And to do that, this is going to be hacky.

We've got eight minutes, but we can do this. So n command, this is going to be super hacky, but we're going to make this run.

We're going to make our honeypot run based on an environment variable that's passed in.

So I'm going to have a switch statement. I'm going to read an environment variable.

It's either going to say SSH or HTTP. It's going to call the correct function.

And this is the correct run here. And then it's going to fail if it's not one of those two arguments.

So n command run a honeypot by environment variable.

Oh, okay.

Here we go. We need to decide on the port.

Or do we?

Or do we? We don't. We don't. We don't. Okay. So instead, what we need to do is we need to do this.

OS dot lookup n. We will look up the environment variable pot.

And OS lookup n returns the environment variable and then whether or not it's set.

If okay, then we will do a switch statement here and we will call switch on it.

I don't want to call this n, but I'll just call this e. Great variable name. And we will do, honestly, I can't remember the syntax for a switch statement and go.

I'm going to Google it.

I rarely use switch statements. And so it's just uncommon for me.

Okay. So there's braces. There's braces around this switch e and then it will be case HTTP.

And we will call in that case HTTP CMD dot run.

And pass in CMD and args, I believe.

There's a common here. Otherwise case SSH. We will call SSH CMD.

Default. We will, nope, no default case. I think go is smart enough to not need a break.

And I will, these will hang.

So when you call run, it hangs for forever because it opens a listener.

And so I'm going to put a fatal here. So if we get to the end, which means either these didn't run or they returned for some reason, the honeypot will close.

I guess we don't need a fatal.

No, we could have a fatal and say run honeypot with and set to HTTP or SSH.

Okay. Let's try this. I actually think this is going to work, but we will need an H, we will need no, we don't need this.

What we need to do is add this command to the root command, root CMD.

So down here, we need to add and CMD. This should work. I think this is actually going to work on the first try because we are that good.


Does it compile? It does. Indeed. We've got our end here. Let's run it with end.

And then let's set pot to SSH.

This is actually totally working.

And then we will run test user at localhost dash P 2022.

Permission denied.

I got another couple of text messages. All right, it's working. We were able to add that.

Okay. So the very last thing we need to do is for our Docker container pass in the environment variable at runtime.

So environment variable entry point Docker.

So you might be able to just use it.

I think that's the case. I'm showing how much I actually get to program since a lot of this is so rusty for me.

Honeypot D and shoot.


Okay. I think this will work. We just run honeypot DN, go build. And the way we run the program is important.

So Docker build. Let's build this Docker up.

I hope the Docker Damon is running and I'm listening on the socket and everything and I can actually run these.

Otherwise this will be a little anti-climatic.

But the way we will run this is.

So now Dr.

Run. Well, where's our actual image after a run should crash. Oh, that's not good.

Did we have an issue?

We might've had an issue here. Let's try it. We have 60 seconds.

I wonder if we can make this work. Oh, I need goose Linux. Go build. Now this will work.

So we have to build this for Linux because I'm building this for Darwin right now for my Mac.

But I think this will work. I'm going to get this all wired up and committed to Bitbucket.

It should all be on our Bitbucket that we've been working on., EJCX, Honeypot D, all of the code we've been working on is here.

And I will commit this in just a few minutes after the show.

Thank you for watching me today. Even though we had some technical difficulties at the beginning to say the least.

And I think next week, you missed this while I was muted, but I think I'm going to start building a home security system on HackerTime for the next few weeks with a camera and some fancy stuff.

So please join me.

Thank you for being here this week. Bye. My name is Jagger McConnell.

I am the CEO of Crunchbase. Crunchbase is the world's leading provider of private company information on the Internet.

We have over 30 million people coming to us using us for find their next investment, find their next investor, even salespeople going and finding their next opportunity all within Crunchbase.

When we break a new story, when we have a new funding event happening, that's a big deal.

Tons of traffic comes into Crunchbase. And those are the most critical times for us to stay up.

If we go down, our users would be disappointed.

They'd go find that new somewhere else. And that's when we honestly rely on Cloudflare at the most.

I don't have the bandwidth or the headcount to go and have a huge team trying to keep our servers up on time, trying to mitigate those attacks.

And that's when you go and turn to a vendor to go and say, look, this is your core competency.

Please do that for us because you're going to do better than we can.

From the CDN perspective, 92% of our traffic goes to the CDN servers. So they don't actually touch our origin servers.

It's pretty amazing. That means that when those spikes happen, the traffic is distributed across that entire network of servers, which not only saves us bandwidth and that ultimately saves us cost, but also from an end user perspective, things are super fast and that makes them happy.

Cloudflare allows us to go and look like we have a huge international presence by having 115 different servers worldwide.

It's actually pushing our data out to those edge servers.

And that allows from our end user perspective to have a faster experience because the servers are right next to them, right?

So there are very few hops, even though they're in Australia or in Asia, they have an incredible experience using Crunchbase because of that CDN.

The most critical thing is that they can rely on us.

They know that when they go to, they find the thing that they expect and having that server up and running.

Cloudflare lets us deliver on that promise, right? That expectation that that user has by being up and running.

When you're a large website, you have a huge target on your back.

So Cloudflare helps us go and mitigate that risk by with our DDoS mitigation, with their WAF protection.

Just last month, we had over 1600 different attacks.

It's funny, lots of people crawl us, as you might imagine, like when we're a data set, people go and try to find, sort of get our information in whatever way they can.

But what's funny is that sometimes they're not the best coders when they try to go and write those crawlers.

So what it actually becomes is a DDoS attack where it's one IP trying to just get as much information from the same page over and over and over, millions and millions of requests.

And they don't even probably intend to be doing that.

We see those sorts of attacks all the time. And that's, again, where Cloudflare can step in and just make sure that doesn't happen.

And that is an important thing for us from a security standpoint.

Obviously, with all these hackers trying to do ransomware and trying to take down our servers, having the Cloudflare protection there ensures that we are safe.

And honestly, I think the hackers just go somewhere else when they see Cloudflare protecting our servers.

Thumbnail image for video "Hacker Time"

Hacker Time
Join Evan Johnson each week for the latest security news, programming tutorials, and more!
Watch more episodes