2010-03-16 26 views
5
$myq = sprintf("select user from table where user='%s'", $_POST["user"]); 

Tôi muốn biết liệu truy vấn trên có thể được khai thác bằng cách sử dụng SQL injection hay không. Có bất kỳ kỹ thuật tiêm SQL nâng cao nào có thể phá vỡ sprintf cho truy vấn cụ thể này không?Truy vấn này có dễ bị tiêm sql không?

+0

Có lý do nào khiến bạn phản đối việc sử dụng mysql_real_escape_string không? –

+0

Dunno nơi bạn đã nhận được nó, nhưng sprintf thoát không có gì. –

+0

ACtually đây là một phần của nhiệm vụ cho việc tìm kiếm tiêm sql. Tôi sao chép kịch bản trong địa phương của tôi và đã thử tất cả các tiêm sql bình thường $ a = sprintf ("chọn người dùng từ bảng nơi người dùng = '% s'", $ _POST ["người dùng"]); echo $ a Tôi tiếp tục nhận được dấu trích dẫn với \. Có điều gì đó ở giữa có thể thoát khỏi dấu ngoặc kép không? – user294924

Trả lời

25

Tôi không nghĩ rằng nó cần phải được đặc biệt tiên tiến ... thử một đầu vào của

' OR 1 = 1 OR user=' 

Nói cách khác, bạn sẽ nhận được SQL của:

select user from table where user='' OR 1 = 1 OR user='' 

Liệu trông giống như một truy vấn bạn thực sự muốn thực thi? (Bây giờ hãy xem xét khả năng thả bảng thay vào đó, hoặc một cái gì đó tương tự.)

Điểm mấu chốt là bạn nên sử dụng truy vấn được tham số hóa.

+0

doesnt sprintf thoát dấu nháy đơn? – user294924

+2

Không, nó không. Ít nhất là không có kinh nghiệm của tôi với PHP. –

+1

@ user294924,% s yêu cầu hệ thống con printf in bất kỳ chuỗi nào đối số variadic chứa. Nó không kiểm tra, không lọc, không thoát .. nó thực hiện chính xác những gì bạn nói nó làm. –

4

khi $ _POST ["người dùng"] bằng "; SHUTDOWN;" - chuyện gì sẽ xảy ra?

+0

sprintf có thể đã thoát khỏi dấu nháy đơn và truy vấn được gửi tới db sẽ là người dùng chọn từ bảng nơi người dùng = '\'; SHUTDOWN; ' – user294924

+0

Nếu áp phích không sử dụng mysqli_multi_query, sẽ không có gì xảy ra vì tất cả các phương thức truy vấn mysql khác trong PHP chỉ thực thi một truy vấn. – chiborg

0
$_POST["user"] = "' or 1=1 or user='" 
0

Có.

Nếu ai đó đưa vào sau khi người sử dụng trong hình thức của bạn:

'; delete * from table 
+2

Mặc dù nó sẽ không làm việc với mysql thông thường, nó là tốt cho ví dụ. –

8

Sử dụng sprintf không cung cấp cho bạn bất kỳ bảo vệ tốt hơn so với sử dụng chuỗi đơn giản nối. Lợi thế của sprintf chỉ là có một chút dễ đọc hơn khi sử dụng nối chuỗi đơn giản của PHP. Nhưng sprintf không làm bất cứ hơn nối chuỗi đơn giản khi sử dụng định dạng %s:

$str = implode('', range("\x00", "\xFF"));  // string of characters from 0x00 – 0xFF 
var_dump(sprintf("'%s'", $str) === "'".$str."'"); // true 

Bạn cần phải sử dụng chức năng mà thoát khỏi ký tự đặc biệt theo ngữ cảnh bạn muốn chèn dữ liệu vào (trong trường hợp này một string declaration in MySQL, giả như bạn đang sử dụng MySQL) như **mysql_real_escape_string** làm:

$myq = sprintf("select user from table where user='%s'", mysql_real_escape_string($_POST["user"])); 
8

Vâng, tôi muốn nói rằng bạn có một vấn đề tiềm ẩn có :)

bạn need to escape: 012.và \x1a. sprintf() does not do that, sprintf() không có sửa đổi đối với chuỗi, nó chỉ mở rộng bất kỳ đối số variadic nào mà bạn đưa nó vào bộ đệm mà bạn cung cấp theo định dạng mà bạn chỉ định.

Nếu các chuỗi đang được chuyển đổi, có khả năng là do magic quotes (như Rob được ghi chú trong Nhận xét), chứ không phải sprintf(). Nếu đúng như vậy, tôi cao khuyên bạn nên tắt chúng.

+0

-1 bởi vì: Anh ta cần phải trốn thoát nhiều hơn thế, và, nếu anh ta quên làm một trong bất kỳ truy vấn nào, anh ta bị choáng váng. Tóm lại: có tốt hơn là một lý do tốt, ** cụ thể ** để xây dựng một chuỗi truy vấn từ các chuỗi được nối, nếu không, hãy sử dụng tham số luôn. – BryanH

+0

@BryanH Hai người khác nói với anh rằng anh cần sử dụng các truy vấn được tham số hóa. Tôi đã trả lời cụ thể cho 'sprintf()' vì OP gặp khó khăn trong việc nắm bắt lý do tại sao nó không làm những gì anh nghĩ nó đang làm (Xem bình luận dưới câu trả lời của Jon). Tôi không gợi ý rằng anh ấy chỉ sử dụng các chuỗi được ghép nối :) –

1

Ahh ở đây tôi đi kèm với câu trả lời kỳ diệu! :)
magic quotes làm thoát cho bạn!

Vì vậy, bạn phải bật chỉ thị ảo_quotes_gpc ini tắt
và sau đó sử dụng mysql_real_escape_string như được đề xuất.

1

Thực ra, tắt báo giá kỳ diệu.

Trong PHP, nơi đó là, các bộ lọc sử dụng thích hợp:

$inUser = $_POST['user']; 
$outUser = filter_var($inUser, FILTER_SANITIZE_STRING); 

lọc loại bỏ các thẻ HTML và thoát khỏi nhân vật khác nhau.

Bên cạnh đó, bạn có thể cho cơ sở dữ liệu của bạn thoát khỏi điều đó cho bạn:

$inUser = $_POST['user']; 
$outUser = mysqli_real_escape_string($conn, $inUser); 

này thoát MySQL ký tự đặc biệt cụ thể như dấu ngoặc kép, dấu nháy đơn vv

Cuối cùng, bạn nên sử dụng các truy vấn tham số :

$sql = "SELECT user FROM table WHERE user = ?"; 
$stmt = $pdo->prepare($sql); 
$params = array($outUser); 
$stmt->execute($params); 

Truy vấn tham số tự động thêm dấu ngoặc kép xung quanh chuỗi, v.v ... và có các hạn chế khác khiến cho việc tiêm SQL thậm chí còn di chuyển nhiều hơn fficult.

Tôi sử dụng cả ba, theo thứ tự đó.

+0

Điều gì là tốt hơn để sử dụng để lọc POST hoặc GET không mong muốn, "mysqli_real_escape_string" hoặc "FILTER_SANITIZE_STRING"? – user345602

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