SIDEBAR
»
S
I
D
E
B
A
R
«
GitHub to be trusted their own SSH host key?
Jun 11th, 2023 by miki

A May 24th 2023 change of GitHub’s RSA SSH host key just hit me on an older, less used, system doing a git clone. The change was prompted by an unintended exposure of the private part of the host key by GitHub itself.

GitHub.com’s RSA SSH private key was briefly exposed in a public GitHub repository

Github blog-post, “We updated our RSA SSH host key”, 2023-03-23

I’m getting even more reluctant to trust a large organization where such a thing can happen. Additionally they didn’t communicate about this in a way that caught my attention. And now that it has my attention, they do not want to share the specifics about the incident to enable assessment of impact (like exposure duration, popularity of repository etc).

Below is the manual recovery with explanations of what happens and why. I don’t like the way the official blog-post instructs users to retrieving the validated host key in a non-visible way, without human eye balls doing the validation. This is the only chance in the process for injecting human trust into the validation of the host key, don’t skip it!

Consequence #1: fatal MitM warning
When an SSH server’s host key is different to a connecting client (system) compared to what the system has previously seen and acknowledged by the user to be a valid key from the intended counterpart (you do check those host key fingerprint strings, right? If not; PHComp help, WinSCP help), it obviously should and do warn the user about this. Whether the change is of malicious origin or not, is up to the user to investigate. So with OpenSSH this happens;

$ git clone git@github.com:mikini/name-suggestion-index
Cloning into 'name-suggestion-index'...
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s.
Please contact your system administrator.
Add correct host key in <~>/.ssh/known_hosts to get rid of this message.
Offending RSA key in <~>/.ssh/known_hosts:17
  remove with:
  ssh-keygen -f "<~>/.ssh/known_hosts" -R "github.com"
RSA host key for github.com has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
$ 

Remedy #1: remove known host keys for domain (pr. OpenSSH instruction)
Remove host keys associated with github.com domain using -R option to ssh-keygen (default for -f is the UserKnownHostsFile config keyword with default ~/.ssh/known_hosts, so no need to specify that):

$ ssh-keygen -R github.com
# Host github.com found: line 17
# Host github.com found: line 18
# Host github.com found: line 19
<~>/.ssh/known_hosts updated.
Original contents retained as <~>/.ssh/known_hosts.old
$

Consequence #2: non-fatal domain and IP mismatch
Now, because host key references are cached for both the domain and IP there are still mismatches caused by the key exchange choosing ECDSA host key and the key associated with the IP address is the old RSA key. This is prompted during each connection attempt:

$ git clone git@github.com:mikini/name-suggestion-index
Cloning into 'name-suggestion-index'...
Warning: the ECDSA host key for 'github.com' differs from the key for the IP address '140.82.121.3'
Offending key for IP in <~>/.ssh/known_hosts:63
Matching host key in <~>/.ssh/known_hosts:72
Are you sure you want to continue connecting (yes/no)? yes
remote: Enumerating objects: 153255, done.
remote: Counting objects: 100% (177/177), done.
remote: Compressing objects: 100% (103/103), done.
remote: Total 153255 (delta 103), reused 121 (delta 74), pack-reused 153078
Receiving objects: 100% (153255/153255), 550.17 MiB | 2.39 MiB/s, done.
Resolving deltas: 100% (111423/111423), done.
$

Remedy #2: remove known host keys for IPs
To get rid of the mismatch warning, the known host keys associated with IP addresses needs to be removed also. Potentially any of the listed endpoint IP addresses used with an RSA host key on the system earlier will now conflict with the ECDSA from server, requiring removal:

$ ssh-keygen -R 140.82.121.3
# Host 140.82.121.3 found: line 63
<~>/.ssh/known_hosts updated.
Original contents retained as <~>/.ssh/known_hosts.old
$

$ ssh-keygen -R 140.82.121.4
# Host 140.82.121.4 found: line 161
<~>/.ssh/known_hosts updated.
Original contents retained as <~>/.ssh/known_hosts.old
$

