You could use FactorInteger
to find out whether or not there are exactly two primes building up a number:
SemiPrimeQ[n_Integer] := With[{factors = FactorInteger[n]},
Total[factors[[All, 2]]] == 2
]
The rest is easy:
Select[Range[50], SemiPrimeQ]
(* {4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49} *)
And for those who like inline anonymous functions
Select[Range[50], Total[Last /@ FactorInteger[#]] == 2 &]
(* {4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49} *)
Update
If you want to create all semi primes which consist of primes smaller than the n-th prime, then this is a one-liner too. Here are all semi primes for the first 10 prime numbers:
Union[Times @@@ Tuples[Array[Prime, 10], 2]]
(* {4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, \
46, 49, 51, 55, 57, 58, 65, 69, 77, 85, 87, 91, 95, 115, 119, 121, \
133, 143, 145, 161, 169, 187, 203, 209, 221, 247, 253, 289, 299, 319, \
323, 361, 377, 391, 437, 493, 529, 551, 667, 841} *)