Score:0

NGINX กำหนดเส้นทางไปยังโฮสต์เสมือนที่ไม่ถูกต้องเมื่อส่วนหัวของโฮสต์มีเครื่องหมายทวิภาค

ธง cn

nginx.conf ของฉันมีส่วน "เซิร์ฟเวอร์" หลายส่วน และส่วนเซิร์ฟเวอร์ที่รับทั้งหมด นี่คือตัวอย่าง nginx.conf เพื่อให้คุณมีความคิด:

ผู้ใช้ www-data;
worker_processes อัตโนมัติ
worker_cpu_affinity อัตโนมัติ
pid /run/nginx.pid;

เหตุการณ์ {
    worker_connections 4000;
    ใช้ epol;
    ยอมรับ_mutex ปิด;
}

http {
    รวม /etc/nginx/mime.types;
    แอปพลิเคชัน default_type/octet-stream;
    error_log /var/log/nginx/error.log;

    เซิร์ฟเวอร์ {
        ฟัง 80;

        server_name foo.com;

        ที่ตั้ง / {
            default_type ข้อความ/ธรรมดา;
            กลับ 200 "สวัสดีจาก foo.com";
        }

        error_page 500 502 503 504 /500.html;
    }

    เซิร์ฟเวอร์ {
        ฟัง 80 default_server;
        ชื่อเซิร์ฟเวอร์ _;

        ที่ตั้ง / {
            กลับ 403 "ขอโทษ";
        }
    }

}

ฉันคาดหวังว่าเซิร์ฟเวอร์จะส่งคืน 403 หากส่วนหัว "โฮสต์" เป็นอย่างอื่นนอกจาก "foo.com"

เห็นได้ชัดว่ามีใครบางคนใช้งาน Burp Suite บนเซิร์ฟเวอร์ของฉัน และฉันสังเกตเห็นพฤติกรรมที่น่าสนใจเมื่อพวกเขาส่งส่วนหัว "Host: foo.com:more-stuff-here": NGINX จะกำหนดเส้นทางคำขอไปยังส่วน "เซิร์ฟเวอร์" แรก ดูเหมือนว่าจะไม่สนใจเครื่องหมายทวิภาคและทุกอย่างหลังจากนั้นในค่าส่วนหัว

ฉันสามารถทำซ้ำในเครื่องด้วย nginx.conf ด้านบน:

$ curl -H "โฮสต์: foo.com" http://127.0.0.1
สวัสดีจาก foo.com

$ curl -H "โฮสต์: foo.com:unexpected-content" http://127.0.0.1
สวัสดีจาก foo.com

$ curl -H "โฮสต์: bar.com" http://127.0.0.1
ขอโทษ

ทำไม NGINX ถึงทำเช่นนี้? นี่เป็นพฤติกรรมที่คาดหวังหรือไม่? ฉันควรเปลี่ยนอะไรใน nginx.conf เพื่อให้แน่ใจว่าคำขอที่มีส่วนหัว "Host: foo.com:more-stuff-here" ไปที่บล็อกเริ่มต้น

อัปเดต: สำหรับใครก็ตามที่ค้นคว้าปัญหาเดียวกัน ฉันก็ได้สร้าง ตั๋วในตัวติดตามปัญหา NGINX.

djdomi avatar
za flag
ขีดเส้นใต้ทำให้ชื่อโฮสต์ไม่ถูกต้องและทำให้เป็นค่าเริ่มต้น
Pēteris Caune avatar
cn flag
@djdomi â nginx เอกสารบอกว่าเครื่องหมายขีดล่างไม่มีความหมายพิเศษ เป็นเพียงชื่อโฮสต์ที่ไม่ถูกต้อง บิตที่สำคัญคือ "default_server" ในคำสั่งการฟัง ฉันสับสนว่าทำไม nginx จึงถือว่าค่าโฮสต์ "foo.com:unexpected-content" เป็นการจับคู่โดยตรงกับชื่อเซิร์ฟเวอร์ "foo.com"
Score:3
ธง in

คำจำกัดความสำหรับส่วนหัวของโฮสต์ใน HTTP RFC ระบุว่าส่วนหัวของโฮสต์ควรมีแบบฟอร์ม โฮสต์:พอร์ต, กับ :ท่า เป็นตัวเลือก

nginx เห็นทุกอย่างหลังจากโคลอนเป็นพอร์ตสำหรับโฮสต์ แต่มันไม่เกี่ยวข้องกับบริบทของคุณเนื่องจากคุณไม่ได้ระบุเซิร์ฟเวอร์บล็อกด้วยวิธีนั้น ดังนั้นจึงใช้การจับคู่ที่ใกล้เคียงที่สุดที่สามารถหาได้ โฮสต์ที่ไม่มี "พอร์ต"

