OpenTollGate / TollDocs

0 stars 0 forks source link

RADIUS support #1

Open Amperstrand opened 2 hours ago

Amperstrand commented 2 hours ago

Warning: this inital POC may contain a vulnerability because the username that the client provides to the RADIUS server is passed as an argument to the bash script without much (or any) checking of the untrusted user input. If you find it, please exploit it, patch it, and report back in this issue.

Elevator pitch

A RADIUS server authenticates a user base on username and password. Normally they look up the username in a database or authenticate against something like LDAP/Active Directory.

What if the RADIUS server instead looked at the username to see if it contained an LNURLw or cashu token and approved or rejected the request based on the result of claiming the payment. The user could even come back with the spent LNURLw or cashu and use that as their username for future interactions.

Buzzwords: Payment instead of identity. Payment as identity. Just in time account creation

CLI DEMO

#install a radius client to debug and test
apt install -y freeradius-utils

#this password is used by the service that wants to authenticate a client
password_to_use_radius_server=tollgate

#we don't really care about the clients password, but for now this needs to be set to tollgate for the demo to work
client_password=tollgate
client_username_reject=PlzSirNeedWifi
radtest ${client_username_reject} ${client_password} radius.dns4sats.xyz 1812 ${password_to_use_radius_server}

This request fails (as expected) because the string "PlzSirNeedWifi" does not look like a string that can be used to claim a payment. It is neither LNURLw or cashu:

Sent Access-Request Id 188 from 0.0.0.0:40145 to 157.173.110.57:1812 length 84 User-Name = "PlzSirNeedWifi" User-Password = "tollgate" NAS-IP-Address = 157.173.110.57 NAS-Port = 1812 Message-Authenticator = 0x00 Cleartext-Password = "tollgate" Received Access-Reject Id 188 from 157.173.110.57:1812 to 157.173.110.57:40145 length 20 (0) -: Expected Access-Accept got Access-Reject

client_username_accept=LNURL1DP68GURN8GHJ7ER9D4HJUMRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9AF5CNTD2939ZAZ4XDA9YUJ5XSE85AZ4FFQ5VT68FPUXYEN2FD6YCU690PQ4QVMD092KX3M02CWEGJK5
radtest ${client_username_accept} ${client_password} radius.dns4sats.xyz 1812 ${password_to_use_radius_server}

This request works because the string is in fact a valid LNURLw that can be used to claim a payment. This demo does not actually try to claim a payment, but it would be trivial to do so.

Sent Access-Request Id 25 from 0.0.0.0:44068 to 157.173.110.57:1812 length 228 User-Name = "LNURL1DP68GURN8GHJ7ER9D4HJUMRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9AF5CNTD2939ZAZ4XDA9YUJ5XSE85AZ4FFQ5VT68FPUXYEN2FD6YCU690PQ4QVMD092KX3M02CWEGJK5" User-Password = "tollgate" NAS-IP-Address = 157.173.110.57 NAS-Port = 1812 Message-Authenticator = 0x00 Cleartext-Password = "tollgate" Received Access-Accept Id 25 from 157.173.110.57:1812 to 157.173.110.57:44068 length 20

