On-chain randomness on any public, decentralized, and deterministic system like a blockchain is difficult.
BABE pallet does provide a source of on-chain randomness, but it has its own limits for security, especially when it comes to being used to win money on chain.
Here is the security note included in the BABE pallet about it's randomness:
/// # Security
/// This MUST NOT be used for gambling, as it can be influenced by a
/// malicious validator in the short term. It MAY be used in many
/// cryptographic protocols, however, so long as one remembers that this
/// (like everything else on-chain) it is public. For example, it can be
/// used where a number is needed that cannot have been chosen by an
/// adversary, for purposes such as public-coin zero-knowledge proofs.
The way BABE randomness works is that each block producer includes some additional randomness which they can verifiably generate which modifies the current randomness.
This means, to fully control the random value generated, you would need the collusion of all block producers before you, which is extremely unlikely.
However, for the purposes of lottery systems, you don't necessarily need to have every block producer collude to gain an advantage. If the value earned by the lottery is worth more than the value earned by building a block, then you can imagine it would be in the interest of a block producer participating in the lottery to not produce a block where they are not the winner.
And this is where ultimately the security of this randomness value breaks down, and where you need to make your own analysis of attack scenarios to using this randomness.
What we have in Polkadot is good enough for things like candle auctions for choosing parachains, but probably not good enough for the mega-millions lottery system. There is no hard science on exactly where things break down since it is all game-theoretical, but understanding how randomness is generated and can be influenced should give you an impression on where it can and cannot be used.