Id say the larger vulnerability is that a system command in a set uid executable can be exploited to give root privileges, in various ways.
You are correct that you can spoof libraries. In the case of both Windows and Linux, you dont even need to try that hard to accomplish that. The vulnerability is only valid in the case of a privileged executable.
The fastest way to copy a file in Windows is CopyFile. Using some clever C++ thing cannot compete, even if it uses overlapped I/o, or completion ports.
So there is a case for using platform specific features. But system is a step too far, for all the reasons stated earlier.
The "system()" function is not a security issue, and even if it were at some point then that issue was solved more than ten years ago. Libraries that change as infrequently and are as ubiquitious as the standard C++ libs are trivial to whitelist by hash: http://csrc.nist.gov/publications/drafts/800-167/sp800_167_draft.pdf
So even though I agree in premise with JLBorges that you should presume that the system you are running on is clean; strictly speaking you don't even have to do that. Any competent administrator will have accounted for this before your application ever got there.
Like anything else, it's a design consideration. The function is of limited utility, for example it doesn't return any handles to the process itself, any of its threads, the input or output or anything like that. The parent process has no way of monitoring its child during execution or even reading it's return code without additional work. Also let's not forget, it's a halting operation so if the child gets hung the parent could be there for awhile.
TL;DR: Unless you're writing an AV client; the cleanliness of the host system is not your problem.
system() is a security risk, not because of the interchangeability of the executables at hand but for various other reasons.
To prefix the following explanation, understand that these exploits are only usable for an executable that is presumed to be safe and unmodifiable, something that would be placed in /usr/lib.
1) system() relies on the system shell. The system shell can change depending on the user. In any occasion that a binary with root privileges uses system, you can guarantee that that binary is a surface for a security exploit because of the variable nature of the shell.
2) system() relies on a specific path, similarly to a shell. Your first nature in Linux might be to do system("/usr/bin/ls"). This is part of the exploitation mentioned above but the pathing is variable to how the shell interprets it. It can be changed to a different executable. This might not be that bad but when your program relies on executing /usr/bin/ls which you thought was a safely untouchable binary, you suddenly have problems, especially in the case of daemons.
3) Obviously any user input that is part of the string to system() is open to manipulation. And of course, any time you run system() with a root-privileged executable, it's open to an exploit. exec is also vulnerable to this.
It also has various practical downsides.
1) It relies on a shell being present which may not always be the present in some environments.
2) system() provides no indication of whether or not the new command actually even succeeded (however, POSIX does define this as an extension to C).
3) It's not cross-platform by design.
4) It doesn't handle environment as conveniently as other functions.
And there's probably more I missed. system() *is* a security risk, at least for any system that allows privileged libraries or relies on another executable for uptime. There are better functions that are easier to use.