{"id":21928612,"url":"https://github.com/nuvious/htb-lost-modulus","last_synced_at":"2025-08-20T17:04:59.892Z","repository":{"id":251255524,"uuid":"525971576","full_name":"nuvious/HTB-Lost-Modulus","owner":"nuvious","description":null,"archived":false,"fork":false,"pushed_at":"2024-01-05T17:40:42.000Z","size":5,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-20T08:14:53.921Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nuvious.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-17T22:21:54.000Z","updated_at":"2024-08-01T17:05:19.000Z","dependencies_parsed_at":"2024-08-01T20:26:57.114Z","dependency_job_id":"56ff1a92-b232-46a0-a16c-8a65503b42aa","html_url":"https://github.com/nuvious/HTB-Lost-Modulus","commit_stats":null,"previous_names":["nuvious/htb-lost-modulus"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2FHTB-Lost-Modulus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2FHTB-Lost-Modulus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2FHTB-Lost-Modulus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2FHTB-Lost-Modulus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nuvious","download_url":"https://codeload.github.com/nuvious/HTB-Lost-Modulus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244955006,"owners_count":20537874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T22:27:04.245Z","updated_at":"2025-03-22T12:24:41.342Z","avatar_url":"https://github.com/nuvious.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hack The Box (HTB) - Lost Modulus Attack Walkthrough\n\nThis is a walkthrough and explanation of the [Lost Modulus](\nhttps://app.hackthebox.com/challenges/lost-modulus) challenge on Hack The Box.\n\n## Overview\n\nWe are provided 2 files in this challenge; [output.txt](output.txt):\n\n```bash\n$\u003e cat output.txt\nFlag: 148d328b543aa2ede5d5970c5236af3c13ca9c520a2f53fbeceae9530a35c0b6cedff1fd86c44154c05d75d418e13dea251f77\n```\n\nNOTE: The flag has been changed for this walkthrough so as not to publish the\nactual flag. To get the real flag download the challenge files from\n[Hack the Box](hackthebox.com).\n\nand [challenge.py](challenge.py):\n\n```python\n#!/usr/bin/python3\nfrom Crypto.Util.number import getPrime, long_to_bytes, inverse\nflag = open('flag.txt', 'r').read().strip().encode()\n\nclass RSA:\n    def __init__(self):\n        self.p = getPrime(512)\n        self.q = getPrime(512)\n        self.e = 3\n        self.n = self.p * self.q\n        self.d = inverse(self.e, (self.p-1)*(self.q-1))\n    def encrypt(self, data: bytes) -\u003e bytes:\n        pt = int(data.hex(), 16)\n        ct = pow(pt, self.e, self.n)\n        return long_to_bytes(ct)\n    def decrypt(self, data: bytes) -\u003e bytes:\n        ct = int(data.hex(), 16)\n        pt = pow(ct, self.d, self.n)\n        return long_to_bytes(pt)\n\ndef main():\n    crypto = RSA()\n    print ('Flag:', crypto.encrypt(flag).hex())\n\nif __name__ == '__main__':\n    main()\n```\n\nIn this example code the public and private components aren't saved and the only\noutput is an encrypted message. There's also a small bit-size to the key which\nmay be exploited in a factorization attack but CTF challenges RARELY result to\nlarge keyspace brute force attacks.\n\n## Vulnerability\n\nIf one looks at the parameters one can see that e is a small value; 3. This\nisn't inherently unsafe but we can assume the key size itself except we are\nalso not padding the message we are encrypting. This means by taking the e-th\nroot of the ciphertext may reveal the plaintext. This vulnerability is tracked\nunder the Common Weakness Enumeration\n[CWE-780](https://cwe.mitre.org/data/definitions/780.html).\n\n## Exploit\n\nThis seems like an easy win, however taking the n-th root of an integer\nfunction is not straightforward. One could try:\n\n```python\nfrom Crypto.Util.number import getPrime, long_to_bytes, inverse\nprint(long_to_bytes(int(bytes_to_long(ct)**(1/3))))\n\nb'not_tg\\xc4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n```\n\nBut due to the rounding and truncation that happens in the above operation you\ndon't get the decrypted flag. Instead of doing float/int conversions, let's\ninstead get a function designed to do nth root operations on large integers. I\nfound the below implementation on\n[RIPTutorial](\nhttps://riptutorial.com/python/example/8751/computing-large-integer-roots).\n\n```python\n# Taken from https://riptutorial.com/python/example/8751/computing-large-integer-roots\ndef nth_root(x, n):\n    # Start with some reasonable bounds around the nth root.\n    upper_bound = 1\n    while upper_bound ** n \u003c= x:\n        upper_bound *= 2\n    lower_bound = upper_bound // 2\n    # Keep searching for a better result as long as the bounds make sense.\n    while lower_bound \u003c upper_bound:\n        mid = (lower_bound + upper_bound) // 2\n        mid_nth = mid ** n\n        if lower_bound \u003c mid and mid_nth \u003c x:\n            lower_bound = mid\n        elif upper_bound \u003e mid and mid_nth \u003e x:\n            upper_bound = mid\n        else:\n            # Found perfect nth root.\n            return mid\n    return mid + 1\n```\n\nUsing the above function we can then take the e-th root of the ciphertext and\nwe get the plaintext flag:\n\n```python\nct = bytes.fromhex(\"148d328b543aa2ede5d5970c5236af3c13ca9c520a2f53fbeceae9530a35c0b6cedff1fd86c44154c05d75d418e13dea251f77\")\ne = 3 # From line 9 of challenge.py\nprint(long_to_bytes(nth_root(bytes_to_long(ct), e)))\n\nb'not_the_real_flag'\n```\n\nFull solution is available in the [solution.py](solution.py) file included in\nthis walkthrough. Be sure to run `pip install -r requirements.txt` to install\nthe pycryptodome version used in this solution example.\n\n## Fixing the Vulnerability\n\nThere are several things wrong with this implementation:\n\n- Using non-standard implementations [CWE-327](\n  https://cwe.mitre.org/data/definitions/327.html)\n  - NEVER ROLL YOUR OWN RSA UNLESS YOU KNOW WHAT YOU'RE DOING\n- Small key size [CWE-326](https://cwe.mitre.org/data/definitions/326.html)\n  - Per the National Security Agency (NSA) and its [Commercial National Security\n    Algorithm (CNSA) Suite](\n    https://apps.nsa.gov/iaarchive/prograams/iad-initiatives/cnsa-suite.cfm),\n    the minimum key-length that is recommended is 3072 bits.\n- Not padding the message before encrypting\n\nA correct implementation using the [PKCS1_OAEP](\nhttps://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html) module\nin the [PyCryptodome suite](\nhttps://pycryptodome.readthedocs.io/en/latest/index.html) has been provided\nas secure implementation counter-example to the insecure RSA implementation\ndemonstrated by the challenge in the [challenge_secure.py](challenge_secure.py)\nfile provided in this write-up.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuvious%2Fhtb-lost-modulus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnuvious%2Fhtb-lost-modulus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuvious%2Fhtb-lost-modulus/lists"}