After remedy
Now, the SSH client will see an unknown host key and prompt for validation. Be sure to verify the presented host key with the officially communicated one (from doc. article or API):
$ git clone git@github.com:mikini/name-suggestion-index
Cloning into 'name-suggestion-index'...
The authenticity of host 'github.com (140.82.121.4)' can't be established.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,140.82.121.4' (ECDSA) to the list of known hosts.
remote: Enumerating objects: 153152, done.
remote: Counting objects: 100% (183/183), done.
remote: Compressing objects: 100% (83/83), done.
Receiving objects: 100% (153152/153152), 550.22 MiB | 1.42 MiB/s, done.
remote: Total 153152 (delta 109), reused 158 (delta 100), pack-reused 152969
Resolving deltas: 100% (111352/111352), done.
$ 
GitHub CLI on Ubuntu LTS (16.04 & 18.04)
Mar 4th, 2020 by miki

Inspired by a John Sullivan (of FSF) tweet asking about opinions on the new and shiny MS(TM) GitHub(TM) CLI(TM) tool named “gh”(TM) I wanted to try it out on one of my Ubuntu LTS systems (16.04).

I’ve always disliked the proprietary and centralised monoculture of github, especially after that thing with MS, so I’ve mostly avoided using the service for code I produce myself. If interested in independence and decentralisation maybe you should read up on that long fabled subject? Thus I’ve never even tried the predecessor “hub”(TM) tool (main page), and exactly how it differs from this new “CLI” thing is not obviously apparent from the communications.

Nevertheless, the “gh” tool, officially dubbed  GitHub CLI, being distributed under MIT license and written in go(lang) (afterwards, found out that this is indeed also applicable to the predecessing “hub” tool) made me curious enough to go see what they’re up to. Maybe its not that sinister a plot and they really just want to improve the independent and freely available mechanisms for source code storage, distribution and maintenance (I wish)?

TL:DR

A fairly recent (2019-09) version of go, >=1.13, is required so some gymnastics are needed to make stuff work on older distros like Ubuntu’s LTS (with 5 years support from Canonical). Anyway, this is what I did to build a useable “gh” ELF executable (20 MiB!, se below), this is from source, no precompiled stuff, no snaps. It was done on Ubuntu 16.04 (xenial) but I’ve been somewhat careful to inspect that things ought to be good for 18.04 (bionic) too. Non-essential output from the commands is largely discarded here. See Gory Details section below for the full monty.

Add go PPA & install packages

$ sudo add-apt-repository ppa:longsleep/golang-backports
$ sudo apt update
$ sudo apt install golang
$ go version
go version go1.13.4 linux/amd64

Clone repo & build

$ cd
$ git clone https://github.com/cli/cli .githubcli
$ cd .githubcli
$ make

Setup PATH & test

$ echo 'export PATH="$HOME/.githubcli/bin:$PATH"' >> ~/.bash_profile
$ bash --login
$ gh
Work seamlessly with GitHub from the command line.

GitHub CLI is in early stages of development, and we'd love to hear your
feedback at <https://forms.gle/umxd3h31c7aMQFKG7>

Usage:
  gh [command]

Available Commands:
  help        Help about any command
  issue       Create and view issues
  pr          Create, view, and checkout pull requests
  repo        Create, clone, fork, and view repositories

Flags:
      --help              Show help for command
  -R, --repo OWNER/REPO   Select another repository using the OWNER/REPO format
      --version           Show gh version

Use "gh [command] --help" for more information about a command.
subcommand is required
$

Trying it out

Randomly picked one of my few github repos, it contains some js experiments on parsing NMEA formatted coordinates, rather uninterestingly empty.

Clone

user@host:~$ gh repo clone mikini/coordinates 
Notice: authentication required
Press Enter to open github.com in your browser... 

<auth session in browser>

Authentication complete. Press Enter to continue...

Cloning into 'coordinates'...
remote: Enumerating objects: 10, done.
remote: Total 10 (delta 0), reused 0 (delta 0), pack-reused 10
Unpacking objects: 100% (10/10), done.
Checking connectivity... done.
user@host:~$

An ordinary OAuth request was spawned for authentication on https://github.com/login/oauth/authorize. The javascript executed in the browser seemed to interact with the gh tool through a local TCP connection on localhost:45454 which was the redirection target on authorisation (URL parameter: “redirect_uri=http://localhost:45454/callback”). The socket was rightfully not bound after the authentication had succeeded but this is definitely an attack vector, albeit hopefully only for locally running processes.

