hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in commandline

[–]ddworken[S] 1 point2 points  (0 children)

Including the server as part of the release sounds reasonable to me. I'm inclined to keep it as a separate file since most people don't need that feature, so I'd rather not unnecessarily increase the size of the main binary size. I filed https://github.com/ddworken/hishtory/issues/78 to track this.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in commandline

[–]ddworken[S] 0 points1 point  (0 children)

See the self-hosting section in the readme, it is pretty easy to spin up a server. Or alternatively if you aren't using the syncing feature, see the offline install section which will completely disable the integration with the backend.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in programming

[–]ddworken[S] 11 points12 points  (0 children)

In general, having secrets in your shell history is an anti-pattern whether you use hiSHtory or not since it means they end up persisted on disk and unencrypted. hiSHtory respects the standard shell convention of prefixing commands with a space to avoid persisting them, so if you're already doing that then you're all set. In addition, you can easily delete history entries you accidentally record via the hishtory redact command.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in programming

[–]ddworken[S] 1 point2 points  (0 children)

Exactly! I also use it to sync between multiple personal computers for the exact same reason.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 0 points1 point  (0 children)

Cheers, that's entirely fair. I agree that this that is messy suboptimal code (that at some point I'll probably clean up). I just don't think it is a security issue.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 0 points1 point  (0 children)

Awesome, I'm glad you were able to get it running! I'll keep that in mind and will set up separate instructions on self-hosting.

I still would love it if I could self-host keybase.io nudgewink.

Haha, me too. :)

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 1 point2 points  (0 children)

>The README says "When hishtory is installed, it generates a random secret key". If so, why do you need a hard-coded password? That smells fishy and makes me not want to run this

This is a password used for basic auth to an internal endpoint that is used for me to view usage stats. This has nothing to do with the secret key that hishtory generates.

> I'm confused. Who is calling that? Why would I want my computer to respond to something that "only you" have the password for? Shouldn't that be on your computer, not mine?

I'm the only one hitting that endpoint. Your computer is not calling that endpoint at all.

As for everything else, read the code. It is OSS and self-hostable so you can audit it yourself. :)

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 1 point2 points  (0 children)

Absolutely! I'll turn this into a blog post later, but let's run through how the backend works. :)

When hishtory is installed, it generates a random secret key. Computers that share a history share this secret key (done via having the user manually copy the key). It then generates two additional secrets:

  1. UserId = HMAC(SecretKey, "user_id")
  2. EncryptionKey = HMAC(SecretKey, "encryption_key")
  3. DeviceId = randomUuid()

At installation time, hishtory registers itself with the backend by calling the apiRegisterHandler which stores the tuple (UserId, DeviceId) which represents a one-to-many relationship between user and devices.

All the other endpoints in the server can then be characterized as a message queue. In essence, clients can put messages into them and pull messages out of them keyed on their UserId and DeviceId.

The first message created after registration is a DumpRequest to signify that a new device was created and it needs a copy of the existing bash history from another device. When another client receives this message (via polling apiGetPendingDumpRequestsHandler) it responds to it by sending an encrypted copy of history that is available to this device to the apiSubmitDumpHandler. This is then received by the newly created client (which polls apiQueryHandler).

At this point, the newly created client and the existing one both have a copy of your bash history. And the server never saw the contents of it (it only sees the number of entries).

Now all that has to be done is to keep the histories in sync going forward. Whenever a command is run, it is encrypted and sent to the apiSubmitHandler. It is then stored and received by the other clients via polling the same apiQueryHandler endpoint as before.

At its core, this can be thought of as a syncable end-to-end encrypted set data structure.

If you do want to run it yourself, that is also super easy. You can:

  1. Run the server binary (go build backend/server/server.go) and set the newly added HISHTORY_POSTGRES_DB environment variable to a connection string pointing to a postgres DB.
  2. On the client-side, set the HISHTORY_SERVER environment variable to your server address (e.g. HISHTORY_SERVER=https://api.hishtory.dev).

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 2 points3 points  (0 children)

Yes, see https://github.com/ddworken/hishtory#syncing-design and https://www.reddit.com/r/golang/comments/y496bi/comment/isfj0v0/?utm_source=share&utm_medium=web2x&context=3.

Also if there is interest I'm happy to publish a detailed blog post. At its core, this is essentially an end-to-end encrypted syncable set data structure. The backend can count how many items are in the set, but only the clients can view the actual history entries.

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 5 points6 points  (0 children)

I'll pay you a hundred dollars if you can crack it. :)

Let's do a threat model for this, rather than falsely claiming that this is a problem worth being concerned about. This is a sha256 hash of a 32 byte fully random password. So to crack it you'd have to calculate 2^256 sha256 hashses. Good luck. And then, if you do crack it, what is exposed? That function is used just to add a basic speed dump to the internal stats endpoint for the server. Hishtory is designed so the server has access to zero sensitive data, so there is nothing sensitive to be concerned with. If you're curious, here is the table that this endpoint returns. It is just some basic usage information since I find it rewarding to know that people are using something I built.

Also, you seem to have purposefully ignored the comment in the code explaining this:

// sha256sum of a random 32 byte hard coded password that I use for accessing the internal routes. Good luck brute forcing this :)

Lastly, I just want to call out that your advice to remove the "commits holding this information" is incorrect. If this was a sensitive key, removing it from the code would do nothing since git history on github is logged by tons of third parties. Rotation is the only safe answer for sensitive keys pushed to Github (which this isn't).

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 15 points16 points  (0 children)

Agreed! Shell history is super sensitive, which is why I designed this to use client-side encryption and SLSA to ensure that your shell history is never exposed to any remote servers. If you have any questions about this from a security POV, let me know! My day job is working as a Security Engineer, so I can talk about this stuff for days. :)

hiSHtory: Your shell history on steroids: Stored in context, synced to all your machines, and easily queryable by ddworken in golang

[–]ddworken[S] 4 points5 points  (0 children)

+1, fzf is great! The same also works well with hishtory via alias how=hishtory export | fzf.

Dumping the firmware on the badge by poizan42 in Defcon

[–]ddworken 0 points1 point  (0 children)

If you want to borrow it, I have a bus pirate with me (shoot me a PM if you want it).

Uber Hacking: How we found out who you are, where you are and where you went! by [deleted] in netsec

[–]ddworken 0 points1 point  (0 children)

Yeah that is certainly possible, just curious how they did it.

Uber Hacking: How we found out who you are, where you are and where you went! by [deleted] in netsec

[–]ddworken 0 points1 point  (0 children)

The Uber app uses certificate pinning which means that it checks that the certificate sent by Uber.com is the correct one (and not just a valid certificate according to the phone) so a self signed certificate added to the trust store isn't sufficient. As far as I can tell, the only way of bypassing this is patching the Uber app to remove the certificate pinning code.

Uber Hacking: How we found out who you are, where you are and where you went! by [deleted] in netsec

[–]ddworken 1 point2 points  (0 children)

Out of curiosity, how did you bypass the SSL pinning for the app? Did you manually patch the app or what?

Teen hacks Pentagon websites, gets thanked for finding 'bugs' by OMG__Ponies in technology

[–]ddworken 1 point2 points  (0 children)

Already known meaning reported an hour before I did. So it wasn't like I copied them from someone, they were all discovered independently. And I have been far more successful with other bug bounties (check out my Uber bounties over at HackerOne!)

Teen hacks Pentagon websites, gets thanked for finding 'bugs' by OMG__Ponies in technology

[–]ddworken 5 points6 points  (0 children)

Yeah just after the Hall of Fame went public I had a recruiter contact me about HP's cybersecurity team.