{"id":29403434,"url":"https://github.com/pericles001/reverse_engineering_challenge","last_synced_at":"2025-07-10T18:08:24.905Z","repository":{"id":298543492,"uuid":"997941080","full_name":"Pericles001/Reverse_engineering_challenge","owner":"Pericles001","description":"Repository used to store reverse engineering technical challenge task","archived":false,"fork":false,"pushed_at":"2025-06-11T16:23:13.000Z","size":595,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-11T17:58:00.280Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Pericles001.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2025-06-07T14:26:04.000Z","updated_at":"2025-06-11T16:23:16.000Z","dependencies_parsed_at":"2025-06-11T17:58:06.911Z","dependency_job_id":"2cd5e78d-610f-4902-bd48-08691197f436","html_url":"https://github.com/Pericles001/Reverse_engineering_challenge","commit_stats":null,"previous_names":["pericles001/reverse_engineering_challenge"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Pericles001/Reverse_engineering_challenge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pericles001%2FReverse_engineering_challenge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pericles001%2FReverse_engineering_challenge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pericles001%2FReverse_engineering_challenge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pericles001%2FReverse_engineering_challenge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Pericles001","download_url":"https://codeload.github.com/Pericles001/Reverse_engineering_challenge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pericles001%2FReverse_engineering_challenge/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264628606,"owners_count":23640507,"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":"2025-07-10T18:08:21.406Z","updated_at":"2025-07-10T18:08:24.900Z","avatar_url":"https://github.com/Pericles001.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reverse_engineering_challenge\n\nRepository used to store reverse engineering technical challenge task\n\n## Task Description\n\n- We are trying to reverse engineer a legacy application, given its url and an authentication credential.\n\n- The application is a web application that uses cookies for handling sessions, and has a private API for the resources (users).\n- The goal is to create a typescript project that simulates the requests and responses of the application in the command line.\n- The project should be able to authenticate the user and retrieve the user information from the private API.\n- The project should be able to handle cookies and sessions, and should be able to simulate the requests and responses of the application in the command line.\n\n## Plan Description\n\n- The first step was to analyze the application using a web browser and web inspector tools to verify the requests and responses.\n\n### Application analysis\n\n#### Login page\n\nThe login page presents a form with two fields: username and password.\nSubmitting the form sends a POST request to the server with the credentials.\n\n- Wrong credentials result in an error message: invalid credentials.\n- Correct credentials redirect to the main page, which contains a list of users.\n\nThe http request for the login page is as follows:\n\n![Login page inspected](images/1-login_headers.png)\n\nThis request is the GET request that retrieves the login page. The response contains the HTML of the login page.\n\n![Login page post request](images/3-login_request_parameters.png)\n\nthe request method is POST, and the request parameters are the username and password fields. The response is a redirect to the main page, which contains a list of users.\nA success response is indicated by a 302 status code, which means the request was successful and the user was redirected to the main page.\n\nA simplified diagram illustrates how the login process works.\n\n![login process](images/custom/1-login-process.drawio.png)\n\nThis confirms that the system uses internal API calls and combines it with cookies for getting the results.\n\n#### List of users page\n\n![List of users](images/2-lists_request_initiators.png)\n\nThe redirection to the list of users page is initiated by the successful login request. The list of users page is a GET request that retrieves the list of users from the server.\nHowever, the GET request calls upon a POST request to the private API to retrieve a JSON object containing the list of users.\n\nThe following diagram illustrates how the list of users page works.\n\n![list of users process](images/custom/2-list_users_process.png)\n\n#### User details page\n\nThe authenticated user details page is accessed by clicking on the settings button, which operates a number of internal requests to the private API to retrieve the user information.\n\n![User details](images/4-authenticated_user_request_initiator_headers.png)\n\nThe image above shows the request initiator for the authenticated user details page. The request is a POST request to the private API, which retrieves the user information in JSON format.\nThen the user information is displayed on the page as embedded javascript elements, through the settings..js file.\n\n\n\n![user_details process](images/5-authenticated_user_request_parameters.png)\n\n\nThe image above shows the first request that retrieves the javaScript file that contains the user information. The request is a GET request to the private API, which retrieves the JavaScript file in JSON format.\n\nThe following diagram illustrates how the authenticated user details page works.\n\n![authenticated user details process](images/custom/3-settings_process.drawio.png)\n\n\n\n\n\n### Implementation approach\n\nThe implementation follows these main steps to simulate the application's workflow and interact with its private API as an authenticated user:\n\n1. **Browser Automation for Authentication**\n\n   - The script uses Puppeteer to launch a headless browser and navigate to the application's login page.\n   - It extracts the CSRF nonce token from the login form.\n   - The script fills in the username and password fields and submits the form, just like a real user.\n   - After submission, it waits for the navigation to complete, ensuring the login was successful.\n\n2. **Session and Cookie Handling**\n\n   - Once logged in, the script extracts all session cookies from the browser.\n   - These cookies are stored in a cookie jar and reused for subsequent API requests, mimicking the browser's session management.\n\n3. **Fetching the List of Users**\n\n   - With the authenticated session, the script makes a POST request to the internal `/api/users` endpoint using `node-fetch` and `fetch-cookie` to include the session cookies.\n   - The response is parsed as JSON to retrieve the list of users.\n\n4. **Extracting API Tokens for Private Endpoints**\n\n   - The script navigates to the `/settings/tokens` page to extract hidden authentication tokens required for further API calls.\n   - These tokens are read directly from the page's HTML inputs.\n\n5. **Fetching the Authenticated User (Custom Signed API Call)**\n\n   - To retrieve the current authenticated user's information, the script must replicate a custom API call found in the application's JavaScript file (`settings.fefd531f237bcd266fc9.js`).\n   - This involves generating a POST request to `/api/settings` with a payload that includes authentication tokens, a timestamp, and a signature (`checkcode`) computed using HMAC-SHA1, exactly as the front-end does.\n   - The script implements the same signing logic as in the JS file to ensure the API accepts the request.\n\n6. **Data Aggregation and Output**\n\n   - The script combines the list of users and the current user's information.\n   - The result is saved to a `users.json` file in the project directory.\n\n7. **Error Handling and Cleanup**\n   - The script includes error handling to report issues during any step.\n   - Finally, it closes the browser and cleans up resources.\n\nThis approach ensures the script closely mimics the real application's workflow, including authentication, session management, and secure API communication, by re-implementing the custom logic found in the application's JavaScript for signed API requests.\n\n## Running the code\n\n- We created the typescript project to simulate the requests and responses of the application in the command line.\n\n- The tools used were:\n   - Node.js\n   - TypeScript\n   - fetch Cookie\n   - node fetch\n- The code was written in TypeScript to ensure type safety and better maintainability.\n\n- The platform used cookies for handling sessions, and has a private API for the resources (users)\n\n\n### Steps to run the project\n\nTo run the project, you need to do the following steps:\n\n1- Clone the repository:\n\n```bash\ngit clone https://github.com/Pericles001/Reverse_engineering_challenge.git\n```\n\n2- Navigate to the project directory:\n\n```bash\ncd reverse_engineering_challenge\n```\n\n3- Install the dependencies:\n\n```bash\nnpm install\n```\n\n4- Run the code:\n\n```bash\nnpm run start\n```\n\n- Alternatively, you can format the code using Prettier:\n\n```bash\nnpm run format\n```\n\nFormatting the code will ensure that it adheres to the project's coding standards and improves readability.\n\n- You can also lint the code using ESLint:\n\n```bash\nnpm run lint\n```\n\nUsing ESLint will help you identify and fix potential issues in the code, ensuring it follows best practices and coding standards.\n\n#### Dependencies (In case you need to install them manually)\n\n    ├── @eslint/js@9.28.0\n    ├── @types/node-fetch@2.6.12\n    ├── @types/node@22.15.30\n    ├── @typescript-eslint/eslint-plugin@8.33.1\n    ├── @typescript-eslint/parser@8.33.1\n    ├── eslint@9.28.0\n    ├── fetch-cookie@3.1.0\n    ├── globals@16.2.0\n    ├── node-fetch@3.3.2\n    ├── prettier@3.5.3\n    ├── puppeteer@24.10.0\n    ├── tough-cookie@5.1.2\n    ├── ts-node@10.9.2\n    ├── typescript-eslint@8.33.1\n    └── typescript@5.8.3\n\n## Total time\n\n\nThe total time spent on this project was approximately 4 hours and 40 minutes, including the analysis of the application, implementation of the code, and testing.\n\n![Wakatime stats](images/custom/time1.png)\n\n\n\n![Wakatime stats](images/custom/time2.png)\n\n\n\n[More details on wakatime](https://wakatime.com/@pericles001/projects/qvkefxytsu?start=2025-06-05\u0026end=2025-06-11)\n\n\n\n\n## Quick demo\n\n[Link to demo](https://www.loom.com/share/519325f7dff74114861814c4a2853af8?sid=b2f9dbf6-75b9-41ef-ac31-3220174088cf)\n\n## Author\n\nThe code was written by [Pericles001](github.com/Pericles001).\n\nFeel free to reach out if you have any questions or suggestions.\n\n## License\n\nThis project is licensed under the Apache 2.0 - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpericles001%2Freverse_engineering_challenge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpericles001%2Freverse_engineering_challenge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpericles001%2Freverse_engineering_challenge/lists"}