Listing issues & prs

user@host:~$ cd coordinates/
user@host:~$:~/coordinates$ gh issue list

Issues for mikini/coordinates

There are no open issues
miki@vcas-miki2:~/coordinates$ gh pr view
no open pull requests found for branch "master"
miki@vcas-miki2:~/coordinates$

Creating issues

miki@vcas-miki2:~/coordinates$ gh issue create

Creating issue in mikini/coordinates

? Title Testing gh
? Body <Received>
? What's next? Preview in browser
Opening github.com/mikini/coordinates/issues/new/ in your browser.
miki@vcas-miki2:~/coordinates$

miki@vcas-miki2:~/coordinates$ gh issue create

Creating issue in mikini/coordinates

? Title Testing gh tool
? Body <Received>
? What's next? [Use arrows to move, type to filter]
> Preview in browser
Submit
Cancel

https://github.com/mikini/coordinates/issues/1
miki@vcas-miki2:~/coordinates$

On the first issue creation interaction I selected “preview in browser” which opened a draft issue in the browser, and dumped me back into the shell on the command line. The second interaction actually resulted in #1.

Gory Details

PPA options

The golang-backports PPA is maintained independently by Simon Eisenmann (credits: ~longsleep, @github, stdin.xyz) and carries packages up to:

There’s also an official PPA from the golang project (~gophers) which however only carries packages up to 1.11 for both.

Full (mostly) installation dump

Add go PPA, install packages

