Witam,
Od pewnego czasu mam problem z jedna develeoperka ktora stworzyla nowy formularz RMA w PHP. Formualrz jednorazowo ma przyjac do 100 numerow seryjnych w formacie: 26-5142733. Problem polega na tym, ze zwiekszym w PHP i ModSecurity obie wartosci PCRE do 1000000 i dalej dostaje false positive z ModSecurity. Pytanie czy definitywnie winne jest ModSecurity, czy skrypt jest delikatnie mowiac skopany (nie znam sie na php)?

Wycinak loga z ModSecurity:
Kod
--31a0a96a-Z--

--f2b83a40-A--
[12/Dec/2016:14:28:51 +0000] WE60I38AAQEAADIZJGUAAAAA 1.2.3.4 33245 1.2.3.5 443
--f2b83a40-B--
POST /warranty/get_warranty.php HTTP/1.1
Host: rma.domain.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://rma.domain.com/warranty/
Content-Length: 356
DNT: 1
Connection: keep-alive

--f2b83a40-C--
data=26-5142733%0A26-5142734%0A26-5142735%0A26-5142736%0A26-5142737%0A26-5142738%0A26-5142739%0A26-5142740%0A26-5142741%0A26-5142742%0A26-5142743%0A26-5142744%0A26-5142745%0A26-5142746%0A26-5142747%0A26-5142748%0A26-5142749%0A26-5142750%0A26-5142751%0A26-5142752%0A26-5142753%0A26-5142754%0A26-5142755%0A26-5142756%0A26-5142757%0A26-5142758%0A26-5142759%0A
--f2b83a40-F--
HTTP/1.1 403 Forbidden
Strict-Transport-Security: max-age=15768000
Content-Length: 234
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--f2b83a40-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /warranty/get_warranty.php
on this server.<br />
</p>
</body></html>