DEMO on wireless router (OpenWRT or any other router that supports WPA enterprise

Note that hostapd-mini and wpad-mini don't support WPA enterprise. You will need to opkg remove them and install the full version. Make sure to do this while connected to the router over a cable and not wifi or you will lock yourself out.

You should also be able to use any other non-openwrt access point that supports RADIUS authentification.

OpenWRT settings:

config wifi-iface
    option device 'radio0'
    option mode 'ap'
    option ssid 'TollGateRADIUS'
    option encryption 'wpa2'
    option auth_server 'radius.dns4sats.xyz'
    option auth_port '1812'
    option auth_secret 'tollgate'

Now you should be able to connect to the access point, enter LNURL or cashu as the username and connect to the network.

DEMO: OpenVPN

OpenVPN also supports RADIUS as the auth backend. Just point the OpenVPN server at the RADIUS server and the RADIUS server will approve or reject the connection depending on if it was able to claim the payment

DEMO: 802.1X: Port-Based Network Access Control demo

Many managed switches and routers support 802.1X, including OpenWRT. Computers too (Ubuntu, Windows, OsX)

The implications are that a computer could authenticate to an OpenWRT router or off the shelf managed switch and provide an LNURLw or cashu token as its username. The switch/router would forward the request to the RADIUS server which would claim the payment and notify the switch/router if it should turn the ethernet port on or off. No extra software is required on the computer or switch, all of the payment logic is done my the RADIUS server. It should work using the radius.dns4sats.xyz demo but has not yet been tested

DEMO: Logging in to Windows or Linux computers

Not tested, but should be totally doable. Could be used by a service like hashbang.sh

ssh LNURL1DP68GURN8GHJ7ER9D4HJUMRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9AF5CNTD2939ZAZ4XDA9YUJ5XSE85AZ4FFQ5VT68FPUXYEN2FD6YCU690PQ4QVMD092KX3M02CWEGJK5@somehost.example

There is a project to configure PAM to use a RADIUS server, but this has not been tested yet

DEMO: Accessing a mobile network phone network using cashu/LNURLw

A smart mobile phone operator could look for client devices that provide cashu or LNURLw as their username when trying to connect to the mobile phone data network. Both iOS and Android allow you to specify a username and a password when connecting to the APN. The mobile phone operator could try to claim the username as a payment and then make a decision about how much data to provide.

This is a really big deal when roaming in foreign countries. Normally the roaming Telco provider would have to bill the home Telco provider for X gigabytes of usage. The home provider will likely charge the end user a lot more (sometimes many times more) then what the roaming provider is paid. If the roaming provider instead is able to receive payment directly from the end user, it could make more money then if it bills the home Telco provider. It is also able to collect the payment in realtime (actually up front, before providing service).

Feel free to add more use cases of RADIUS where payment like this could be usefull.

Amperstrand commented 1 hour ago

How to configure the radius server

Full writeup coming real soon (tm), but here are some notes:

This issue implements several configuration updates and enhancements in FreeRADIUS to improve security, add validation, and customize authentication. Below are the diffs explained and organized by file.


Added a universal client configuration for "all_clients" in clients.conf

+client all_clients {
+    ipaddr     = 0.0.0.0/0
+    secret     = tollgate
+    shortname  = all
+}

Changed default EAP type to PEAP in mods-available/eap

-       default_eap_type = md5
+#      default_eap_type = md5
+                default_eap_type = peap
+

Added a new module validate_username in mods-available/validate_username to validate usernames using a shell script

+exec validate_username {
+    wait = yes
+    program = "/usr/local/bin/validate_username.sh %{User-Name}"
+    input_pairs = request
+    output_pairs = reply
+    shell_escape = yes
+}

Added user authorization entries in mods-config/files/authorize

+a   Cleartext-Password := "a"
+
+DEFAULT   Cleartext-Password := "tollgate"
+

Enabled validate_username module by creating a symlink in mods-enabled/validate_username

/etc/freeradius/3.0/mods-available/validate_username

Enabled logging for authentication attempts in radiusd.conf

-   auth = no
+   auth = yes

-   auth_badpass = no
-   auth_goodpass = no
+   auth_badpass = yes
+   auth_goodpass = yes

Integrated validate_username module in sites-available/default for authorization

+    validate_username
+if (validate_username == fail) {
+    reject
+}

Integrated validate_username module in sites-available/inner-tunnel for inner-tunnel authorization

+       validate_username
+if (validate_username == fail) {
+    reject
+}
Amperstrand commented 1 hour ago

And finally, the logic that actually would claim the payment. For now it is not claiming any money, just validating that it looks like a string that might represent an actual payment using grep:

/usr/local/bin/validate_username.sh

USERNAME=${1}

# Ensure USERNAME contains only allowed characters
#if [[ ! "${USERNAME}" =~ ^[a-zA-Z0-9_-]+$ ]]; then
#    exit 1
#fi

#todo: also allow this kind of links: 
#https://demo.lnbits.com/withdraw/api/v1/lnurl/cb/HWgBJw4kjfrPXjWctfxj7M

# Check if USERNAME contains 'cashu' or 'lnurlw'
#if [[ "${USERNAME}" == *"cashu"* ]]; then
if echo "${USERNAME}" | grep -qi "cashu"; then

    # For 'cashu' users
   echo "${USERNAME}" >> /tmp/cashu
    exit 0
#    echo "User-Category := 'cashu_user'"
#    echo "Max-Data-Rate := '30Mbps'"
#elif [[ "${USERNAME}" == *"lnurl"* ]]; then
elif echo "${USERNAME}" | grep -qi "lnurl"; then

    # For 'lnurlw' users
   echo "${USERNAME}" >> /tmp/lnurl
    exit 0
#    echo "User-Category := 'lnurlw_user'"
#    echo "Max-Data-Rate := '20Mbps'"
else
    # Username does not contain 'cashu' or 'lnurlw', reject authentication
    exit 1
fi

# Log the USERNAME to /tmp/log
echo "${USERNAME}" >> /tmp/log

exit 0