Fix information leakage by validating the URL scheme
authorAntonio Ospite <ao2@ao2.it>
Sun, 30 Oct 2016 10:34:22 +0000 (11:34 +0100)
committerAntonio Ospite <ao2@ao2.it>
Sun, 30 Oct 2016 10:44:05 +0000 (11:44 +0100)
Validate the scheme to prevent leaking information by abusing the
file:// scheme.

Before this change it was possible to see what files are available on
the system running tweeper.

The script in tests/test_information_leakage.sh shows the problem on
earlier versions.

Here is an execution with tweeper-0.6:

-----------------------------------------------------------------------
URL file://twitter.com//etc/passwd
--> /etc/passwd
    exists

URL file://twitter.com//etc/file_with_an_unlikely_name
... /etc/file_with_an_unlikely_name
    does not exist

Staring a test server

URL file://twitter.com//etc/passwd
--> /etc/passwd on http://localhost:8000
    exists

URL file://twitter.com//etc/file_with_an_unlikely_name
... /etc/file_with_an_unlikely_name on http://localhost:8000
    does not exist

Shutting down the test server
-----------------------------------------------------------------------

Here is an execution after this fix:

-----------------------------------------------------------------------
PHP Fatal error:  unsupported scheme: file in /home/ao2/Proj/Tweeper/tweeper/tweeper.php on line 323
URL file://twitter.com//etc/passwd
... /etc/passwd
    does not exist

PHP Fatal error:  unsupported scheme: file in /home/ao2/Proj/Tweeper/tweeper/tweeper.php on line 323
URL file://twitter.com//etc/file_with_an_unlikely_name
... /etc/file_with_an_unlikely_name
    does not exist

Staring a test server

URL file://twitter.com//etc/passwd
... /etc/passwd on http://localhost:8000
    does not exist

URL file://twitter.com//etc/file_with_an_unlikely_name
... /etc/file_with_an_unlikely_name on http://localhost:8000
    does not exist

Shutting down the test server
-----------------------------------------------------------------------

tests/test_information_leakage.sh [new file with mode: 0755]
tweeper.php

diff --git a/tests/test_information_leakage.sh b/tests/test_information_leakage.sh
new file mode 100755 (executable)
index 0000000..061d917
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+set -e
+
+TWEEPER="/usr/share/php/tweeper/tweeper"
+#TWEEPER="./tweeper"
+
+check_result() {
+  URL="$1"
+  FILE="$2"
+  RESULT="$3"
+
+  echo "URL $URL"
+  if [ "$RESULT" ];
+  then
+    echo "--> $FILE"
+    echo "    exists"
+  else
+    echo "... $FILE"
+    echo "    does not exist"
+  fi
+  echo
+}
+
+file_exists() {
+  FILE="$1"
+  URL="file://twitter.com/$FILE"
+  OUTPUT=$($TWEEPER $URL)
+  check_result "$URL" "$FILE" "$OUTPUT"
+}
+
+file_exists_on_server() {
+  SERVER="$1"
+  FILE="$2"
+  URL="file://twitter.com/$FILE"
+  OUTPUT=$(curl $SERVER/tweeper.php?src_url=$URL 2> /dev/null)
+  check_result "$URL" "$FILE on $SERVER" "$OUTPUT"
+}
+
+file_exists /etc/passwd || true
+file_exists /etc/file_with_an_unlikely_name || true
+
+echo "Staring a test server"
+echo
+
+php -S localhost:8000 -t $(dirname $TWEEPER) > /dev/null 2>&1 &
+SERVER_PID=$!
+sleep 1
+
+file_exists_on_server http://localhost:8000 /etc/passwd || true
+file_exists_on_server http://localhost:8000 /etc/file_with_an_unlikely_name || true
+
+echo "Shutting down the test server"
+kill $SERVER_PID
index 0955a11..87efd60 100644 (file)
@@ -318,6 +318,12 @@ class Tweeper {
       return NULL;
     }
 
+    $scheme = $url["scheme"];
+    if (!in_array($scheme, array("http", "https"))) {
+      trigger_error("unsupported scheme: $scheme", E_USER_ERROR);
+      return NULL;
+    }
+
     // Strip the leading www. to be more forgiving on input URLs.
     $host = preg_replace('/^www\./', '', $url["host"]);