--f2b83a40-H--
Message: Rule 7fc35b3599d0 [id "942360"][file "/usr/share/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"][line "451"] - Execution error - PCRE limits exceeded (-8): (null).
Message: Access denied with code 403 (phase 2). Match of "streq 0" against "TX:MSC_PCRE_LIMITS_EXCEEDED" required. [file "/etc/modsecurity/modsecurity.conf"] [line "107"] [id "200005"] [msg "ModSecurity internal error flagged: TX:MSC_PCRE_LIMITS_EXCEEDED"]
Action: Intercepted (phase 2)
Apache-Handler: application/x-httpd-php
Stopwatch: 1481552931298259 4802 (- - -)
Stopwatch2: 1481552931298259 4802; combined=2622, p1=456, p2=1992, p3=0, p4=0, p5=134, sr=63, sw=40, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.8.0 (http://www.modsecurity.org/); OWASP_CRS/3.0.0.
Server: Apache
Engine-Mode: "ENABLED"


Kod get_warranty.php
  1. <div class="row bottom1">
  2. <div class="container">
  3. <h1>STB Warranty Result</h1>
  4. </div><!-- container -->
  5. </div>
  6. <div class="row bottom1_background"></div>
  7. <div class="row about_content">
  8. <div class="container">
  9. <div class="col-lg-12 col-xs-12">
  10.  
  11. <?php
  12. if ( $_POST['data'] ) {
  13. include "js/function.php";
  14.  
  15. try {
  16. if ( strlen(trim($_POST['data'])) == 0 ) {
  17. throw new Exception("No entry found.");
  18. }
  19. $database = loadDatabase("","","database");
  20.  
  21. // CREATE TEMP mt1 TABLE
  22. $aryField = array( 'SN' );
  23. setQuery( $database, createTempTable( 'mt1', $aryField ) );
  24.  
  25. // Split input data and insert into mt1 table
  26. $aryData = preg_split( "/\n|\r|\s/", "SN\n". htmlspecialchars(trim($_POST['data'])), -1, PREG_SPLIT_NO_EMPTY );
  27. setQuery( $database, insertTempTable( 'mt1', $aryField, removeEmpty($aryData) ) );
  28.  
  29. /* Remove inaccurate serial numbers
  30.   $query = "DELETE FROM mt1 WHERE SN NOT LIKE '__-_______'";
  31.   setQuery( $database, $query );*/
  32.  
  33. // Remove duplicate SN and set LIMIT of 100 units only
  34. $query = "CREATE TEMPORARY TABLE t1 AS (
  35. SELECT SN AS Find, customer_name, SN AS oSN
  36. FROM mt1
  37. LEFT JOIN repair_report AS a
  38. ON mt1.SN = a.unit_serial_number AND a.customer_rma != 'INVENTORY' AND a.current_status NOT IN ('UTR')
  39. GROUP BY SN
  40. ORDER BY complete_date DESC
  41. LIMIT 0, 100)";
  42. setQuery( $database, $query );
  43.  
  44. //---- Start to find the original serials -----------//
  45. $query = "SELECT Find, customer_name FROM t1";
  46. $result = getQuery( $database, $query );
  47. while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
  48.  
  49. //----- Find the original serials along same customer ----//
  50. $serial = $row['Find'];
  51. $customer = $row['customer_name'];
  52.  
  53. $is_end = 1;
  54. do {
  55. $query = "SELECT fail_unit_serial_number
  56. FROM repair_report
  57. WHERE customer_name = ? AND unit_serial_number = ? AND fail_unit_serial_number LIKE '__-_______'
  58. ORDER BY complete_date DESC";
  59. $stmt = $database -> prepare( $query );
  60.  
  61. $stmt->bind_param( "ss", $customer, $serial );
  62. $stmt->execute();
  63. $stmt->store_result();
  64.  
  65. if ( $stmt->num_rows > 0 ) {
  66. $stmt->bind_result( $fail_serial );
  67. $stmt->fetch();
  68. $serial = $fail_serial;
  69. } else {
  70. $is_end = 0;
  71. }
  72.  
  73. $stmt->close();
  74. } while( $is_end > 0 );
  75.  
  76. //---------------- Update the original serial ----------//
  77. $query = "UPDATE t1 SET oSN = '". $serial ."' WHERE Find = '". $row['Find'] ."'";
  78. setQuery( $database, $query );
  79. }
  80. mysqli_free_result( $result );
  81. //-------- End finding the original seiral -------------//
  82.  
  83. // Find the warranty status for the original SN
  84. $query = "CREATE TEMPORARY TABLE showCase AS (
  85. SELECT Find, oSN, (additional_warranty_month + 12) AS given_warranty_month, database_sale_order, customer, CASE WHEN customer_ship_date = '0000-00-00' THEN manufacturer_ship_date ELSE customer_ship_date END AS customer_ship_date
  86. FROM t1 LEFT JOIN production_shipment AS a
  87. ON t1.oSN = a.unit_serial_number )";
  88. setQuery( $database, $query );
  89.  
  90. //--------- For EU warranty by prefix and sale order --------------//
  91. $query = "UPDATE showCase AS t1, customer_order_detail AS a SET t1.given_warranty_month = (a.given_warranty_month + t1.given_warranty_month - 12) WHERE t1.database_sale_order = a.database_sale_order AND SUBSTRING(t1.Find,1,2) = a.serial_prefix";
  92. setQuery( $database, $query );
  93.  
  94. //---------- For CCI Kamai500 3 year warranty ----------------------//
  95. $query = "UPDATE showCase SET given_warranty_month = given_warranty_month + 24 WHERE customer LIKE 'CCI %' AND SUBSTRING(Find,1,2) = '26'";
  96. setQuery( $database, $query );
  97.  
  98. //---------- For CCI Amulet400 2 year warranty ----------------------//
  99. $query = "UPDATE showCase SET given_warranty_month = given_warranty_month + 12 WHERE customer LIKE 'CCI %' AND SUBSTRING(Find,1,2) = '20'";
  100. setQuery( $database, $query );
  101.  
  102. //---------- For P&T 15 month warranty ----------------------------//
  103. $query = "UPDATE showCase SET given_warranty_month = given_warranty_month + 3 WHERE customer LIKE 'P%&%T%' OR customer LIKE 'P%and%T%' OR customer LIKE 'Advanced Media%' OR customer LIKE 'Confluent%'";
  104. setQuery( $database, $query );
  105.  
  106. //---------- All customer get addition 12 month warranty period ---//
  107. $query = "UPDATE showCase SET given_warranty_month = given_warranty_month + 12 WHERE customer_ship_date >= '2016-08-01'";
  108. setQuery( $database, $query );
  109.  
  110. $query = "SELECT Find AS SN, SUBSTRING(Find,1,2) AS Model, CASE WHEN customer_ship_date IS NULL THEN 'Not Found' ELSE DATE_ADD(customer_ship_date, INTERVAL given_warranty_month MONTH) END AS ship_date FROM showCase ORDER BY ship_date DESC, Find ASC ";
  111. $result = getQuery( $database, $query );
  112.  
  113. //Drawing Tables for second phase of submit serial numbers
  114. echo "<div class='result_data'>";
  115. echo "Total ". mysqli_num_rows( $result ) ." records found.<br>";
  116. generateTables( $result );
  117. echo "End.";
  118. ?>
  119.  
  120. </div></div>
  121.  
  122. <div class="disclaimer">
  123. <ul style="border: 1px solid #DDD; border-radius: 10px; padding: 20px 40px; margin-top: 20px;"><b style="font-size:16px; margin-left: -20px; display: block;">The product is considered out of warranty if any of the following conditions apply:</b>
  124. <li>The Company product serial number has been defaced or removed.</li>
  125. <li>Damage has occurred to the product caused by normal wear and tear, accident, negligence, abuse, misuse, misapplication, willful damage, acts of God, or use with non-Companyproducts.</li>
  126. <li>Damage has occurred to the product due to not adhering to instructions on use and care of product.</li>
  127. <li>The Company product or a part of the product has been modified, had alterations, or repairs done to it without the written permission of Company.</li>
  128. <li>Damage has occurred to the Company product due to improper installation, abnormal working conditions, or effects of excessive electrical current or voltage, whether or not caused by lightning.</li>
  129. </ul>
  130. </div>
  131. <?php
  132.  
  133. echo "</div>";
  134. mysqli_close($database);
  135.  
  136. } catch( Exception $e ) {
  137. echo "<font color=red>ERROR: ". $e->getMessage(). "</font>";
  138. }
  139. } else {
  140. echo "<font color=red>ERROR: Invalid Input Data.</font>";
  141. }
  142.  
  143. ?>
  144.  
  145. </div><!-- operators -->
  146. </div><!-- container -->
  147. </div>