Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTB parser #193

Merged
merged 2 commits into from
Dec 10, 2022
Merged

Add HTB parser #193

merged 2 commits into from
Dec 10, 2022

Conversation

JJ-8
Copy link
Collaborator

@JJ-8 JJ-8 commented Dec 5, 2022

This parses the tasks of the CTF website https://ctf.hackthebox.com/. The tasks can be copied from the network tab. A direct GET-request to the endpoint does not work, since the endpoint requires authentication with a bearer token in the Authorization header.

The number to category mapping seems to be static and comes from the https://ctf.hackthebox.com/api/public/challengeCategories endpoint, which is publicly accessible.

This parser also imports the challenge description. To allow this, the ParsedTask type is modified to include an optional description field. The object passed to createTask is also implicit, to include the description in the object.

This commit also includes small code refactoring:

  • The ParsedTask type is not duplicated anymore, but imported from parsers/index.ts.
  • Because of this, the keep field is also added to fix typing in TaskImportDialog.vue.
  • The dialog now only hides when the importing is fully finished to prevent confusion with an empty screen after importing (due to delay of importing). The button displays the loading progress.

To test this parser, you can copy the following data from the HTB University CTF 2022:

{"id":696,"name":"HTB University CTF 2022 : Supernatural Hacks","org_name":"HackTheBox","starts_at":"2022-12-02T13:00:00.000000Z","ends_at":"2022-12-04T19:00:00.000000Z","status":"Ongoing","logo":null,"hide_scoreboard":0,"custom_image":0,"certificate_info":null,"participating_team":{"id":0,"name":"REDACTED","participating_members":1,"country_code":"REDACTED","motto":null,"avatar":"REDACTED","points":0,"solved_challenges":0,"total_challenges":20,"owned_flags":0,"total_flags":0,"rank":0,"vpn_server":"REDACTED","isCaptain":false},"hasVPN":1,"hasPwnbox":false,"datadog":0,"light_mode":1,"challenges":[{"id":16529,"name":"EdgeRunner","creator":"makelaris","description":"Dark Pointy Hats took over Poltergeist Research Organisation, restricted all their access, and altered data. Can you take back Poltergeist Research?","challenge_category_id":1,"difficulty":"medium","filename":"","hasDocker":null,"docker_online":null,"docker_ports":null,"points":1100,"solves":8,"flag_hint":null,"hostname":null,"new":0,"hasMachine":1,"type":1,"machine":{"status":"active","ip":"10.129.230.108","expires_at":"2022-12-05T10:48:25.000000Z"},"solved":null,"team_solves":[]},{"id":16532,"name":"Enchanted","creator":"makelaris","description":"N\/A","challenge_category_id":20,"difficulty":"easy","filename":"","hasDocker":null,"docker_online":null,"docker_ports":null,"points":350,"solves":41,"flag_hint":null,"hostname":null,"new":0,"hasMachine":1,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16535,"name":"Wand Permit","creator":"makelaris","description":"You are a big boy magician now, it's time to get your magic wand permit but the wand permit service has closed registration for some weird reason. Can you find a way to get your permit?","challenge_category_id":1,"difficulty":"easy","filename":"","hasDocker":null,"docker_online":null,"docker_ports":null,"points":725,"solves":27,"flag_hint":null,"hostname":null,"new":0,"hasMachine":1,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16538,"name":"Spellbook","creator":"makelaris","description":"In this magic school, there are some spellbound books given to young wizards where they can create and store the spells they learn throughout the years. Some forbidden spells can cause serious damage to other wizards and are not allowed. Beware what you write inside this book. Have fun if you are a true wizard, after all..","challenge_category_id":3,"difficulty":"medium","filename":"pwn_spellbook.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":350,"solves":48,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16541,"name":"Sacred Scrolls","creator":"makelaris","description":"Each house on the campus has its secret library to store spells or spellbound messages so the others cannot see them. Messages are encrypted and must be signed by the boy who lived, turning them into sacred scrolls, otherwise, they are not accepted in this library. You can try it yourself as long as you are a wizard of this house.","challenge_category_id":3,"difficulty":"easy","filename":"pwn_sacred_scrolls.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":325,"solves":104,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16544,"name":"Side Spell","creator":"makelaris","description":"Many young people want to be invited to the Wizards Hacking School. Unfortunately, not all of them are capable of doing so. However, a small number of candidates try to hack their way into the school. Our registration department has been a target of many phishing campaigns by candidates and mercenaries. The latter has been running a black market of invitations, where each candidate can buy an invitation for a specific amount. They finally managed to get access to our internal network. Can you investigate what happened before they moved laterally to the rest of the network?\r\n","challenge_category_id":7,"difficulty":"hard","filename":"","hasDocker":null,"docker_online":null,"docker_ports":null,"points":500,"solves":10,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16547,"name":"One of us","creator":"makelaris","description":"Dark Pointy Hats are causing trouble again. This time, they have targeted Invisible Shields and the protectors of the forbidden spells. They developed a specific spyware that aims to get access to the forbidden spells server. We managed to retrieve a sample of the spyware and suspicious mail that seems to be produced by the spyware. Can you analyze the provided files and find out what happened?","challenge_category_id":7,"difficulty":"medium","filename":"forensics_one_of_us.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":350,"solves":48,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16550,"name":"Fake News","creator":"makelaris","description":"The Magic Informer is our school's newspaper. Our system administrator and teacher, Nick, maintain it. But according to him, his credentials leaked while sharing his screen to present on a course. It is believed that Dark Pointy Hats got access to the Magic Informer, which they use to host their phishing campaign for freshmen people. Given the root folder of the Magic Informer, can you investigate what happened?","challenge_category_id":7,"difficulty":"easy","filename":"forensics_fake_news.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":300,"solves":211,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16553,"name":"The Magic Informer","creator":"makelaris","description":"The Magic Informer is the only byte-sized wizarding newspaper that brings the best magical news to you at your fingertips! Due to popular demand and bold headlines, we are often targeted by wizards and hackers alike. We need you to pentest our news portal and see if you can gain access to our server.","challenge_category_id":2,"difficulty":"easy","filename":"","hasDocker":1,"docker_online":null,"docker_ports":null,"points":300,"solves":177,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16556,"name":"Spell Weaving Exam","creator":"makelaris","description":"Turn your spellbooks over now - the final exam has begun! Under the watchful eye of a strict adjuducator, you must answer each question perfectly.","challenge_category_id":5,"difficulty":"hard","filename":"rev_spellweavingexam.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":450,"solves":13,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16559,"name":"Curse Breaker","creator":"makelaris","description":"A dark wizard placed a curse on you - if you open your mouth to say anything, it'll strike! Only by perfectly reciting the counter-spell can you escape...","challenge_category_id":5,"difficulty":"medium","filename":"rev_cursebreaker.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":325,"solves":81,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16562,"name":"Potion Master","creator":"makelaris","description":"After adding the curried eel, your potion is almost complete, your cauldron boiling over. All you need to do now is incant the final spell to finish your masterwork!","challenge_category_id":5,"difficulty":"easy","filename":"rev_potionmaster.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":300,"solves":176,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16565,"name":"Wizard's Diary","creator":"makelaris","description":"Our lovely University of Magicians created this application for its students, and its purpose is to help organize lecture notes with relative ease. This is the beta version of the app, but we trust the elder wizard so much that we already have it running.","challenge_category_id":3,"difficulty":"hard","filename":"pwn_wizards_diary.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":725,"solves":5,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16568,"name":"AbraCryptabra","creator":"makelaris","description":"Your secret crush, Alex, has been captured and possessed by Voldemart. On your days-long search for her, you finally reach a secret chamber. Before you lies her paralysed body. She seems to be under a spell. A loud, crashing sound is heard from a distance. Something big is coming towards you. It's the Basilisk! Magic doesn't seem to affect it. Your only weapon is the Sword of Gryffindar, which has materialised from the Sorting Hat. Can you defeat the Basilisk and free your love?","challenge_category_id":4,"difficulty":"hard","filename":"crypto_abracryptabra.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":375,"solves":25,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16571,"name":"AESWCM","creator":"makelaris","description":"Few people on this planet studied wandlore. It was known that the wand selects the wizard, but a good wand seller should be able to guess it with at most 3 suggestions. During the 190th Great Wizard Examination, the last question was created by Olivender, the greatest wand seller of all time. It was considered one of the most difficult questions of the last decade. Can you solve it?","challenge_category_id":4,"difficulty":"medium","filename":"crypto_aeswmc.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":325,"solves":101,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16574,"name":"Bank-er-smith","creator":"makelaris","description":"You used the invisibility cloak to enter the bank and spy on the employees. They seem to be using magic to automate the paperwork. As you watched the papers flying around, you managed to steal one of them. It contains details about the vault containing the Golden Grail with Valdemort's soul. After regrouping with Ermiani and Ran, you drank the transformation poison and entered the bank as one of the employees. The passphrase for the vault is encrypted, and the only thing you can ask the bank for is a small hint that seems to be magic-proof.","challenge_category_id":4,"difficulty":"easy","filename":"crypto_bank-er-smith.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":325,"solves":136,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16577,"name":"Spell Orsterra","creator":"makelaris","description":"The wizards of the enemy land have cast binding spells on high-profile individuals in the land of Orsterra to track their movements in real-time. The council of Orsterra is seeking your help in neutralizing the casted spells and taking down their magical spell cast service. The talented scout wizards have tracked down the source of this tracking service. Please take a look and see if you can compromise the server.","challenge_category_id":2,"difficulty":"hard","filename":"web_spell_orsterra.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":1000,"solves":2,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16580,"name":"BatchCraft Potions","creator":"makelaris","description":"An underground potions shop has been selling potions to one of the wizard houses that helps them cheat on the annual magical contest of the houses. The potion shop has a vendor program, and we managed to steal the credentials \"<b>vendor53:PotionsFTW!<\/b>\" by casting a spy spell on one of the shop vendors. Unfortunately, the shop requires two-factor authentication, so we need you to break into the vendor account and uncover who is running this shop.","challenge_category_id":2,"difficulty":"medium","filename":"web_batchcraft_potions.zip","hasDocker":1,"docker_online":1,"docker_ports":[30037],"points":425,"solves":18,"flag_hint":null,"hostname":"206.189.118.55","new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16586,"name":"Death's Glance","creator":"makelaris","description":"You find yourself in possession of an ancient forbidden spell. Rumors have it that by revealing the rune originated from the spell, the mystery behind how you perish will be unveiled.","challenge_category_id":8,"difficulty":"medium","filename":"ml_deaths_glance.zip","hasDocker":null,"docker_online":null,"docker_ports":null,"points":650,"solves":6,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]},{"id":16589,"name":"Sacred Scrolls' Revenge","creator":"makelaris","description":"Each house on the campus has its secret library to store spells or spellbound messages so the others cannot see them. Messages are encrypted and must be signed by the boy who lived, turning them into sacred scrolls otherwise they are not accepted in this library. You can try it yourself as long as you are a wizard of this house.","challenge_category_id":3,"difficulty":"easy","filename":"pwn_sacred_scrolls_revenge.zip","hasDocker":1,"docker_online":null,"docker_ports":null,"points":325,"solves":61,"flag_hint":null,"hostname":null,"new":0,"hasMachine":null,"type":1,"machine":null,"solved":null,"team_solves":[]}],"canAddTeams":false}

This parses the tasks of the CTF website https://ctf.hackthebox.com/
The tasks can be copied from the network tab. A direct GET-request to the
endpoint does not work, since the endpoint requires authentication with
a bearer token in the Authorization header.

The number to category mapping seems to be static and comes from the
https://ctf.hackthebox.com/api/public/challengeCategories endpoint, which
is publicly accessible.

This parser also imports the challenge description. To allow this, the
`ParsedTask` type is modified to include an optional `description` field.
The object passed to `createTask` is also implicit,
to include the description in the object.

This commit also includes small code refactoring:
- The `ParsedTask` type is not duplicated anymore,
but imported from `parsers/index.ts`.
- Because of this, the `keep` field is also added to fix typing in `TaskImportDialog.vue`.
- The dialog now only hides when the importing is fully finished
to prevent confusion with an empty screen after importing (due to delay of importing).
The button displays the loading progress.
@JJ-8 JJ-8 requested a review from XeR December 5, 2022 09:08
Copy link
Contributor

@XeR XeR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR !

Looks like isValid is broken and the parser will try to hijack everything you paste in.

Here is a light ctfd json I've been using to make my tests for a while if you need one :

{"data": [{"category": "recon", "name": "Welcome", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 17, "value": 100}, {"category": "web", "name": "CaaS", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 8, "value": 132}, {"category": "rev", "name": "Simple Encryption", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 16, "value": 340}, {"category": "ppc", "name": "Warmup ROX", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 14, "value": 454}, {"category": "web", "name": "URL to PDF", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 10, "value": 458}, {"category": "misc", "name": "Miscrypto Alphabet", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 4, "value": 479}, {"category": "ppc", "name": "Dungeon Escape", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 12, "value": 489}, {"category": "web", "name": "XTrader", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 15, "value": 491}, {"category": "misc", "name": "Against the Perfect discord Inquisitor 1", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 1, "value": 496}, {"category": "pwn", "name": "FireHTTPD", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 6, "value": 498}, {"category": "misc", "name": "Mineflag Return", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 21, "value": 498}, {"category": "ppc", "name": "Gamod", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 13, "value": 499}, {"category": "misc", "name": "Against the Perfect discord Inquisitor 2", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 2, "value": 500}, {"category": "misc", "name": "Listening to the flag", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 3, "value": 500}, {"category": "rev", "name": "Cars", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 5, "value": 500}, {"category": "web", "name": "wfPM", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 11, "value": 500}, {"category": "crypto", "name": "Conora Secret", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 18, "value": 500}, {"category": "pwn", "name": "The Return of the Side Effect", "template": "/plugins/dynamic_challenges/assets/view.html", "tags": [], "script": "/plugins/dynamic_challenges/assets/view.js", "type": "dynamic", "id": 19, "value": 500}], "success": true}

front/src/ctfnote/parsers/htb.ts Outdated Show resolved Hide resolved
@JJ-8 JJ-8 requested a review from XeR December 10, 2022 15:06
@XeR XeR mentioned this pull request Dec 10, 2022
3 tasks
@XeR XeR merged commit fb06639 into TFNS:main Dec 10, 2022
@JJ-8 JJ-8 deleted the 0-htb-parser branch June 17, 2023 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants