Gõ lẫn lộn php

________số 8_______

$dateTime = new DateTime[];

foreach [[
   'ATOM',
   'COOKIE',
   'ISO8601',
   'RFC822',
   'RFC850',
   'RFC1036',
   'RFC1123',
   'RFC2822',
   'RFC3339',
   'RFC3339_EXTENDED',
   'RSS',
   'W3C',
   ] as $format] {
   eval["print 'DateTimeInterface::$format\t'.\$dateTime->format[DateTimeInterface::$format].\"\n\";"];
}

The above example will output:

DateTimeInterface::ATOM    2020-01-28T16:22:37-07:00
DateTimeInterface::COOKIE    Tuesday, 28-Jan-2020 16:22:37 MST
DateTimeInterface::ISO8601    2020-01-28T16:22:37-0700
DateTimeInterface::RFC822    Tue, 28 Jan 20 16:22:37 -0700
DateTimeInterface::RFC850    Tuesday, 28-Jan-20 16:22:37 MST
DateTimeInterface::RFC1036    Tue, 28 Jan 20 16:22:37 -0700
DateTimeInterface::RFC1123    Tue, 28 Jan 2020 16:22:37 -0700
DateTimeInterface::RFC2822    Tue, 28 Jan 2020 16:22:37 -0700
DateTimeInterface::RFC3339    2020-01-28T16:22:37-07:00
DateTimeInterface::RFC3339_EXTENDED    2020-01-28T16:22:37.803-07:00
DateTimeInterface::RSS    Tue, 28 Jan 2020 16:22:37 -0700
DateTimeInterface::W3C    2020-01-28T16:22:37-07:00

Tôi đã thực hiện một số nghiên cứu về chủ đề này và có một số chuyên gia đã nói rằng điều đó là không thể, vì vậy tôi muốn hỏi một giải pháp thay thế

Hoàn cảnh của tôi

Trang A. [Thủ tục thanh toán. php] Khách hàng điền vào chi tiết thanh toán của họ

Trang B. [tiến trình. php] Tạo số hóa đơn và lưu trữ thông tin khách hàng trong cơ sở dữ liệu

Trang C. [bên thứ ba. com] Cổng thanh toán thứ ba [CHẤP NHẬN DỮ LIỆU BÀI ĐĂNG]

Khách hàng điền thông tin chi tiết của họ và thiết lập giỏ hàng của họ ở Trang A, sau đó ĐĂNG lên Trang B. quy trình bên trong. php, lưu trữ dữ liệu đã đăng bên trong cơ sở dữ liệu và tạo số hóa đơn. Sau đó, POST dữ liệu khách hàng và số hóa đơn cho bên thứ ba. com cổng thanh toán. Sự cố đang thực hiện POST ở trang B. cURL có thể POST dữ liệu lên Trang C, nhưng vấn đề là trang không chuyển hướng đến trang C. Khách hàng cần điền thông tin chi tiết Thẻ tín dụng trên Trang C

Cổng thanh toán của bên thứ ba đã cung cấp cho chúng tôi mẫu API, mẫu này đang ĐĂNG số hóa đơn cùng với chi tiết khách hàng. Chúng tôi không muốn hệ thống tạo ra quá nhiều số hóa đơn không mong muốn

Có giải pháp nào cho điều này?

Khi so sánh hai giá trị, PHP đoán kiểu của chúng và thực hiện phép so sánh tương ứng. Điều này có thể bị lạm dụng bằng cách định dạng một chuỗi dưới dạng số, do đó việc so sánh được thực hiện lỏng lẻo hơn

Loại nhầm lẫn

PHP là một ngôn ngữ động, được gõ lỏng lẻo. PHP đôi khi sẽ âm thầm chuyển đổi các biến sang kiểu khác, được gọi là tung hứng kiểu. Ví dụ, điều này xảy ra khi thêm một chuỗi vào một số nguyên

php > var_dump[3 + "12"];
int[15];

Điều này cũng xảy ra khi sử dụng toán tử bằng bình thường, ==. Toán tử này trước tiên đoán loại của cả hai toán hạng, sau đó so sánh chúng. Điều này thậm chí xảy ra khi cả hai toán hạng là chuỗi