Pēteris Caune avatar
cn flag
อา ฉันเข้าใจแล้ว ฉันจะทำอย่างไรเพื่อแก้ไขปัญหานี้ เป็นไปได้ไหมที่จะทำให้ nginx เพิกเฉยต่อคำขอด้วยค่าพอร์ตที่ไม่ถูกต้อง
in flag
เป็นปัญหาของคุณหรือไม่ที่แอปพลิเคชันที่ส่งคำขอที่ไม่ถูกต้องทำงานไม่ถูกต้อง ถ้าใช่ ฉันจะแก้ไขแอปพลิเคชัน ถ้าไม่ใช่ ฉันจะเพิกเฉยต่อแอปพลิเคชันนั้น
in flag
ตัวเลือกเดียวที่ฉันคิดได้คือพยายามเพิ่ม `foo.com:*` เป็น server_alias ไปยังโฮสต์เริ่มต้นและหวังว่า nginx จะฉลาดพอที่จะแยกแยะได้
Pēteris Caune avatar
cn flag
แอปพลิเคชันของฉันสร้างคำเตือนเกี่ยวกับส่วนหัวของโฮสต์ที่ไม่ถูกต้อง ฉันสามารถปิดเสียงคำเตือนได้ แต่ฉันอยากให้ NGINX สามารถตรวจจับคำขอที่ไม่ถูกต้องก่อนที่จะส่งไปยังแอปพลิเคชัน
Pēteris Caune avatar
cn flag
ฉันทดสอบ `foo.com:*` แล้ว NGINX ไม่เริ่มทำงานและพิมพ์ข้อผิดพลาด: `ชื่อเซิร์ฟเวอร์หรือสัญลักษณ์แทนไม่ถูกต้อง "foo.com:*"`
in flag
คิดมาก. ถ้าอย่างนั้นฉันไม่คิดว่าจะมีอะไรที่คุณสามารถทำได้ในด้าน nginx สิ่งนี้ควรได้รับการแก้ไขในแอปพลิเคชันที่สร้างคำขอที่ไม่ถูกต้อง
Score:0
ธง us

สิ่งต่อไปนี้อาจใช้ได้กับ default_server:

เซิร์ฟเวอร์ {
    ฟัง 80 default_server;

    server_name _ ~ตัวอย่าง\.com:;

    ที่ตั้ง / {
        กลับ 403 "ขอโทษ";
    }
}

ส่วนที่สำคัญคือตัวหนอน ~ซึ่งระบุการจับคู่นิพจน์ทั่วไป

Pēteris Caune avatar
cn flag
เป็นความคิดที่ดี แต่ดูเหมือนจะไม่ได้ผลสำหรับฉัน คำขอยังคงถูกส่งไปยังส่วนอื่นของเซิร์ฟเวอร์
Score:0
ธง tl

ความคิดทางเลือกเดียวที่ฉันคิดได้คือโค้ดบางอย่างในระดับแอปพลิเคชันฝั่งเซิร์ฟเวอร์เพื่อตรวจสอบค่าโฮสต์และส่งคืนการตอบกลับ 403 เป็นโค้ด

อย่างไรก็ตาม นี่ไม่ใช่วิธีที่ถูกต้อง เนื่องจากปัญหาเป็นปัญหาไคลเอ็นต์ที่ต้องแก้ไข ไม่ใช่สำหรับแอปพลิเคชันของคุณ

เช่น เอาจาก คำตอบ SO นี้ ด้วยแอปพลิเคชัน PHP คุณสามารถแก้ไขตรรกะนี้ได้อย่างง่ายดายเพื่อให้ได้ผลตามที่ต้องการ สังเกตเฉพาะการตรวจสอบสำหรับ SERVER_PORT ตาม คำตอบของเจอรัลด์

$allowed_hosts = array('foo.example.com', 'bar.example.com');
$allowed_ports = อาร์เรย์(80,443);
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts) || !in_array($_SERVER['SERVER_PORT'], $allowed_ports )) {
    header($_SERVER['SERVER_PROTOCOL'].' 400 คำขอไม่ถูกต้อง');
    ทางออก;
}
Pēteris Caune avatar
cn flag
ขอบคุณสำหรับคำตอบ. นั่นเป็นวิธีที่มันใช้งานได้สำหรับฉันที่นี่ (แอปพลิเคชันแบ็กเอนด์ใช้เฟรมเวิร์กเว็บ Django ซึ่งตรวจสอบส่วนหัวของโฮสต์เทียบกับรายการที่อนุญาต ไม่เป็นไร แต่ฉันหวังว่าจะให้ NGINX ทำหน้าที่เป็น "เกราะป้องกัน" ต่อหน้าแอปแบ็กเอนด์ ตรวจสอบให้แน่ใจว่ามีเพียงคำขอที่ถูกต้องและมีรูปแบบที่ดีเท่านั้นที่จะผ่านไปยังแอปแบ็กเอนด์)

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา