You can use a sparse tree search C-c / p custom_id RET <value>. See Sparse Trees in the manual. The sparse tree is (mostly) folded, but top-level headlines that match are highlighted and lower-level headlines that match unfolded up to the headline (you can change the behavior, but I think I am describing the default behavior). So it is easy to find all the matching headlines. You can exit the sparse tree view with C-c C-c.
For example, if I have an Org mode file like this:
* something
wild
* one
:PROPERTIES:
:CUSTOM_ID: foo
:END:
* something
wicked this way comes
* two
** two.one
:PROPERTIES:
:CUSTOM_ID: barfoo
:END:
* something
completely different
* three
** three.one
*** three.one.one
:PROPERTIES:
:CUSTOM_ID: foo
:END:
** three.two
*** three.two.one
and I do C-c / p CUSTOM_ID RET foo, I get this view:

The highlights (on the one headline and the three.one.one headline - note that the red rectangle is my cursor, it is not a highlight) indicate a match, so you can TAB on each one to open it and on the PROPERTIES drawer underneath to verify. Note that all other headlines (in particular the three something headlines) don't match and remain folded and un-highlighted. When you are done, exit the sparse tree view with C-c C-c.
C-c / can yield sparse trees based on different matching criteria: p for properties, r for regexps, m for matching tags and properties (see Matching tags and properties in the manual), and others.
For example, doing C-c / r CUSTOM_ID RET will find all CUSTOM_ID properties (as well as other places mentioning CUSTOM_ID: it just uses it the string CUSTOM_ID as a regexp). This is what that looks like on the example above:

C-c / m can do all sorts of searches but you need to practice: the matching language is somewhat peculiar. You'll probably have to reread the section I linked to above a few times.