cryptic-game/frontend

Bruteforce attack dosen't work (Angular 13)

Closed this issue · 10 comments

Describe the bug
The bruteforce attack cannot be performed

Reproduce

Screenshot 2022-03-13 181053

Screenshot 2022-03-13 213908

There is also a bigger problem here. The bruteforce command triggers a request to /bruteforce/status (before actually trying to initialize the attack via /bruteforce/attack) which returns in your case something like this:

{
  "data": {
    "error": "attack_not_running"
  }, 
  "tag": "..."
}

The frontend tries to catch errors directly and pass them into the subscription error.
But the websocket-service is just expecting errors stored on a higher level inside the payload.
Such as:

{
  "data": {"...": "..."},
  "error": "attack_not_running",
  "tag": "..."
}

Its totally inconsistent and just not well defined - which leads to a bigger problem at this point.
Also interesting is the fact that terminal-state.ts consists of 1700 loc.

Because no error was passed to the subscription, the status subscription triggers the normal behavior which tries to print out the target_device using promptAppender (see line 1159) which is undefined or to be more precise the key is just missing.
The real bug occurs inside the handleMessage function in websocket.service.ts (starting at line 184) or inside the microservice implementing this endpoint - not sure because of the missing provision of documentation here.

Also some players seem to not having the problem. I think its just a (in this case positive) side-effect of the very strong caching-strategy (sw and maybe http-middleware) used in production.

With the following change brute force attacks work for me:

diff --git a/src/app/websocket.service.ts b/src/app/websocket.service.ts
index 1f7cd11..4668021 100644
--- a/src/app/websocket.service.ts
+++ b/src/app/websocket.service.ts
@@ -194,8 +194,8 @@ export class WebsocketService {
 
       if (this.open[tag] != null) {
 
-        if (message['error']) {
-          this.open[tag].error(new Error(message['error']));
+        if (message['data']['error']) {
+          this.open[tag].error(new Error(message['data']['error']));
         } else {
           this.open[tag].next(message['data']);
         }

I don't know why that works, but this might help someone else to further pinpoint and fix the issue.
Also i currently do not have time to further test it.

Referring to the wiki (German: https://wiki.cryptic-game.net/books/einf%C3%BChrungen/page/websocket-api-endpunkte), the frontend does everything correctly when trying to catch errors on the first level.
An answer should be structured as followed:

{
 "status": {
   "code": 200,
   "name": "OK"
 },
 "error": "<message>", // optional
 "tag": "some_tag",
 "data": {
   "id": "fd973bf5-3801-402f-8c85-d5313aa02baa",
   "user_id": "2cea82a0-3425-4d0e-8e1b-4823ad744162"
 }
}

Thus, there must be an error in the creation of the WS-Answer. @cryptic-game/java

As use-to already mentioned, please provide a broader set of endpoint examples and more documentation. @cryptic-game/backend

The Wiki of an open-source multiplayer hacking browser game.

@Tristan-H11 thats the old v3 documentation.
But the v2 documentation says the same about errors: https://github.com/cryptic-game/server/wiki/API-Reference#contact-microservice
https://github.com/cryptic-game/cryptic-service/wiki/API-Reference-%5Bexperimental%5D#bruteforce-service

GitHub
official game-server of cryptic-game. Contribute to cryptic-game/server development by creating an account on GitHub.
GitHub
The offical service microservice of Cryptic. Contribute to cryptic-game/cryptic-service development by creating an account on GitHub.

Oh. Did not know where to find this documentation. Is there a place, where all these different wikis are linked? @MarcelCoding

If I'm understanding this correctly, that's a backend error, right?

It looks like.

Because of the check in

} else if (message['error'] != null) {
and the return if that check passes, just putting the error message on the top level won't work.

In general that line and

if (message['error']) {
both check for message['error'], and if error is not null, it will never reach the second one.

That means no matter what the backend does, the bruteforce attack will only work if something in the frontend changes.

Maybe the check in line 188 shouldn't be there. But I don't know where the documentation about how it should work is.

fixed by #355