Skip to content

Commit

Permalink
Merge pull request #1144 from hackclub/malted-patch-2
Browse files Browse the repository at this point in the history
malted patch 2
  • Loading branch information
malted authored Jan 27, 2025
2 parents 9f883fa + 201c2b4 commit 19a90fe
Showing 1 changed file with 228 additions and 4 deletions.
232 changes: 228 additions & 4 deletions docs/vuln-report.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#DRAFT!

Jan 1 14:42: `@Toshit` informed a member of the High Seas team of a vulnerability privately.
Jan 1 16:31: Locked all Vercel deployments. https://hackclub.slack.com/archives/C07MS92E0J3/p1735767096234219?thread_ts=1735760565.330479&cid=C07MS92E0J3

Expand Down Expand Up @@ -179,13 +181,235 @@ They implemented a preliminary fix, but since the injection was source formula a

So, what actually happened? TL;DR, nothing. We checked our logs and no data was stolen.

The person records contains these fields:
The person records contained these fields at the time the vuln was fixed (this is my real `Person` record):

```
ships, slack_id, autonumber, email, battles, orders, shop_true, address, YSWS Verification User, waka_last_synced_from_db, waka_last_heartbeat, waka_known_machine_count, waka_known_machines, waka_known_installation_count, waka_known_installations, waka_first_heartbeat, zapier_loops_marked_signed_up_at, zapier_loops_marked_wakatime_installed_at, waka_total_hours_logged, has_received_hakatime_install_nudge, contest, last_step_completed, auto_num, tavern_rsvp_status, address_geocode, address_latitude, address_longitude, tavern_map_geocode, taverns_attendee, Manual sort, nearest_tavern_1, nearest_tavern_2, nearest_tavern_3, nearest_tavern_1_distance, nearest_tavern_2_distance, nearest_tavern_3_distance, rsvp_nudge_sent, first_name, last_name, identifier, battles__explanation, agggregated_battle_explanations, record_id, vote_quality_multiplier, vote_count, votes_expended, vote_balance, shipped_ship_count, verification_status, full_name, all_orders_string, academy_completed, preexisting_user, user_has_graduated, country, all_project_repo_urls, battles__uniqueness_enforcement_string, ships_awaiting_vote_requirement_count, ships_with_vote_requirement_met_count, minimum_pending_vote_requirement, vote_balance_minus_minimum_pending_requirement, votes_remaining_for_next_pending_ship, votes_required_for_all_pending_ships, votes_remaining_for_all_pending_ships, unique_vote_count, duplicate_vote_count, unique_vote_explanation_count, aggregated_battle_explanations_length, aggregate_discordance, mean_discordance, all_battle_ship_autonumbers, all_battle_ship_autonumbers_unique, all_battle_ship_autonumber_strings, magic_auth_link, likely_test_user, magic_auth_message, orders_awaiting_mailout, all_order_items, has_ordered_free_stickers, orders__item_name, verified_eligible, verification_alum, orders__items, free_stickers_dupe_check, staged_ships_count, last_activity_time, days_since_last_activity, stale, hours_since_last_activity, sniffable_vote_count, telemetry_vote_count, total_vote_count, duplicate_vote_explanation_count, duplicate_vote_explanation_percentage, duplicate_explanation_trust_factor, mean_vote_time, time_trust_factor, consensus_violation_coefficient, consensus_violation_trust_factor, mean_rating_difference, mean_absolute_rating_difference, accordance_coefficient, accordance_coefficient_trust_factor, voting_trust_factor_sans_clickthrough, voting_trust_factor, verification_updated_at, duplicate_vote_explanation_count_prior_week, mean_consensus_disagreement, consensus_disagreement_coefficient, total_ships, vote_count_prior_week, aggregated_rating_differences, referral_link, impersonation_link, contest__all_slack_ids, order_count_no_free_stickers, paid_out_ship_count, hakatime_has_coded, hakatime_installed, tutorial_ship_count, stage, doubloons_paid, contest__doubloons_per_dollar, dollars_paid, total_real_money_we_spent, amount_earned_vs_fulfillment_cost, count_battles_exact_mention, battles_exact_mention_percentage, slack_profile_url, all_project_demo_urls, total_hours_shipped, average_doubloons_per_hour, created_at, days_since_joining, daily_hours_logged, days_since_first_heartbeat, daily_hours_shipped, days_between_first_and_last_heartbeats, first_heartbeat_modified_at, orders__item_name_list, dollars_fulfilled, doubloons_granted, referral_credit_count, doubloons_received, didn't_complete_tutorial_bc_of_bug, stuck_in_tutorial_generally, ysws_submission_total_submitted_weighted_projects, address__formatted, tavern_map_marker_size, status (from orders), tavern_map_coordinates, Tavern City, slack_profile, location_confirmed, rsvp_partially_complete, nearest_tavern_1_locality, nearest_tavern_2_locality, nearest_tavern_3_locality, nearest_tavern_1_organizer_needed, doubloons_spent, doubloons_balance, settled_tickets
{
identifier: "b_en_d_2005",
ships: [
"recmLrezpPCPfjO8G", "recHRXQc38TAs5yHZ", "rectfb990YVxy6urc",
"rec3owEHeVParhGjW", "recQpF5QN5Nspgzja", "rec9NtPdxbhl5xqdy",
"recSWVXmNgjsm23Wf", "rec1f69CDE4Hvp1tn", "recTylct4Va2Ztj86",
"rec3gve9DyrlnWZqD", "rec3265DhvzbDpDif", "recXeeJFYxAAKlg63",
"recc9NxnEKbd7GkyE", "rec65wdwhJsB0TTDR", "recr9ZU76Ee9nBpcZ",
"rec2S0UkjyPjcG6k0", "recsR9NnlWkiT9BEz", "recbTAUwRTdzeAKG1",
"recMgIFj7Vs9OPg9e", "recK9WCAAbt34XkeZ", "rec8IxLhQSEgAvqPt",
"recHxzMvnl66dDy0J", "recxbJHAnYSTG7ZiF", "recS5U4rhWvMYdH4Z",
"recPa2aRcVN5ra0RG", "recNTgQWQK5B9OIX1", "recLpZqvqvYYPfBXO",
"recrVgPhsvHPzCok6", "recUt8a7KUwRMXYRn", "rec8RHcjAXNWFCC0R",
"reckDUD39FYnVvmpD", "recESG52mL96YseZD", "recevgGBhXwuoHGSR",
"recHlKOv0tVPczopm", "rec83EU35Y85bZK1i", "recfJxbjVtHUN99jF",
"reccNp5ho720Eq6MK", "recZ9SALngkTpd4WM", "recoBsJX3FxfppBcv",
"recyCSyCmiakvugVU", "recJlqLAg0f9ueABn", "recOnaXOepV6LJA0c",
"recAufwu8dbeQtdBg", "recuxj2mC1Sz3CTB0", "recutRTI5uVXS3XCJ",
"recNEUFC9fIGGRVjI", "reczlLVR1urHKrNLj", "recVxW1T89EQW1qhF",
"recbRBlonp95ndqYF", "recKtqeaYMTfcgyq0"
],
slack_id: "U03DFNYGPCN",
first_name: [ "B" ],
last_name: [ "en D" ],
autonumber: 2005,
email: "[email protected]",
full_name: "B en D",
battles: [
"recAIFuzybUFeomdZ", "recnzD9WoBAdbtmqB", "rec4FLz8TnLBSLe5K",
"recUECAnjct2uo3M1", "recgTmcwmXNszON9y", "recrVaSry7BXleQIT",
"rec4prbbrkTCiEaMO", "recxbmkMybpj9xoeU", "recVkvYxVuDVbUrbH",
"rec8iUO3mbu5MP5Mr", "recnwPVd3kyZ6XXDE", "recbO2fXnpHUUY3x4",
"recyoteDNFEy73Sqi", "recKqK8N4vFvNAuqe", "rec6ecsTuK7PTLJV4",
"recSZPXy3vYNgAEX9", "rec4aKH4HV2AH4t4k", "rec7XaBsixE5ayIsV",
"recSg8EnMBeHb3RKK", "recPc3ABjj7op7fiE", "recR2NrK9iNMiNVlp",
"rec2QcE1zKQ37Ejle", "rec5olDy2rvvTBbqS", "recQoZeiq8kIPiVcs",
"recpFsuxA9K7gL6jc", "reccN2VnfZ7ziRvzC", "recJ3BgClbO6Ewnzc"
],
orders: [ "rec6DYYnsPb6NwcXw" ],
settled_tickets: 69,
shop_true: true,
academy_completed: true,
user_has_graduated: true,
preexisting_user: true,
address: [ "recCkFOWIivwt4I4R" ],
doubloons_paid: 69,
doubloons_spent: 0,
doubloons_balance: 69,
doubloons_granted: 0,
created_at: "2024-10-02T16:38:18.000Z",
vote_balance: -11,
shipped_ship_count: 2,
vote_count: 13,
ships_awaiting_vote_requirement_count: 0,
ships_with_vote_requirement_met_count: 2,
votes_expended: 24,
minimum_pending_vote_requirement: 0,
vote_balance_minus_minimum_pending_requirement: -11,
"YSWS Verification User": [ "recjr2NnxJ2bkeK8L" ],
verification_status: [ "Eligible L1" ],
votes_remaining_for_next_pending_ship: 11,
votes_required_for_all_pending_ships: 0,
votes_remaining_for_all_pending_ships: 11,
unique_vote_count: 27,
duplicate_vote_count: -14,
unique_vote_explanation_count: 27,
duplicate_vote_explanation_count: 0,
battles__uniqueness_enforcement_string: [
"U03DFNYGPCN-1824-1849", "U03DFNYGPCN-1811-1857",
"U03DFNYGPCN-1811-1831", "U03DFNYGPCN-1852-1863",
"U03DFNYGPCN-1834-1858", "U03DFNYGPCN-1844-1850",
"U03DFNYGPCN-1870-1899", "U03DFNYGPCN-1980-2026",
"U03DFNYGPCN-1827-2126", "U03DFNYGPCN-2087-2100",
"U03DFNYGPCN-1801-2131", "U03DFNYGPCN-1848-2159",
"U03DFNYGPCN-1916-2148", "U03DFNYGPCN-1916-2380",
"U03DFNYGPCN-1989-2484", "U03DFNYGPCN-1791-2020",
"U03DFNYGPCN-2083-2490", "U03DFNYGPCN-2322-2423",
"U03DFNYGPCN-1881-2080", "U03DFNYGPCN-1880-2139",
"U03DFNYGPCN-1792-2052", "U03DFNYGPCN-1833-1962",
"U03DFNYGPCN-1971-2498", "U03DFNYGPCN-5027-6104",
"U03DFNYGPCN-2364-6146", "U03DFNYGPCN-4795-6149",
"U03DFNYGPCN-6874-8701"
],
agggregated_battle_explanations: "recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUtest test test test test test test test test test test test testrecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUa a a a a a a a a a a a a a a a a a a a arecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI love guessing games! This reminds me of Wordle. I like the simple design too! The gradient adds to it.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUs s s s s. s s. s s. s srecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUWoah, this is an awesome project. I love using HCB. This is a technically impressive project!recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUThis is a super cool project! I think it will be very useful in the real world.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI'm only voting for this project because the other one was abandoned.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI love the huge selection of games on the site! It's great.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI love this game! It seems really fun! I loved playing itrecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI'm voting for this project because I couldn't access the other one due to a signin screenrecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUI love this so much!! It's such a creative websiterecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUCool blog! it's super snappy and I love the webringrecBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUThe Nurikabe puzzle solver is a more logically impressive project - while the other is cool, it just connects APIs, while the Nurikabe puzzle solver is solving a cooler problem I think.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUThis is such a fun project to browse! I absolutely love how it's laid out. I was presented with examples of the question at hand in a very digestible way, plus it didn't feel biased (it wasn't just a yes or a no answer). The other project has no clear CTA or steps, just a GitHub repo you are supposedly meant to trawl through.recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUWhile the other project seems cool, I don't know how to use it since I don't know what a Lewis structure is (I assume it's a chemistry thing). The project I'm voting for is an okay-looking blog, (where one of the posts is referring to the Replit GQL schema I put online I think :))recBOPNwqrd8TIFPUrecBOPNwqrd8TIFPUtest vote test vote test vote test vote test vote test vote recBOPNwqrd8TIFPU",
record_id: "recBOPNwqrd8TIFPU",
aggregated_battle_explanations_length: 3633,
battles__explanation: [
"test test test test test test test test test test test test test",
"a a a a a a a a a a a a a a a a a a a a a",
"I love guessing games! This reminds me of Wordle. I like the simple design too! The gradient adds to it.",
"s s s s s. s s. s s. s s", "Woah, this is an awesome project. I love using HCB. This is a technically impressive project!",
"This is a super cool project! I think it will be very useful in the real world.",
"I'm only voting for this project because the other one was abandoned.",
"I love the huge selection of games on the site! It's great.",
"I love this game! It seems really fun! I loved playing it",
"I'm voting for this project because I couldn't access the other one due to a signin screen",
"I love this so much!! It's such a creative website",
"Cool blog! it's super snappy and I love the webring",
"The Nurikabe puzzle solver is a more logically impressive project - while the other is cool, it just connects APIs, while the Nurikabe puzzle solver is solving a cooler problem I think.",
"This is such a fun project to browse! I absolutely love how it's laid out. I was presented with examples of the question at hand in a very digestible way, plus it didn't feel biased (it wasn't just a yes or a no answer). The other project has no clear CTA or steps, just a GitHub repo you are supposedly meant to trawl through.",
"While the other project seems cool, I don't know how to use it since I don't know what a Lewis structure is (I assume it's a chemistry thing). The project I'm voting for is an okay-looking blog, (where one of the posts is referring to the Replit GQL schema I put online I think :))",
"test vote test vote test vote test vote test vote test vote "
],
aggregate_discordance: 0.1179447524304271,
voting_trust_factor_sans_clickthrough: 0.87573822502845,
mean_discordance: 0.13936768142035244,
eligible_to_vote: true,
verification_alum: [ null ],
waka_last_synced_from_db: "2025-01-27T20:30:48.407Z",
waka_last_heartbeat: "2025-01-25T20:48:53.357Z",
waka_known_machine_count: 2,
waka_known_machines: "[\n \"device.com\"\n]",
waka_30_day_active_machine_count: 1,
waka_30_day_active_machines: "[\n \"device.com\"\n]",
waka_known_installation_count: 3,
waka_known_installations: "[\n \"Macos|Darwin|device.com\",\n \"Vscode|Darwin|\",\n \"Vscode|Darwin|device.com\"\n]",
waka_30_day_active_installation_count: 1,
waka_30_day_active_installations: "[\n \"Vscode|Darwin|device.com\"\n]",
waka_first_heartbeat: "2024-10-29T16:07:53.759Z",
zapier_loops_marked_signed_up_at: "2024-10-23",
zapier_loops_marked_wakatime_installed_at: "2024-10-23",
waka_total_hours_logged: 18.16,
waka_30_day_hours_logged: 6.47,
magic_auth_link: "https://highseas.hackclub.com",
all_battle_ship_autonumbers: [
"1849", "1824", "1811", "1857", "1811", "1831", "1863", "1852", "1834", "1858", "1850", "1844", "1870",
"1899", "2026", "1980", "1827", "2126", "2087", "2100", "1801", "2131", "1848", "2159", "1916", "2148",
"2380", "1916", "2484", "1989", "2020", "1791", "2083", "2490", "2322", "2423", "2080", "1881", "1880",
"2139", "1792", "2052", "1962", "1833", "1971", "2498", "6104", "5027", "2364", "6146", "6149", "4795",
"8701", "6874"
],
all_battle_ship_autonumbers_unique: [
"1849", "1824", "1811", "1857", "1831", "1863", "1852", "1834", "1858", "1850", "1844", "1870", "1899",
"2026", "1980", "1827", "2126", "2087", "2100", "1801", "2131", "1848", "2159", "1916", "2148", "2380",
"2484", "1989", "2020", "1791", "2083", "2490", "2322", "2423", "2080", "1881", "1880", "2139", "1792",
"2052", "1962", "1833", "1971", "2498", "6104", "5027", "2364", "6146", "6149", "4795", "8701", "6874"
],
all_battle_ship_autonumber_strings: [
"18241849", "18111857", "18111831", "18521863", "18341858", "18441850", "18701899", "19802026",
"18272126", "20872100", "18012131", "18482159", "19162148", "19162380", "19892484", "17912020",
"20832490", "23222423", "18812080", "18802139", "17922052", "18331962", "19712498", "50276104",
"23646146", "47956149", "68748701"
],
orders__items: [ "item_free_stickers_41" ],
magic_auth_message: "Welcome to the Hack Club Slack, a vibrant community hosting thousands of teenagers, regular online events, and tons of other Hack Club programs in addition to High Seas!\n\nNow it's time for Step 2, where you'll learn how High Seas works (and get free stickers):\n\n ~1. Join Slack~\n *2. Do the Tutorial* _← you are here_\n 3. Install Hackatime\n\n*<https://highseas.hackclub.com|👉 Click here to start the High Seas tutorial! 👈>*",
orders_awaiting_mailout: [],
orders__item_name: [ "Free Stickers" ],
verified_eligible: true,
all_order_items: [ "item_free_stickers_41" ],
stage: "payout_received",
staged_ships_count: 1,
hakatime_installed: true,
hakatime_has_coded: true,
last_activity_time: "2024-12-20T20:29:22.000Z",
tutorial_ship_count: 3,
hours_since_last_activity: 912,
days_since_last_activity: 38,
mean_rating_difference: 69.58333333333333,
mean_absolute_rating_difference: 170.41666666666666,
accordance_coefficient: 0.4083129584352078,
consensus_violation_coefficient: 0.25,
paid_out_ship_count: 2,
order_count_no_free_stickers: 0,
mean_vote_time: 102.36363636363636,
all_orders_string: "item_free_stickers_41",
sniffable_vote_count: 11,
average_ship_rating: 1075.5,
duplicate_vote_explanation_percentage: 0,
total_vote_count: 27,
country: [ "🇺🇸 United States of America" ],
contest: [ "rec3mojf205woc8Dp" ],
verification_updated_at: "2024-10-27T03:41:59.000Z",
duplicate_vote_explanation_count_prior_week: 0,
mean_consensus_disagreement: 50.416666666666664,
consensus_disagreement_coefficient: 0.6896100599019119,
time_trust_factor: 0.9632295962245,
consensus_violation_trust_factor: 0.9375,
total_ships: 50,
vote_count_prior_week: 0,
duplicate_explanation_trust_factor: 1,
accordance_coefficient_trust_factor: 0.6389937076647999,
vote_quality_multiplier: 1,
aggregated_rating_differences: "-331\n47\n117\n147\n-83\n-158\n-125\n15\n-37\n-25\n-22\n-85\n25\n179\n-86\n-39\n93\n374\n33\n465\n168\n57\n-427\n-139\n70\n1\n70",
last_step_completed: true,
total_real_money_we_spent: 0,
referral_link: "https://ahoy.hack.club/2005",
impersonation_link: {
label: "go undercover!",
url: "http://localhost:3000/api/admin/impersonate/U03DFNYGPCN",
},
dollars_paid: 16.428571428571427,
contest__doubloons_per_dollar: [ 4.2 ],
contest__all_slack_ids: [ "high_seas" ],
referral_credit_count: 0,
amount_earned_vs_fulfillment_cost: 16.428571428571427,
auto_num: 201,
telemetry_vote_count: 1,
"Fraud - Wonderdome Reports": [ "recjqmpQaY6YQK7Ra", "rec6yIb0mRbIwd6tT" ],
count_battles_exact_mention: 0,
battles_exact_mention_percentage: 0,
slack_profile_url: "https://hackclub.slack.com/team/U03DFNYGPCN",
all_project_repo_urls: "https://github.com/hackclub/shadergraph \nhttps://github.com/hackclub/high-seas \nhttps://github.com/malted/cnn-thing ",
all_project_demo_urls: "https://shadergraph.hackclub.dev \nhttps://highseas.hackclub.com \nhttps://highseas.hackclub.com ",
average_doubloons_per_hour: 13.82842509603073,
daily_hours_logged: 0.15498645741345488,
days_since_first_heartbeat: 89.29166666666667,
total_hours_shipped: 4.989722222222222,
daily_hours_shipped: 0.04258476710899856,
days_between_first_and_last_heartbeats: 88.19444444444444,
first_heartbeat_modified_at: "2024-11-26T03:32:48.000Z",
days_since_joining: 117.17152777777778,
voting_trust_factor: 0.87573822502845,
orders__item_name_list: "* Free Stickers",
dollars_fulfilled: 2.6187873699999997,
show_in_leaderboard: true,
doubloons_received: 69,
"didn't_complete_tutorial_bc_of_bug": 0,
stuck_in_tutorial_generally: 0,
}
```

The only data that was accessed using the methods above was Toshit and FoxMoss accessing their own records.
Notably, address data was not available, as it is stored separately. @Toshit said:
> Address data was not directly exposed through getSelfPerson, I was getting values with random letters and numbers
The only data that was accessed using the methods above was Toshit and FoxMoss accessing their own records, along with some team members' records for testing.
Although cccount takeovers could have happened, we checked our logs and no accounts were logged in this way.

The next event we run will have a much stronger focus on security (and won't use Next.js!).
The next event we run will have a much stronger focus on security (and won't use Next.js!) ~

0 comments on commit 19a90fe

Please sign in to comment.