2019-02-16 16:31 阅读 64


edit - this shouldn't be marked as a duplicate. The question isn't how to prevent SQL injection attacks (I'm already using prepared statements elsewhere), it's related to why MySQL is killing a maliciously-injected query.

I'm testing out a web app with a connected MySQL database, specifically looking for potential SQL injection concerns and wondering how to prevent such attacks in this specific case.

One page loads a person's information from the database based on a unique ID number, which is visible through the page's URL. Obviously, this is a concern in its own right - I could simply change the ID from "?id=2" to "?id=3" to load a new record from the database - but the issue I'm more concerned with at the moment is a URL-based attack to execute a "bad" query on top of the intended query.

The intended query looks something like this: ... where person.ID="10" and person.ID = notes.ID and ...

By changing the URL, I'm able to close the parameter that's looking for an ID and execute another, potentially malicious query, like this:

... ?id=10"; drop table person; select * from notes where ID=" ... 

which would cause the following queries to be executed:

... select * from person, notes where id="10"; drop table person; select * from notes where ID="" and ...

I've been able to get this malicious set of queries to print (echo) to my webpage, so I know it's a vulnerability. However, when I try to execute this exact query in MySQL, it hangs for several seconds before exiting MySQL completely with the response "Killed" and no further explanation.

My question, then, is what's causing MySQL to kill this malicious query and exit? This seems like a security feature, but I don't know what it'd be - those queries are perfectly fine on their own. I'm also confused by the lack of error message beyond "Killed" if anyone has come across a similar situation.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    dongpiao9078 dongpiao9078 2019-02-16 22:01

    The only protection MySQL has against the case you show is that by default, MySQL's query interface doesn't execute multiple statements. Separating statements by ; will only result in a syntax error.

    However, multi-query is an option, and depending on the client, the option may have been enabled.

    PDO enables multi-query by default. I can run the following and it will insert two rows:

    $pdo->query("insert into foo set id = 1; insert into foo set id = 2");

    However, if you try to use prepared statements (disabling emulated prepare), it fails:

    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $stmt = $pdo->prepare("insert into foo set id = ?; insert into foo set id = ?");

    This throws an exception if you enabled exceptions:

    PHP Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into foo set id = ?' at line 1

    Mysqli enables multi-query only for queries you execute with the mysqli_multi_query() function. So if you don't use multi_query() in your code, you're safe.

    Furthermore, if you do use query parameters (I saw your comment that you do use query parameters), you're also safe, because even if the parameter were to contain any attempt to fool the query, it won't work.

    Parameters are not simply concatenated into the SQL query when you use prepared statements. This is a misunderstanding many developers have.

    Parameters are kept separate from the SQL syntax until after the SQL is parsed. Then the parameter is combined as MySQL executes the query, but it's too late for any attempted SQL injection to modify the way the query will be parsed.

    That's why query parameters are a good method of protecting your app from SQL injection.

    点赞 评论 复制链接分享