View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0015573 | mantisbt | security | public | 2013-03-06 10:32 | 2014-09-23 18:05 |
Reporter | jjtest | Assigned To | dregad | ||
Priority | high | Severity | crash | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Platform | Unix | OS | Solaris | OS Version | 8/10 |
Product Version | 1.2.12 | ||||
Target Version | 1.2.15 | Fixed in Version | 1.2.15 | ||
Summary | 0015573: CVE-2013-1883: One query can be issued via current Mantis interface to take down site | ||||
Description | This is a very bad query problem that can be used as a DOS attack very easily. I found it while upgrading 1.1.18 to 1.2.14. When I ran it on your site yesterday... somewhere around 5pm EST, it took you down too! (Sorry but proved the issue!) In my situation, I had to kill the offending thread in MySQL and restart Apache to get my site back online. The query caused MySQL to take all of the cpu on my solaris box... It has to do with the search feature "Match Type: Any Condition" Basically it is broken badly WHEN USED WITH A TEXT STRING SEARCH. All you have to do to reproduce this is search a large dataset for any text string from the View Issues search box. Searching with the default "Match Type: All Conditions" should yield expected results. Now switch Match Type to "Any Condition" and press Apply Filter.... and watch your site... die. This is all compounded (TERRIBLY) by the feature that stores your last View Issues query and automatically reissues it when you click View Issues.... now you DOS your site every time you click View Issues! To get control back from this mishap I was forced to remove my cookie so the offending search was not automatically reissued. | ||||
Steps To Reproduce | All you have to do to reproduce this is search a large dataset for any text string from the View Issues search box. Searching with the default "Match Type: All Conditions" should yield expected results. Now switch Match Type to "Any Condition" and press Apply Filter.... and watch your site... die. | ||||
Additional Information | When using the fast All Conditions to search for the string "sql", this query is issued: Count( DISTINCT mantis_bug_table.id ) as idcnt FROM mantis_bug_text_table, man When using the tragically slow "Any Condition" query for the string "sql", this query is issued: Count( DISTINCT mantis_bug_table.id ) as idcnt FROM mantis_bug_text_table, man Basically, you cannot "OR" the primary key of the LEFT-JOINED mantis_bug_text table, while attempting to match against it's description field. Well...you obviously CAN...but the results are tragic. When I change that OR to an AND the query runs quickly. | ||||
Tags | No tags attached. | ||||
Attached Files | 15573-fix-1.diff (728 bytes)
diff --git a/core/filter_api.php b/core/filter_api.php index 55edd46..7b964b8 100644 --- a/core/filter_api.php +++ b/core/filter_api.php @@ -1996,8 +1996,7 @@ # add text query elements to arrays if ( !$t_first ) { $t_from_clauses[] = "$t_bug_text_table"; - $t_where_clauses[] = "$t_bug_table.bug_text_id = $t_bug_text_table.id"; - $t_where_clauses[] = $t_textsearch_where_clause; + $t_where_clauses[] = "$t_bug_table.bug_text_id = $t_bug_text_table.id AND $t_textsearch_where_clause"; $t_join_clauses[] = " LEFT JOIN $t_bugnote_table ON $t_bug_table.id = $t_bugnote_table.bug_id"; $t_join_clauses[] = " LEFT JOIN $t_bugnote_text_table ON $t_bugnote_table.bugnote_text_id = $t_bugnote_text_table.id"; } | ||||
related to | 0006809 | closed | rombert | Using an 'Or' filter logic |
related to | 0015678 | closed | dregad | Bad performance when filtering and using match type "Any Condition" |
related to | 0015721 | closed | grangeway | Functionality to consider porting to master-2.0.x |
related to | 0016922 | closed | dregad | View Issues list is very slow if a filter is used |
Basically..I think you may only have one "OR" in the water! Maybe you meant the OR to replace the AND between: ...213, 299) ) AND ( mantis_bug_table.bug_text_id... instead of the current: ...mantis_bug_table.bug_text_id = mantis_bug_text_table.id OR ( ( (summary LIKE... |
|
I was upgrading from 1.1.8... not 1.1.18 |
|
Thanks for the bug report. I'm marking this issue as private for now, to avoid giving ideas to some people... |
|
I know. I just hate those "some people" too... they have sucked a lot of the fun out of my job in the last decade or so... |
|
Thanks for the report and the detailed analysis, it has been quite helpful in narrowing down the root cause. I have attached a fix which works for me ™ but I'd be happy if you could validate that it fixes the performance problem and also returns the correct results. |
|
I tested the proposed patch on my dev box, using an old clone of our tracker DB (about 11'000 bugs and 30'000 notes). The query's performance with ANY condition is about the same as for ALL (whereas before I killed mysql after 30 minutes of execution). As a side note and while on the topic of performance, I'm not sure why we are using an outer join on the bugnote_text table, in theory it should be a 1:1 relationship so an inner join would be enough and be more efficient. It may also be useful from a readability perspective, to rewrite the query to use a JOIN clause for the mantis_bug_text_table and mantis_project_table. This way the where clauses would only relate to the filter criteria. |
|
Wouldn't an inner join require that the bugnote_text_table exist? |
|
Yes it would, but an outer join does also - not sure I get your point... |
|
Um, sorry. I'm less fluent in SQL by the day :-) I meant that an inner join would require a bugnote to exist, whereas the outer join would allow matching even if no matching bugnote entry exists. |
|
You're absolutely right on principle. However in this case as I said before bugnote_text and bugnote tables have a 1:1 relationship, i.e. there is (or should be) always one record in each table for a given note, except possibly in case of errors (in which case we'd likely have orphan records in bugnote_text table). See bugnote_add() lines 154 & 176. It's worth noting that the same logic also applies to bug & bug_text tables. |
|
Oh right, I misread that as bug_table and bugnote_table. |
|
I've actually left this unchanged since I don't want to muck around in the filter_api anymore ... sigh. Hopefully there will come a time for cleanups as well. |
|
dregad wrote at 0015573:0035414
I did the same, using latest code from github. |
|
Reopening based on atrol's indication that the fix does not work. |
|
Strange. I'll re-test and let you know (likely not before next week though) |
|
Not sure how I tested this the last time... Now I can consistently reproduce the problem. I think the problem is caused by mixing join criteria with where clauses. I'll dump the SQL statements and have a closer look later tonight. |
|
That should (hopefully) do the trick. Please test and let me know. Note: I also pushed one additional commit implementing my suggestion in 0015573:0035414. |
|
Made some quick tests, looks good at first sight. |
|
I would love to see bug and bug_text tables merged into one at one point. Not sure if it is worth the work, but I always thought of this as extra complexity. However, I do agree with atrol's recommendation over email that we should deploy this to the official / demo bug trackers and once validated for few days kick-off 1.2.15. |
|
Agreed. And the same goes for bugnote vs bugnote_text too. But this is no small undertaking, and definitely not on the critical path atm... Not to mention that it obviously involves a schema change, which means it has to be done in master branch, and we still have no plan or resources to get cracking on releasing that ;) That said, I have updated both trackers with the fix now, so I'll make this issue public. |
|
A CVE ID for this issue was requested from oss-security mailing list [1] on 21-Mar-2013. [1] http://article.gmane.org/gmane.comp.security.oss.general/9779 |
|
CVE-2013-1883 was assigned on 22-Mar-2013 |
|
Marking as 'acknowledged' not resolved/closed to track that change gets ported to master-2.0.x branch |
|
MantisBT: master-1.2.x 543ba012 2013-03-07 16:02 Details Diff |
filter_api: ensure that the free_text where clauses are always ANDed Fixes 0015573: One query can be issued via current Mantis interface to take down site |
Affected Issues 0015573 |
|
mod - core/filter_api.php | Diff File | ||
MantisBT: master 540ae471 2013-03-07 16:02 Details Diff |
filter_api: ensure that the free_text where clauses are always ANDed Fixes 0015573: One query can be issued via current Mantis interface to take down site |
Affected Issues 0015573 |
|
mod - core/filter_api.php | Diff File | ||
MantisBT: master ce961095 2013-03-18 18:26 Details Diff |
Revert "filter_api: ensure that the free_text where clauses are always ANDed" This reverts commit 543ba012999c20310a2208bd8e5f7f88efe392ce. |
Affected Issues 0015573 |
|
mod - core/filter_api.php | Diff File | ||
MantisBT: master-1.2.x d4e7b224 2013-03-18 18:26 Details Diff |
Revert "filter_api: ensure that the free_text where clauses are always ANDed" This reverts commit 543ba012999c20310a2208bd8e5f7f88efe392ce. |
Affected Issues 0015573 |
|
mod - core/filter_api.php | Diff File | ||
MantisBT: master 44055f88 2013-03-18 18:36 Details Diff |
Fix filter api issue with 'any condition' and text search A filter combining some criteria and a text search with 'any condition' results in a cartesian product, which has the potential to bring down the site as the RDBMS eats up all available resources. The root cause of this behavior is joining the bug_text table with a from clause and setting the join's criteria in the query's where clause, without taking consideration the operator's precedence (AND/OR). This commit resolves the problem by using a JOIN clause instead, which makes the query cleaner. Fixes 0015573 |
Affected Issues 0015573, 0016922 |
|
mod - core/filter_api.php | Diff File | ||
MantisBT: master-1.2.x d16988c3 2013-03-18 18:36 Details Diff |
Fix filter api issue with 'any condition' and text search A filter combining some criteria and a text search with 'any condition' results in a cartesian product, which has the potential to bring down the site as the RDBMS eats up all available resources. The root cause of this behavior is joining the bug_text table with a from clause and setting the join's criteria in the query's where clause, without taking consideration the operator's precedence (AND/OR). This commit resolves the problem by using a JOIN clause instead, which makes the query cleaner. Fixes 0015573 |
Affected Issues 0015573 |
|
mod - core/filter_api.php | Diff File |