user@host:~$ sudo add-apt-repository ppa:longsleep/golang-backports
Golang 1.8, 1.9, 1.10, 1.11, 1.12, 1.13 and 1.14 PPA for Ubuntu
 More info: https://launchpad.net/~longsleep/+archive/ubuntu/golang-backports
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpvnuym97a/secring.gpg' created
gpg: keyring `/tmp/tmpvnuym97a/pubring.gpg' created
gpg: requesting key 56A3D45E from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpvnuym97a/trustdb.gpg: trustdb created
gpg: key 56A3D45E: public key "Launchpad PPA for Simon Eisenmann" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK
user@host:~$

user@host:~$ sudo apt update
Hit:1 http://dk.archive.ubuntu.com/ubuntu xenial InRelease
Get:2 http://dk.archive.ubuntu.com/ubuntu xenial-updates InRelease [109 kB] 
...
...
Get:37 http://security.ubuntu.com/ubuntu xenial-security/universe DEP-11 64x64 Icons [194 kB]
Get:38 http://security.ubuntu.com/ubuntu xenial-security/multiverse amd64 DEP-11 Metadata [2.468 B]
Fetched 7.614 kB in 3s (2.346 kB/s) 
Reading package lists... Done
Building dependency tree 
Reading state information... Done
419 packages can be upgraded. Run 'apt list --upgradable' to see them.
user@host:~$

user@host:~$ apt list --upgradeable golang -a
Listing... Done
golang/xenial,xenial 2:1.13~1longsleep1+xenial all [upgradable from: 2:1.6-1ubuntu4]
golang/xenial,xenial,now 2:1.6-1ubuntu4 all [installed,upgradable to: 2:1.13~1longsleep1+xenial]

user@host:~$

user@host:~$ sudo apt install golang
Reading package lists... Done
Building dependency tree 
Reading state information... Done
The following packages were automatically installed and are no longer required:
golang-1.6 golang-1.6-doc golang-1.6-go golang-1.6-src
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
golang-1.13 golang-1.13-doc golang-1.13-go golang-1.13-src golang-doc golang-go golang-src
Recommended packages:
golang-1.13-race-detector-runtime
The following NEW packages will be installed
golang-1.13 golang-1.13-doc golang-1.13-go golang-1.13-src
The following packages will be upgraded:
golang golang-doc golang-go golang-src
4 to upgrade, 4 to newly install, 0 to remove and 413 not to upgrade.
Need to get 60,2 MB of archives.
After this operation, 322 MB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-1.13-src amd64 1.13.4-1longsleep1+xenial [12,7 MB]
Get:2 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-1.13-go amd64 1.13.4-1longsleep1+xenial [44,9 MB]
Get:3 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-1.13-doc all 1.13.4-1longsleep1+xenial [2.542 kB]
Get:4 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-1.13 all 1.13.4-1longsleep1+xenial [25,2 kB]
Get:5 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-src amd64 2:1.13~1longsleep1+xenial [3.838 B]
Get:6 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-go amd64 2:1.13~1longsleep1+xenial [23,0 kB]
Get:7 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang-doc all 2:1.13~1longsleep1+xenial [3.880 B]
Get:8 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu xenial/main amd64 golang all 2:1.13~1longsleep1+xenial [3.826 B]
Fetched 60,2 MB in 5s (10,8 MB/s) 
Selecting previously unselected package golang-1.13-src.
(Reading database ... 460737 files and directories currently installed.)
Preparing to unpack .../golang-1.13-src_1.13.4-1longsleep1+xenial_amd64.deb ...
Unpacking golang-1.13-src (1.13.4-1longsleep1+xenial) ...
Selecting previously unselected package golang-1.13-go.
Preparing to unpack .../golang-1.13-go_1.13.4-1longsleep1+xenial_amd64.deb ...
Unpacking golang-1.13-go (1.13.4-1longsleep1+xenial) ...
Selecting previously unselected package golang-1.13-doc.
Preparing to unpack .../golang-1.13-doc_1.13.4-1longsleep1+xenial_all.deb ...
Unpacking golang-1.13-doc (1.13.4-1longsleep1+xenial) ...
Selecting previously unselected package golang-1.13.
Preparing to unpack .../golang-1.13_1.13.4-1longsleep1+xenial_all.deb ...
Unpacking golang-1.13 (1.13.4-1longsleep1+xenial) ...
Preparing to unpack .../golang-src_2%3a1.13~1longsleep1+xenial_amd64.deb ...
Unpacking golang-src (2:1.13~1longsleep1+xenial) over (2:1.6-1ubuntu4) ...
Preparing to unpack .../golang-go_2%3a1.13~1longsleep1+xenial_amd64.deb ...
Unpacking golang-go (2:1.13~1longsleep1+xenial) over (2:1.6-1ubuntu4) ...
Preparing to unpack .../golang-doc_2%3a1.13~1longsleep1+xenial_all.deb ...
Unpacking golang-doc (2:1.13~1longsleep1+xenial) over (2:1.6-1ubuntu4) ...
Preparing to unpack .../golang_2%3a1.13~1longsleep1+xenial_all.deb ...
Unpacking golang (2:1.13~1longsleep1+xenial) over (2:1.6-1ubuntu4) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up golang-1.13-src (1.13.4-1longsleep1+xenial) ...
Setting up golang-1.13-go (1.13.4-1longsleep1+xenial) ...
Setting up golang-1.13-doc (1.13.4-1longsleep1+xenial) ...
Setting up golang-1.13 (1.13.4-1longsleep1+xenial) ...
Setting up golang-src (2:1.13~1longsleep1+xenial) ...
Setting up golang-go (2:1.13~1longsleep1+xenial) ...
Setting up golang-doc (2:1.13~1longsleep1+xenial) ...
Setting up golang (2:1.13~1longsleep1+xenial) ...
user@host:~$ 

user@host:~$ go version
go version go1.13.4 linux/amd64
user@host:~$ 

Clone repo & build

user@host:~$ git clone https://github.com/cli/cli .githubcli
Cloning into '.githubcli'...
remote: Enumerating objects: 168, done.
remote: Counting objects: 100% (168/168), done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 5577 (delta 93), reused 122 (delta 67), pack-reused 5409
Receiving objects: 100% (5577/5577), 7.53 MiB | 2.61 MiB/s, done.
Resolving deltas: 100% (3269/3269), done.
Checking connectivity... done.
user@host:~$ 

user@host:~$ cd .githubcli
user@host:~/.githubcli (master=)$ make
go: downloading github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
go: downloading github.com/mitchellh/go-homedir v1.1.0
go: downloading github.com/mattn/go-colorable v0.1.6
go: downloading github.com/spf13/cobra v0.0.6
go: downloading gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
go: downloading github.com/mattn/go-isatty v0.0.12
go: downloading golang.org/x/text v0.3.2
go: extracting github.com/mitchellh/go-homedir v1.1.0
go: extracting github.com/mattn/go-colorable v0.1.6
go: extracting github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
go: extracting github.com/spf13/cobra v0.0.6
go: extracting github.com/mattn/go-isatty v0.0.12
go: downloading golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
go: downloading golang.org/x/crypto v0.0.0-20200219234226-1ad67e1f0ef4
go: downloading github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
go: downloading github.com/briandowns/spinner v1.9.0
go: extracting gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
go: downloading github.com/hashicorp/go-version v1.2.0
go: downloading github.com/spf13/pflag v1.0.5
go: downloading github.com/AlecAivazis/survey/v2 v2.0.7
go: downloading github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: downloading github.com/charmbracelet/glamour v0.1.1-0.20200304134224-7e5c90143acc
go: extracting github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
go: extracting github.com/spf13/pflag v1.0.5
go: extracting github.com/hashicorp/go-version v1.2.0
go: downloading gopkg.in/yaml.v2 v2.2.8
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.0
go: downloading github.com/henvic/httpretty v0.0.4
go: extracting github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: extracting github.com/briandowns/spinner v1.9.0
go: extracting github.com/AlecAivazis/survey/v2 v2.0.7
go: downloading github.com/fatih/color v1.7.0
go: extracting github.com/charmbracelet/glamour v0.1.1-0.20200304134224-7e5c90143acc
go: downloading github.com/yuin/goldmark v1.1.24
go: downloading github.com/microcosm-cc/bluemonday v1.0.2
go: extracting gopkg.in/yaml.v2 v2.2.8
go: extracting github.com/henvic/httpretty v0.0.4
go: downloading github.com/olekukonko/tablewriter v0.0.4
go: downloading github.com/muesli/reflow v0.1.0
go: extracting github.com/fatih/color v1.7.0
go: extracting github.com/microcosm-cc/bluemonday v1.0.2
go: extracting github.com/cpuguy83/go-md2man/v2 v2.0.0
go: extracting golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
go: extracting github.com/muesli/reflow v0.1.0
go: extracting github.com/olekukonko/tablewriter v0.0.4
go: downloading golang.org/x/net v0.0.0-20200219183655-46282727080f
go: extracting github.com/yuin/goldmark v1.1.24
go: downloading github.com/alecthomas/chroma v0.7.2-0.20200304075647-34d9c7143bf5
go: downloading github.com/mattn/go-runewidth v0.0.8
go: downloading github.com/muesli/termenv v0.4.0
go: downloading github.com/russross/blackfriday/v2 v2.0.1
go: extracting golang.org/x/crypto v0.0.0-20200219234226-1ad67e1f0ef4
go: extracting github.com/mattn/go-runewidth v0.0.8
go: extracting github.com/russross/blackfriday/v2 v2.0.1
go: downloading github.com/shurcooL/sanitized_anchor_name v1.0.0
go: extracting github.com/alecthomas/chroma v0.7.2-0.20200304075647-34d9c7143bf5
go: extracting github.com/shurcooL/sanitized_anchor_name v1.0.0
go: extracting github.com/muesli/termenv v0.4.0
go: downloading github.com/dlclark/regexp2 v1.2.0
go: downloading github.com/lucasb-eyer/go-colorful v1.0.3
go: downloading github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f
go: downloading github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
go: extracting golang.org/x/text v0.3.2
go: extracting github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f
go: extracting github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
go: extracting golang.org/x/net v0.0.0-20200219183655-46282727080f
go: extracting github.com/lucasb-eyer/go-colorful v1.0.3
go: extracting github.com/dlclark/regexp2 v1.2.0
go: finding github.com/spf13/cobra v0.0.6
go: finding github.com/AlecAivazis/survey/v2 v2.0.7
go: finding github.com/henvic/httpretty v0.0.4
go: finding github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
go: finding github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
go: finding gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
go: finding github.com/spf13/pflag v1.0.5
go: finding github.com/hashicorp/go-version v1.2.0
go: finding github.com/mitchellh/go-homedir v1.1.0
go: finding github.com/briandowns/spinner v1.9.0
go: finding golang.org/x/text v0.3.2
go: finding github.com/cpuguy83/go-md2man/v2 v2.0.0
go: finding github.com/charmbracelet/glamour v0.1.1-0.20200304134224-7e5c90143acc
go: finding github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: finding github.com/mattn/go-colorable v0.1.6
go: finding gopkg.in/yaml.v2 v2.2.8
go: finding github.com/russross/blackfriday/v2 v2.0.1
go: finding github.com/mattn/go-isatty v0.0.12
go: finding github.com/fatih/color v1.7.0
go: finding golang.org/x/crypto v0.0.0-20200219234226-1ad67e1f0ef4
go: finding github.com/muesli/termenv v0.4.0
go: finding golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
go: finding github.com/shurcooL/sanitized_anchor_name v1.0.0
go: finding github.com/yuin/goldmark v1.1.24
go: finding github.com/alecthomas/chroma v0.7.2-0.20200304075647-34d9c7143bf5
go: finding github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f
go: finding github.com/dlclark/regexp2 v1.2.0
go: finding github.com/lucasb-eyer/go-colorful v1.0.3
go: finding github.com/muesli/reflow v0.1.0
go: finding github.com/microcosm-cc/bluemonday v1.0.2
go: finding github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
go: finding github.com/olekukonko/tablewriter v0.0.4
go: finding github.com/mattn/go-runewidth v0.0.8
go: finding golang.org/x/net v0.0.0-20200219183655-46282727080f
user@host:~/.githubcli (master=)$ 

Cursory inspection of exec

user@host:~/.githubcli (master=)$ ls -l bin/gh
-rwxrwxr-x 1 user user 21097487 Mar  4 18:03 bin/gh
user@host:~/.githubcli (master=)$ 

user@host:~/.githubcli (master=)$ file bin/gh
bin/gh: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, not stripped
user@host:~/.githubcli (master=)$ 

user@host:~/.githubcli (master=)$ ldd bin/gh
	linux-vdso.so.1 =>  (0x00007ffdc4329000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb1018c2000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb1014f8000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb101adf000)
user@host:~/.githubcli (master=)$ 

user@host:~/.githubcli (master=)$ nm -D bin/gh
                 U abort
00000000004fd140 T _cgo_panic
000000000045bf10 T _cgo_topofstack
00000000004fd190 T crosscall2
                 U __errno_location
                 U __fprintf_chk
                 U fputc
                 U free
                 U freeaddrinfo
                 U fwrite
                 U gai_strerror
                 U getaddrinfo
                 U getnameinfo
                 U malloc
                 U mmap
                 U munmap
                 U nanosleep
                 U pthread_attr_destroy
                 U pthread_attr_getstacksize
                 U pthread_attr_init
                 U pthread_cond_broadcast
                 U pthread_cond_wait
                 U pthread_create
                 U pthread_detach
                 U pthread_mutex_lock
                 U pthread_mutex_unlock
                 U pthread_sigmask
                 U setenv
                 U sigaction
                 U sigaddset
                 U sigemptyset
                 U sigfillset
                 U sigismember
                 U __stack_chk_fail
                 U stderr
                 U strerror
                 U unsetenv
                 U __vfprintf_chk
user@host:~/.githubcli (master=)$ 

Setup PATH & test

user@host:~/.githubcli (master=)$ cd
user@host:~$ echo 'export PATH="$HOME/.githubcli/bin:$PATH"' >> ~/.bash_profile
user@host:~$ bash --login
user@host:~$ gh
Work seamlessly with GitHub from the command line.

GitHub CLI is in early stages of development, and we'd love to hear your
feedback at <https://forms.gle/umxd3h31c7aMQFKG7>

Usage:
  gh [command]

Available Commands:
  help        Help about any command
  issue       Create and view issues
  pr          Create, view, and checkout pull requests
  repo        Create, clone, fork, and view repositories

Flags:
      --help              Show help for command
  -R, --repo OWNER/REPO   Select another repository using the OWNER/REPO format
      --version           Show gh version

Use "gh [command] --help" for more information about a command.
subcommand is required
user@host:~$
Silent browser redirect on invalid certificate
Nov 15th, 2018 by miki

Hit an odd browser behaviour today.

Trawling through some of those nice and dandy terms for a service (no I won’t tell) I followed a link and suddenly hit an “insecure connection” message from Firefox.

Examining the certificate using the usual “openssl s_client” and “openssl x509” tools surely enough revealed that the served certificate didn’t include the second-level but only on the third-level www sub-domain. Strangely enough I discovered that when entering the same URL directly into the address bar of Firefox the connection was somehow redirected to the www sub-domain and loaded fine without any complaints from Firefox.

Looking into what was happening on the wire using wget directed to not check the certificate (–no-check-certificate) and displaying server responses (–server-response/-S) revealed that the server behind the misconfigured certificate was aiming to issue a HTTP 301 redirect to the valid www sub-domain of the site (actual site replaced by foo.bar and localhost ip);

$ wget –server-response –no-check-certificate –output-document=/dev/null https://foo.bar
–2018-11-15 18:59:14– https://foo.bar/
Resolving foo.bar (foo.bar)… 127.0.0.1
Connecting to foo.bar (foo.bar)|127.0.0.1|:443… connected.
WARNING: no certificate subject alternative name matches
requested host name ‘foo.bar’.
HTTP request sent, awaiting response…
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Location: https://www.foo.bar/
Date: Thu, 15 Nov 2018 17:59:13 GMT
Content-Length: 152
Location: https://www.foo.bar/ [following]

Apparently Firefox’s behaviour in this scenario differs depending on the method in which the user is supplying the URL, in some cases silently ignoring the TLS/SSL warning. A little more experimentation revealed that it was actually not the source of the URL, link followed versus one entered in address bar, that made any difference. Instead it is the presence of a trailing slash on the URL that triggers the silent suppression of the serious red flag that the second-level domain asked to be fetched is not present in the served certificate. I was fooled by the fact that when entering URLs in the address bar Firefox suggests ending the URL on a slash (‘/’) if it is not already present. Manually removing this when editing in the address bar also makes Firefox display the security warning. Alas, the link I originally followed was also missing the trailing slash and behaved as expected by throwing me into a security warning.

The whole “feature” of silently ignoring a security issue seemed very odd to me, but a bit of searching revealed that this was apparently championed by Google Chrome a couple of years ago. It is described in this servertastic post which also directs to a discussion on Twitter, with some key points replicated below, about its presence in Chrome and confirmation from a Chrome team member that the behaviour is intended.

The thread ends with a guy who had dug up the source code of the feature in Chromium (on which Chrome is based) known as “SSLCommonNameMismatchHandling” in file browser/ssl/common_name_mismatch_handler.cc (see all mentions across code base).

This has obviously also trickled down into Firefox, however, not much mention of that is to be found. Not even traces of it by some quick searches of the mozilla-central codebase. Some day I promise (really!) to dig through all source of Mozilla and hunt down the implementation, but for now I’ll revert to a bit of practical experimentation showing the behaviour in the different browsers and operating systems I happen to have access to at the moment;

  • Ubuntu 16.04
    • Firefox 62.0.3: warning, with trailing ‘/’: No warning
    • Chromium 69.0.3497.81: no warning, with trailing ‘/’: no warning
  • Windows Server 2016
    • Firefox 62.0.2: warning, with trailing ‘/’: no warning
    • Google Chrome 70.3538.102: no warning, with trailing ‘/’: no warning
    • Internet Explorer 11.2580.14393.0: warning, with trailing ‘/’: warning
  • Windows Server 2008
    • Firefox 59.0.3: warning, with trailing ‘/’: warning
    • Google Chrome 70.3538.102: no warning, with trailing ‘/’: no warning
    • Internet Explorer 11.0.9600.19080: warning, with trailing ‘/’: warning

So somewhere between 59.0.3 and 62.0.2 Firefox also implemented a policy of silently accepting invalid certificates when certain non-obvious criteria is met (is the redirect actually followed and certs checked, or is “www.” just prefixed?), but this happens only when the URL ends on a slash. Go figure…

Setting free a Google Authenticator TOTP secret
Nov 7th, 2017 by miki

Below you’ll find an illustrated guide for freeing the authentication mechanism used by the Google Authenticator app for Android or iPhone for use on your favorite device (anywhere an implementation is available). In fact the Authenticator is using a standards based 2FA (two factor authentication) scheme defined by OATH (Initiative for Open Authentication) and published in RFC6238 dubbed TOTP – Time-Based One-Time Password Algorithm (more Authenticator background and it’s basis HOTP).

This is a rather fine contraption but Google doesn’t advertise it very loudly being a standard instead locking the generated TOTP secret into a QR code that they will only imply are for use by their own Google Authenticator. That is not true as a host of alternative Android OTP apps are compatible and can read the QR codes as they are based upon the Authenticator’s legacy as an open source application which Google took private.

Retrieve Google Account QR Code

Login to your Google Account (maybe using the authenticator?) and go to Account -> Security -> Signin -> 2-step verification.

Locate the “Authenticator app” section and Click “CHANGE PHONE” (really “CHANGE TOTP SECRET”).

Screenshot from 2017-11-06 22-32-05

In my country’s locale, Danish, this is BTW mistranslated as “SKIFT TELEFONNUMMER” = change phone number);

Screenshot from 2017-11-07 00-50-06

You’ll now get a choice between either iPhone or Android, this will only affect the link to the app store shown on next screen which also contains the QR code, the one we are really after:

Screenshot from 2017-11-06 23-03-44

Right click the QR code image, select to save it and put it somewhere you can find it (~/Google_TOTP_QR.png might be sensible).

Get your tools right

Install the QR-code decoder zbar for extracting the TOTP secet from the image and the OATH toolkit oathtool for generating future TOTP passwords using it. On Debian/Ubuntu this can be done by installing the packages zbar-tools and oathtool.

 

$ sudo apt install zbar-tools oathtool

 

Now extract the otpauth URI (seems to be a Google thing) by passing the image file to zbarimg;

 

$ zbarimg ~/Google_TOTP_QR.png
 QR-Code:otpauth://totp/Google%3Auser%40domain.com?secret=pca7uyfht7f6mfs7oiec4aeavxaevish&issuer=Google
 scanned 1 barcode symbols from 1 images in 0.02 seconds

 

The URI contains all parameters to input into the TOTP algorithm for generating a password usable for 2FA authentication, notably the secret key in base32 format. Defaults are not mentioned in the URI and are not necessary to specify explicitly for oathtool. So for the above URI specifying only a secret, a password can be generated as such;

$ oathtool --totp --base32 pca7uyfht7f6mfs7oiec4aeavxaevish
 491293

“491293” being the password, having a default validity of 30 seconds (called step size because of the counter based nature of the HOTP behind it).

If your are interested in the defaults assumed by oathtool they can be viewed by supplying -v to it (not showing TOTP mode=SHA512, I later added this feature in my oath-toolkit fork, and opened a MR) ;

$ oathtool --totp --base32 pca7uyfht7f6mfs7oiec4aeavxaevish -v
Hex secret: 7881fa60a79fcbe6165f72082e0080adc04aa247
Base32 secret: PCA7UYFHT7F6MFS7OIEC4AEAVXAEVISH
Digits: 6
Window size: 0
Step size (seconds): 30
Start time: 1970-01-01 00:00:00 UTC (0)
Current time: 2017-11-06 23:23:31 UTC (1510010611)
Counter: 0x30007F7 (50333687)

133339

 

Use & Behold

Enjoy having cut your reliance on the Google Autenticator, and opened up for your own choice of client:

Also see the dongleauth.info website for a list of other sites supporting TOTP and U2F.

Clean Up & Secure

Be sure to delete the QR code image when finished, and seek out a suitably secure place to store your TOTP secret. One solution could be using PGP encryption, maybe even through some clever management system such as pass.

Also educate yourself of the shortcomings of TOTP/HOTP and consider studying and using the FIDO U2F standard and related devices.

»  Substance:WordPress   »  Style:Ahren Ahimsa
© 2023 Mikkel Kirkgaard Nielsen, contents CC BY-SA 4.0