Interesting that your question hasn't received many (correct) answers yet!
As you discovered, usual PHP MySQL APIs like mysql_query, mysqli::query etc. only execute the first SQL statement in case one passes several of them (separated by semicolons), as would an attacker using the most common class of SQL injections.
Defender tip: banish mysqli::multi_query and friends from your code; the minute performance improvements are not worth the risk.
Does this clever move by PHP-folk completely close all attack channels on some code that goes like "SELECT yadda yadda" . $_GET["untrusted"]? Not quite. As knittl remarks, even a pure-DQL SELECT can be used to escalate one's privileges by UNION ALL SELECT'ing from any nearby interesting table, including but not limited to the passwords table. There are cheat sheets out there giving enough tips and tricks to basically extract the entire database this way.
Defender tip: apply defense-in-depth with known-good techniques:
- input validation
- whitelist indirection in an associative array
- prepared statements (if you can make sure that they are effective and not just string escaping in disguise!)
- an ORM
- protective encoding (e.g. Base64) when the untrusted input cannot be satisfactorily sanitized (e.g. a blog post that may legitimately contain SQL-sensitive punctuation)
- or as a last resort only, string escaping
Next, one may observe that not all DQL is side-effect free, in particular when it ends with INTO DUMPFILE somethingsomething.
Defender tip: always configure secure_file_priv in your MySQL / MariaDB server.
Last but not least, even an attacker who is in a position to inject arbitrary SQL is limited by the authority granted to the Web app as a whole.
Defender tip: secure your app by applying POLA.
- Only
GRANT the Web app's MySQL user as much authority as it needs. It is not a bad idea to design your app so that it requires no DDL at all. If you must provide a “back up / restore DB” feature or some such from the Web UI, use a separate MySQL user for that.
- Automate backups, even though they are useless — restores are what matters.
JOIN/UNIONanother table and get admin login credentials. Then, with elevated privileges he could do more evil things, e.g. uploading a PHP shell to execute arbitrary commands on the server