36

Here’s an example request we can make to the GitHub API:

curl 'https://api.github.com/authorizations' --user "USERNAME"

This will prompt for the account password, to continue:

Enter host password for user 'USERNAME':

If we don’t want to get the prompt, we can provide the password at the same time as the username:

curl 'https://api.github.com/authorizations' --user "USERNAME:PASSWORD"

But is this method less secure? Does curl send all the data at once, or does it first setup a secure connection, and only then send the USERNAME and PASSWORD?

user137369
  • 693
  • 5
  • 9

3 Answers3

74

Regarding the connection there's no difference: the TLS is negotiated first and the HTTP request is secured by the TLS.

Locally this might be less secure, because:

  • The password gets saved to the command history (~/.bash_history) as a part of the command. Note: This can be avoided by adding a space in front of the command before running it (provided you have the setting ignorespace in variable HISTCONTROL).
  • On a shared system, it will usually be visible to others in ps, top and such, or by reading /proc/$pid/cmdline, for as long as the command is running.
  • Storing the password unsecured in a script might pose a security risk, depending on where the script itself is stored.
sleske
  • 1,622
  • 12
  • 22
Esa Jokinen
  • 16,100
  • 5
  • 50
  • 55
  • Thank you. I’m not sending it directly through the shell. I’m asking for it via `read` in a script. – user137369 Mar 16 '19 at 12:11
  • 1
    Then you must keep the script in a safe place. I'd recommend `700` permissions. – Esa Jokinen Mar 16 '19 at 12:40
  • 7
    to solve the issue with `.bash_history` you could just prepend a space in front of your command. This way it doesn't get saved to history. (further info over here: https://unix.stackexchange.com/questions/115917/why-is-bash-not-storing-commands-that-start-with-spaces ) – Anticom Mar 16 '19 at 15:04
  • 8
    This doesn't solve the `/proc/${pid}/cmdline` issue (e.g., it showing up in `ps` output). If there are multiple users on a system, this is a great way to accidentally disclose a password. – Stephen Touset Mar 16 '19 at 17:26
  • 4
    @StephenTouset check here: https://unix.stackexchange.com/q/385339/135943. Curl password arguments do NOT appear in ps output, except possibly for a minuscule (and hard to demonstrate) time period after the curl command is invoked. Should not be relied on entirely for security but it’s pretty effective. – Wildcard Mar 16 '19 at 19:52
  • 1
    @dave_thompson_085 see my comment above. It is actually usually NOT visible in the places you mention, although there is a tiny race condition window where it may be. – Wildcard Mar 16 '19 at 19:57
9

But is this method less secure?

No, it is not if you use https. When you use HTTPS your complete transaction will be encrypted. But as @Esa mentioned it is insecure locally which you can avoid adding a space before your command so that the command will not be in your command history. If you are worried about exposing the command on the other users ps than hardening /proc would help you with that. Follow the link to enable hidepid.

Does curl send all the data at once, or does it first setup a secure connection, and only then send the USERNAME and PASSWORD?

No curl doesn't send all the data at once. Like other SSL/TLS connection, curl will initiate SSL handshake before passing any data.

You can inspect how your data is transferred with tcpdump, tshark or Wireshark like following, (after running tcpdump/tshark, run the curl command)

TCPDUMP

[root@arif]# tcpdump -i eth0 -n src host 192.168.1.1 and dst host 192.168.1.2 and port 443 -XX

Where,

  • -i: for listening on a specific interface which is in this case eth0
  • src host : Specifying source ip address
  • dst host : Specifying destination ip address
  • port: Specifying port 443 which is the default for SSL connection. You can change according to your requirement.
  • XX: For showing header, packet contents and link level header in HEX and ASCII.

You will start to see gibberish contents after a few packets. You also can grep your password from the packet with the following command,

[root@arif]# tcpdump -li eth0 -n src host 192.168.1.1 and dst host 192.168.1.2 and port 443 -XX | grep 'password'

If your password shows up there then your password did not get encrypted before transmission. Otherwise, you are okay.

TSHARK

[root@arif]# tshark -O tls "ip src 192.168.1.1 and ip dst 192.168.1.2" -x

Where,

  • -O: for mentioning protocol.
  • -x: for see packet contents.

you can grep your password with the above command too.

arif
  • 1,088
  • 13
  • 24
3

The best way to protect from local users is to use a ".netrc" file. The curl man page should have details on how to use it.

schroeder
  • 123,438
  • 55
  • 284
  • 319