In a large Dutch oven or pot, add the water, beef shanks, garlic, bay leaves, and salt. Bring to a boil, cover, reduce heat to a low simmer, and cook for 1 ½ to 2 hours, until the meat is tender.
Skim off and discard any white or brown foam floating at the top of the pot as well as the bay leaves and garlic cloves. Transfer the cooked bone-in beef shank to a bowl and set aside to cool slightly.
Add the carrots, corn, potatoes, zucchini, cabbage, cilantro, and tomato paste to the pot. Stir until the tomato paste has fully dissolved. Bring the soup to a boil, reduce heat to a low simmer, and cook for 15-20 minutes, until all the vegetables are tender and cooked through.
While the vegetables are cooking, remove the bones and any tough sinewy pieces from the beef shank and discard. Cut the tender meat into small bite-sized chunks and add them back into the pot when the vegetables are fully cooked.
Stir everything together and taste. Season with more salt if necessary.
Serve soup in large bowls, making sure that each bowl gets a little bit of everything. Top each bowl with more fresh cilantro, freshly squeezed lime juice, and a few dashes of hot sauce if desired.
Notes
For easier serving, remove the cooked corn from the soup, cut off the kernels and add them back into the soup. Discard the cobs.
Feel free to use any vegetables you have on hand! Green beans, peas, peppers, and anything you've got in the fridge will work.
If you can't find bone-in beef shank, you can use bone-in beef chuck or ribs since they both have good ratios of fat. Make sure you use a cut of beef with bone because that's what give the broth a wonderful flavor!