The `.*` is greedy first -- it's matching `foo 6`. The only reason it stops there is because matching any further would stop the whole pattern from matching, so it leaves the `5` for the `([0-9]+)`. If you made it `([0-9]*)` instead the `.*` would match the whole line and you'd get nothing in your group. One way around it is to tell the first part not to match numbers:
$ echo "foo 65 bar" | sed -n -e 's/[^0-9]*\([0-9]\+\).*/\1/p'
65