2016-10-07 19 views
6

Trên một cơ sở dữ liệu MySQL 5.6, tôi xây dựng bảng đơn giản này và chèn một hàng:Tại sao "" =" khai thác truy vấn MySQL này

CREATE TABLE `users` ( 
`username` varchar(64) DEFAULT NULL, 
`password` varchar(64) DEFAULT NULL 
); 

INSERT INTO users VALUES ('bob', 'pass'); 

Sau đó, tôi thiết lập một truy vấn trong PHP như sau:

$query = "SELECT * from users where username=\"".$username."\" and password=\"".$password."\""; 

Khi $username$password đều bằng ""=", kết quả truy vấn là SELECT * from users where username="""="" and password="""="". Khi điều đó được sử dụng để truy vấn bảng thiết lập trước đó, các hàng trong bảng được trả về.

Câu hỏi đặt ra là, MySQL đánh giá truy vấn đó như thế nào để nó xem xét truy vấn hợp lệ và câu lệnh WHERE là đúng? Giả sử tất cả hai dấu ngoặc kép được kết hợp với untaken liền kề đúp quote gần nhất, tôi dự kiến ​​sẽ có các truy vấn để được giải thích một cái gì đó như thế này, mà hình như nó cần được xem xét vô nghia:

SELECT * from users where username="" 
"=" 
" and password=" 
"" 
= 
"" 

Dưới đây là một ví dụ điển hình hành vi trên MySQL 5.6 DB: http://sqlfiddle.com/#!9/02e606/2

+1

SQL injection cảnh báo https://xkcd.com/327/ sử dụng tham số để thay thế. –

+2

Đây là một lỗ hổng có chủ ý trong một thử thách "vào SQL injection" đơn giản mà tôi đã giải quyết. Câu hỏi đặt ra là tại sao giải pháp cụ thể này hoạt động thay vì cách bảo mật nó. Nhưng tôi thích dải đó. –

+1

chạy 'GIẢI THÍCH 'trên truy vấn và xem cách _MySQL_ đang đánh giá nó ... – War10ck

Trả lời

9

Đó là bởi vì MySQL cho phép "" như một sự thay thế cho \".

mysql> select '"foo"' = """foo""", '"foo"' = "\"foo\"", 'foo' = """foo"""; 
+---------------------+---------------------+-------------------+ 
| '"foo"' = """foo""" | '"foo"' = "\"foo\"" | 'foo' = """foo""" | 
+---------------------+---------------------+-------------------+ 
|     1 |     1 |     0 | 
+---------------------+---------------------+-------------------+ 
1 row in set (0.00 sec) 

Trong trường hợp của bạn cụ thể:

SELECT * from users where username="""="" and password="""="" 

sẽ được giống như (nếu tôi đang phân tích cú pháp này một cách chính xác trong đầu của tôi):

SELECT * from users where (username='"="" and passsword="') = "" 

Một thử nghiệm bình đẳng ba chiều IS cú pháp chính xác, nhưng không đánh giá như mong đợi

mysql> select 'a' = 'a' = 'a'; 
+-----------------+ 
| 'a' = 'a' = 'a' | 
+-----------------+ 
|    0 | 
+-----------------+ 
.210

vì đó phân tích như (a=a)=a ->true=a ->false

- bình luận theo dõi cho @juan:

mysql> select 'a'='a'='a', 'a'='a'='b', 'a'='b'='a', 'b'='a'='a', 'b'='b'='a'; 
+-------------+-------------+-------------+-------------+-------------+ 
| 'a'='a'='a' | 'a'='a'='b' | 'a'='b'='a' | 'b'='a'='a' | 'b'='b'='a' | 
+-------------+-------------+-------------+-------------+-------------+ 
|   0 |   0 |   1 |   1 |   0 | 
+-------------+-------------+-------------+-------------+-------------+ 

Đó là phi trực quan, vì

mysql> select 'a'=('a'='b'), ('a'='a')='b', true='b', 'a'=false; 
+---------------+---------------+----------+-----------+ 
| 'a'=('a'='b') | ('a'='a')='b' | true='b' | 'a'=false | 
+---------------+---------------+----------+-----------+ 
|    1 |    0 |  0 |   1 | 
+---------------+---------------+----------+-----------+ 

--- followup cho followup: một lần nữa, truy vấn ban đầu của bạn:

SELECT * from users where username="""="" and password="""="" 

sẽ chạy như

SELECT * from users where (username='"="" and passsword="') = "" 
SELECT * from users where (false) = "" 
SELECT * from users where true 

false ="" trong mysql đánh giá là TRUE, do đó tất cả các hàng được bao gồm, trừ khi bạn có một người dùng có tên là nghĩa đen "="" and password=".

+1

[Trang hướng dẫn có liên quan] (http://dev.mysql.com/doc/refman/5.7/en/string-literals.html). Cá nhân tôi không biết mysql đã hỗ trợ điều này nhưng đã làm việc với Oracle db trong một thời gian và đó là cách họ thoát khỏi dấu ngoặc kép. –

+1

nếu 'a '=' a '=' a'' đánh giá thành' 0' cách 'WHERE 0' trả về hàng? –

+0

@JuanCarlosOropeza: vì nó không phải là bộ lọc bảng. nó đang chọn một giá trị theo nghĩa đen, mà xảy ra là một biểu thức tất cả các hằng số. nó không khác gì 'chọn 1' hoặc' chọn sai'. –

1

tôi đoán bạn đang làm một cái gì đó như thế này

Sql Demo

SELECT """="" and password="""="" -- this is equal to 0 
from users 
where (username = "anything") = false; 

enter image description here

0

Trong MYSQL bạn có thể thoát khỏi dấu ngoặc đơn và đôi như thế này:

Thay vì \" bạn có thể làm "" này khi useing " như lĩnh vực wrapper. Cùng với \' trở thành '' khi sử dụng ' như lĩnh vực wrapper

Và những gì trong MYSQL cũng làm việc là:

SELECT * FROM tbl WHERE name = 'ab' 'b c' 

truy vấn thực:

SELECT * FROM tbl WHERE name = 'abb c' 

Xem online MYSQL documention

Các vấn đề liên quan