From 9d13138a5fc9fb112345c41769f7cb137472e7dc Mon Sep 17 00:00:00 2001 From: Matthias Prader Date: Tue, 22 Oct 2019 14:29:30 +0000 Subject: [PATCH] Add writeup seccon19 --- writeups/matthias/seccon19.md | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 writeups/matthias/seccon19.md diff --git a/writeups/matthias/seccon19.md b/writeups/matthias/seccon19.md new file mode 100644 index 0000000..9b9f2ef --- /dev/null +++ b/writeups/matthias/seccon19.md @@ -0,0 +1,97 @@ +## The CTF in retrospective +--- +It was the first time I saw a Jeopardy CTF so I can't compare it with others. However I think it was fun and challenging. Just like I immagined it. I tired to pick challenges that contained something somehow familiar. +I wasn't successful in solving them and I am impressed of how satisfying it is to look at others solutions afterwards and understand what I did not think of. + +## Option-Cmd-U (not solved) +--- +The first thing I did was letting the Browser show me the HTML document. There I found the comments that describe how the challenge works. +```html + + + +``` +`/index.php?action=source` then revealed the PHP code: + +```php +if (isset($_GET['url'])){ + $url = filter_input(INPUT_GET, 'url'); + $parsed_url = parse_url($url); + if($parsed_url["scheme"] !== "http"){ + // only http: should be allowed. + echo 'URL should start with http!'; + } else if (gethostbyname(idn_to_ascii($parsed_url["host"], 0, INTL_IDNA_VARIANT_UTS46)) === gethostbyname("nginx")) { + // local access to nginx from php-fpm should be blocked. + echo 'Oops, are you a robot or an attacker?'; + } else { + // file_get_contents needs idn_to_ascii(): https://stackoverflow.com/questions/40663425/ + highlight_string(file_get_contents(idn_to_ascii($url, 0, INTL_IDNA_VARIANT_UTS46), + false, + stream_context_create(array( + 'http' => array( + 'follow_location' => false, + 'timeout' => 2 + ) + )))); + } +} +``` +` filter_input(INPUT_GET, 'url')` according to the documentation does noting: "Do nothing, optionally strip or encode special characters." +` parse_url($url)` parses the url into an associative array. The array then contains the parts of the url (scheme, host, port, user, pass, etc). +`idn_to_ascii` converts a unicode domain into an ascii domain. +The PHP code checks if the entered URL has the scheme `http`. If this is the case, it checks if the ip of the host in the url is the same as the ip of `nginx`. The host `nginx` is available in the docker network for the inter container communication. + +Then I tried to access `flag.php`. I got an error message containing my ip. So i copied the link into the input filed of the index.php and it showed the same error message but with the ip `172.25.0.1`. I tried to enter `http://127.0.0.1:10000/flag.php`. That returned an error "Connection refused". So it can't be the ip of the nginx server. Therefore php-fpm and nginx must run in different containers. A look at the /docker-compose.yml confirmed this. So its the ip of the php-fpm container in the docker network. By trying to enter `http://172.25.0.2/flag.php` and `http://172.25.0.3/flag.php` I found out that the ip of the nginx container is `172.25.0.3` (because it shows "Oops, are you a robot or an attacker?") + +By looking closer at the PHP code I saw, that the `if` that was preventing me from accessing the `flag.php` uses `$parsed_url["host"]` while the method I would want to invoke uses `$url`. According to the PHP documentation `parse_url($url)` will replace invalid characters with `_`. So if I find a character that is invalid for `parse_url` but not for `ind_to_ascii` or I will find a url form that causes `parse_url` to choose a wrong host i could acces the flag. +I've set up a small test setup to be able to test the different urls and see which method returned what. The best I got was a `#` or a whitespace in the url but that caused the schema to be non http. [Maybe I am about three years to late.](https://bugs.php.net/bug.php?id=73192) + +While I was trying somebody of our team solved the challenge and I did not continue. + +## Sandstorm (not solved) +--- +![sandstorm.png](https://gitlab.w0y.at/ctf-seminar/ws19/raw/master/writeups/matthias/seccon2019/sandstorm.png) + +What I tried: +- check if the Image contains any `exif` information +- `Stegsolve.jar` to see if something is written on the image +- `string` to check if there is a valid string in the image file that could be the flag + +Nothing was helpful. +Then I converted the image into a txt containing the rgb color values: `convert sandstorm.png :-txt `. I found out, that there are 2202 pixels which are not black or white. So I turned the black pixels into white ones and generated a new image: +![newimage.png](https://gitlab.w0y.at/ctf-seminar/ws19/raw/master/writeups/matthias/seccon2019/newimage.png) + +So not helpful too. +I saw that the pixels that are not black or white contained three times the same value followed by FF (e.g. F6F6F6FF). So I tried to take the first value of every pixel, treat it as binary combine them in an array and turn it into a string. +```java +public static void main(String[] args) throws IOException { + File f = new File(PATH_TO_TEXT_FILE_REPRESENTING_THE_IMAGE_WITHOUT_BLACK_AND_WHITE_PIXELS); + BufferedReader bufferedReader = new BufferedReader(new FileReader(f)); + String s = ""; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + while((s = bufferedReader.readLine()) != null) { + int pos = s.indexOf("#"); + s = s.substring(pos+1,pos+3); + byteArrayOutputStream.write(hexToByte(s)); + } + System.out.println(new String(byteArrayOutputStream.toByteArray(),"UTF-8")); +} + +public static byte hexToByte(String hexString) { + int firstDigit = toDigit(hexString.charAt(0)); + int secondDigit = toDigit(hexString.charAt(1)); + return (byte) ((firstDigit << 4) + secondDigit); +} + +private static int toDigit(char hexChar) { + int digit = Character.digit(hexChar, 16); + if (digit == -1) { + throw new IllegalArgumentException( + "Invalid Hexadecimal Character: " + hexChar); + } + return digit; +} +``` +But without luck. At this point i had no more ideas of how to get a flag out of the image and I surrendered. + + -- 2.43.0