php > var_dump["0" == "-0"];
bool[true]

Cả hai giá trị đều giống số, được chuyển đổi thành int và sau đó được so sánh

Ký hiệu khoa học

Để viết các số rất lớn hoặc rất nhỏ một cách dễ dàng, có kí hiệu khoa học. Điều này thêm lũy thừa 10 dưới dạng số nhân, điều này có tác dụng dịch chuyển dấu thập phân sang trái hoặc phải. Ví dụ, một số lớn có thể được viết là

6. 022 × 1023

Trong PHP, một cái gì đó tương tự tồn tại sử dụng e

php > var_dump[6.022e23];
float[6.022E+23]

Kết hợp cả hai

Bây giờ chúng ta biết rằng PHP cố gắng chuyển đổi chuỗi thành số trước khi so sánh và diễn giải một e trong một số dưới dạng số mũ, giai đoạn được thiết lập cho lỗ hổng nhầm lẫn kiểu khi so sánh mật khẩu

Lỗ hổng này phát sinh khi hàm băm đơn giản của mật khẩu được kiểm tra với hàm băm mật khẩu trong cơ sở dữ liệu bằng toán tử bằng. Ví dụ này đến từ Monstra CMS

if [trim[$user['password']] == Security::encryptPassword[Request::post['password']]] {
    // Logged in
}

function encryptPassword[$password]
{
    return md5[md5[trim[$password] . MONSTRA_PASSWORD_SALT]];
}

Bây giờ, hãy xem điều gì sẽ xảy ra nếu mật khẩu của chúng ta băm thành tổng MD5 này

0e770334890835629043478642775106

Đối với PHP, đây trông giống như số sau

0 × 10770334890835629043478642775106

bằng 0. Điều này có nghĩa là bạn có thể đăng nhập bằng bất kỳ mật khẩu nào khác có hàm băm tương tự và cũng bằng số 0

Tìm một vụ va chạm

Hãy tìm hai giá trị băm mà cả hai đều có giá trị số 0

for [$i = 0;; $i++] {
    $hash = encryptPassword[$i];
    if [$hash == "0"] {
        echo "$i $hash\n";
    }
}

Sau khoảng năm phút, nó có hai giá trị đầu ra

228453663 0e770334890835629043478642775106
576315426 0e561311390263821655340886129044

Chúng tôi có thể kiểm tra bằng cách đặt mật khẩu của mình thành “228453663” và sau đó thử đăng nhập bằng “576315426”. Điều này hoạt động, chỉ ra rằng các giá trị băm được so sánh dưới dạng số

xác suất

Để hàm băm của chúng ta là số không, chúng ta cần một hoặc nhiều số không, sau đó là một e, sau đó là tất cả các số. Giả sử rằng hàm băm MD5 không thể phân biệt được với ngẫu nhiên, xác suất điều này xảy ra là bao nhiêu?

Đầu tiên, hãy tính toán trường hợp có đúng một số không. Vì vậy, hàm băm bắt đầu bằng

php > var_dump["0" == "-0"];
bool[true]
0. Vì mỗi vị trí có thể có 16 khả năng, nên cứ 16 khả năng thì có một vị trí chứa một ký tự cụ thể. Đối với hai ký tự, đây là một trên mười sáu lần mười sáu, hoặc 1∕256

30 ký tự còn lại phải là chữ số. Một vị trí có 10/16 cơ hội là một chữ số. Điều này có nghĩa là 30 ký tự có cơ hội [10∕16]30 là tất cả các chữ số

[1∕16]2 × [10∕16]30 ≈ 1∕340.000.000

Vì vậy, nếu chúng ta giả sử một mật khẩu ngẫu nhiên, thì có một phần trăm triệu khả năng nó được so sánh là số 0

Phần kết luận

So sánh một cách lỏng lẻo MD5 chắc chắn là một lỗ hổng, nhưng nó vẫn không cho phép kẻ tấn công bước qua cửa. Kẻ tấn công sẽ cần hàng trăm triệu lần thử trước khi có thể phá vỡ bảo mật với lỗ hổng này

Chủ Đề