Getting started
Whenever I have a project like this I like to approach it in stages. The first thing I like to do is add an echo to the inside the loop and then run it, to make sure that the loop is giving me what I want.
#! /bin/bash
for (( CON1=10000; CON1<=99999; CON1++ )) ;
do
  echo $CON1
done
Now when I run it I'll use head -5 to just show the first 5 lines it outputs.
$ ./cmd.bash | head -5
10000
10001
10002
10003
10004
OK, so that looks good, check the end like this:
$ ./cmd.bash | tail -5
99995
99996
99997
99998
99999
That looks good too. So now let's figure out some ways we could approach the next step of identifying numbers with 2 digits from the set {4,5,6}. My first instinct here is to go for grep. There are also methods for doing this purely in Bash, but I like to use the various tools, grep, awk, and sed for doing these types of things, mainly because that's how my mind works.
An approach
So how can we greplines that contain 2 digits from the set, {4,5,6}? For this you can use a set notation, that's written like this in regex, [456]. You can also specify how many digits you want to match from this set. That's written like this:
[456]{#}
Where # is a number or range of numbers. If we wanted 3, we'd write [456]{3}. If we wanted 2-5 digits, we'd write [456]{2,5}. If you wanted 3 or more, [456]{3,}`.
So for your scenario it's [456]{2}. To use a regex in grep, your particular version of grep needs to support the -E swtich. This is typically available in most standard grep's.
$ echo "45123" | grep -E "[456]{2}"
45123
Seems to work but if we give it numbers with 3, we start to see an issue:
$ echo "45423" | grep -E "[456]{2}"
45423
That's matching too. This is because grep has not concept of the fact that these are digits in a string. It's dumb. We told it to tell us if the series of characters in our string are from a set and that there are 2 of them and there are 2 digits in the string 45423.
It also fails for these strings:
$ echo "41412" | grep -E "[456]{2}"
$
So is this method usable? It is if we change tactics a bit, but we'll have to rejigger the regex.
Example
$ echo -e "41123\n44123\n44423\n41423" | grep -E "[^456]*([456][^456]*){2}"
44123
44423
41423
The above is presenting 4 types of the strings. The echo -e "41123\n44123\n44423\n41423" just prints 4 of the numbers from our range.
$ echo -e "41123\n44123\n44423\n41423"
41123
44123
44423
41423
How does this regex work? It sets up a regex pattern of zero or more "not [456]" followed by either 1 or more [456] or zero or more "not [456]" characters, looking for 2 occurrences of the latter.
So now we do a little assembly in your script.
for (( CON1=10000; CON1<=99999; CON1++ )) ;
do
  if echo $CON1 | grep -q -E "[^456]*([456][^456]*){2}"; then
      echo $CON1
    fi
done
Using our head & tail trick from above we can see that it's working:
$ ./cmd.bash | head -5
10044
10045
10046
10054
10055
$ ./cmd.bash | tail -5
99955
99956
99964
99965
99966
But this method proves to be dog slow. The problem is that grep. It's expensive, and we're running `grep 1 time, per iteration through the loop, so that's ~80k times!
To improve that we could move our grep command outside the loop and run it 1 time, after the list's been generated, like so, using our original version of the script that just echoed the numbers out:
$ ./cmd.bash | grep -E "[^456]*([456][^456]*){2}"
NOTE: We could drop the for loop entirely and use the command line tool, seq. This will generate the same sequence of numbers, seq 10000 99999.
One liner?
A fancy way to do this would be to use the sequence of numbers from the above command, and then pipe it to the paste command which would insert a + between each number, and then run that output into the command line calculator, bc.
$ ./cmd.bash | grep -E "[^456]*([456][^456]*){2}" | paste -s -d"+"
10044+10045+10046+10054+10055+10056+10064+10065+10066+10144+10145+...
$ ./cmd.bash | grep -E "[^456]*([456][^456]*){2}" | paste -s -d"+" | bc
2409327540
But that's a completely different way to solve this problem, so lets get back to the for loop.
Using pure Bash
So we need some method for testing if a digit has exactly 2 digits within Bash, but isn't as expensive as calling grep 80k times. Modern versions of Bash include the ability to match using the =~ operator, which can do similar matching as grep. Let's take a look at that next.
#!/bin/bash
for (( CON1=10000; CON1<=99999; CON1++ )) ;
  if [[ $CON1 =~ [^456]*([456][^456]*){2} ]]; then
    echo $CON1
  fi
done
Running this looks to do exactly what we want.
$ ./cmd1.bash  | head -5
10044
10045
10046
10054
10055
$ ./cmd1.bash  | tail -5
99955
99956
99964
99965
99966
Checking it shows that it works with 41511 now:
$ ./cmd1.bash | grep 41511
41511
References