
CVE ID: CVE-2023-36664
उत्पाद: Ghostscript (< 10.01.2)
भेद्यता प्रकार: Remote Code Execution (RCE)
यह भेद्यता (CVE-2023-36664) Ghostscript द्वारा पाइप डिवाइस (%pipe% या | उपसर्ग) के लिए पथ अनुमति सत्यापन को अपर्याप्त रूप से संभालने के कारण उत्पन्न होने वाली मनमाने कोड निष्पादन (RCE) भेद्यता है।
जब सिस्टम हमलावर द्वारा दुर्भावनापूर्ण रूप से हेरफेर की गई दस्तावेज़ फ़ाइल (PS/EPS) को पार्स या प्रोसेस करता है, तो उपयोगकर्ता प्राधिकरण के बिना मनमानी सिस्टम कमांड निष्पादित की जा सकती हैं।
मुख्य भूमिका: यह मूल रूप से टेक्स्ट-आधारित ग्राफ़िक्स निर्देशांक कोड (जैसे: "100 200 स्थान पर एक रेखा खींचें") को पढ़ता है और उसे मॉनिटर स्क्रीन या प्रिंटर आउटपुट के लिए छवि फ़ाइल में परिवर्तित करता है जिसे हम आँखों से देख सकते हैं।
पाइप एक ऐसी सुविधा है जो एक एप्लिकेशन के आउटपुट को दूसरे एप्लिकेशन के इनपुट से जोड़कर सॉफ़्टवेयर के बीच संचार करने में मदद करती है। कमांड में इसे | प्रतीक द्वारा दर्शाया जाता है।
उदाहरण: cat /etc/hosts | grep localhost
Ghostscript डिफ़ॉल्ट रूप से सुरक्षित मोड (-dSAFER) चालू होने पर सिस्टम की संवेदनशील फ़ाइलों तक पहुँचने या बाहरी कमांड को मनमाने ढंग से निष्पादित करने से रोकने के लिए फ़ाइल पथों की कड़ी जाँच करता है।
समस्या: जब हमलावर फ़ाइल पथ के स्थान पर सामान्य फ़ाइल नाम के बजाय पाइप डिवाइस उपसर्ग (%pipe% या |) को सटीक रूप से हेरफेर करके डालता है, तो Ghostscript की आंतरिक अनुमति सत्यापन लॉजिक इस उपसर्ग को ठीक से नहीं पहचान पाता और इसे "सुरक्षित पथ" या "सत्यापन योग्य नहीं" समझकर पास कर देता है।
परिणाम: जिन खतरनाक कमांडों को मूल रूप से फ़िल्टर किया जाना चाहिए था, वे सत्यापन लूप को आसानी से बायपास कर जाती हैं।
दुर्भावनापूर्ण फ़ाइल इंजेक्शन: हमलावर पोस्टस्क्रिप्ट (.ps/.eps) फ़ाइल के अंदर (%pipe%दुर्भावनापूर्ण-कमांड) (मोड) file /DCTDecode filter जैसे रूप में कोड एम्बेड करता है।
पार्सिंग और गलत पहचान: Ghostscript इस फ़ाइल को पढ़कर संसाधित करने की प्रक्रिया में अनुमति सत्यापन चरण (द्वारपाल) को बिना किसी त्रुटि के पार कर जाता है।
OS शेल में स्थानांतरण: सत्यापन पार करने वाली कमांड स्ट्रीम पाइप डिवाइस सुविधा द्वारा लिनक्स के sh या विंडोज़ के cmd जैसे ऑपरेटिंग सिस्टम के आंतरिक शेल में सीधे पहुँचाई जाती है और बैकएंड अनुमतियों के साथ निष्पादित होती है।
पैच किए गए कोड को देखने पर निम्नलिखित दो .c फ़ाइलों में संशोधन होने की पुष्टि होती है।
base/gpmisc.cbase/gslibctx.cयहाँ gpmisc.c को देखकर ही भेद्यता को समझा जा सकता है।

इस भेद्यता का मूल यह है कि %pipe% जैसे विशेष पथ को सामान्य फ़ाइल पथ से ठीक से अलग नहीं किया जाता और उसे वैसे ही सामान्य पथ के रूप में पहचान लिया जाता है।
gp_file_name_reduceइसे सत्यापित करने के लिए फ़ाइल पथ को परिष्कृत करने वाले फ़ंक्शन पर ध्यान देना आवश्यक है। gpmisc.c में पथ को साफ करने का कार्य gp_file_name_reduce(...) करता है, और यह फ़ंक्शन आंतरिक रूप से gp_file_name_combine() को कॉल करके उसका परिणाम लौटाता है।
gp_file_name_reduce(const char *fname, uint flen, char *buffer, uint *blen) {
return gp_file_name_combine(fname, flen, fname + flen, 0, false, buffer, blen);
}
gp_file_name_combine() जैसा कि नाम से ही स्पष्ट है, प्राप्त फ़ाइल पथ से ./, // जैसी अनावश्यक सापेक्ष पथ अभिव्यक्तियों को हटाने वाला फ़ंक्शन है।
समस्या यहीं उत्पन्न होती है। यदि इस फ़ंक्शन में सामान्य फ़ाइल पथ के बजाय %pipe% जैसी कमांड निष्पादन को प्रेरित करने वाली विशेष स्ट्रिंग इनपुट की जाती है, तो फ़ंक्शन उसे वैध पथ पैटर्न के रूप में न पहचानते हुए बिना किसी प्रसंस्करण के मूल स्ट्रिंग को वैसे ही लौटा देता है।
gp_validate_path_len
gp_validate_path_len(...) आंतरिक रूप से gp_file_name_reduce() को कॉल करके पथ को सत्यापित करने वाला फ़ंक्शन है, लेकिन इस प्रक्रिया में यह अलग करने के लिए कोई अतिरिक्त सत्यापन लॉजिक मौजूद नहीं है कि इनपुट मान सामान्य फ़ाइल पथ है या %pipe% जैसी कमांड निष्पादन सिंटैक्स।
परिणामस्वरूप, %pipe% युक्त स्ट्रिंग बिना किसी फ़िल्टरिंग के वैसे ही पार हो जाती है, और यही इस भेद्यता का मूल कारण है।
इसलिए, जब %pipe%touch /tmp/pwned जैसी स्ट्रिंग फ़ाइल पथ के रूप में पास की जाती है, तो उपयोगकर्ता ने केवल एक छवि फ़ाइल रेंडर करना चाहा था, फिर भी वास्तव में touch /tmp/pwned कमांड निष्पादित होकर /tmp/pwned फ़ाइल बन जाती है।
┌─────────────────────────────────┐
│ Docker Container │
│ (Ubuntu 22.04 + Ghostscript) │
│ │
│ /home/test/ ← Working directory
│ ├── poc.py ← PoC 생성 스크립트
│ | |
│ └── /var/www/html/config.php ← 민감 정보 파일
│ │
│ User: test (비 root) │
│ Ghostscript: 10.01.1 (취약) │
└─────────────────────────────────┘
यहाँ root खाते के बजाय सामान्य खाते का चयन करने का कारण यह है कि वास्तविक उत्पादन सर्वर में सुरक्षा कारणों से आमतौर पर root खाते का सीधे उपयोग नहीं किया जाता। इसलिए, वास्तविक सर्वर पर हमले की स्थिति को यथासंभव निकटता से दोहराने के लिए पर्यावरण सामान्य खाते के आधार पर बनाया गया है।
version: '3.8'
services:
gs-lab:
build: .
container_name: cve_lab
network_mode: "host"
environment:
- DISPLAY=${DISPLAY}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:ro
- ./poc.py:/home/test/poc.py
stdin_open: true
tty: true
DISPLAY=${DISPLAY}: कंटेनर के भीतर GUI एप्लिकेशन को होस्ट के X11 डिस्प्ले सर्वर तक पहुँचने की अनुमति देने के लिए पर्यावरण चर पास करता है।/tmp/.X11-unix:/tmp/.X11-unix:ro: होस्ट के X11 डिस्प्ले सर्वर और कंटेनर के बीच संचार के लिए Unix सॉकेट को माउंट करता है।
./poc.py:/home/test/poc.py: होस्ट की स्थानीय PoC स्क्रिप्ट को कंटेनर निष्पादन वातावरण में माउंट करता है।
FROM ubuntu:22.04
RUN apt update && \
apt install -y \
wget \
build-essential \
gedit \
python3 \
sudo && \
rm -rf /var/lib/apt/lists/*
RUN wget https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10011/ghostscript-10.01.1.tar.gz && \
tar -xzf ghostscript-10.01.1.tar.gz
WORKDIR /ghostscript-10.01.1
RUN ./configure && \
make && \
make install
RUN mkdir -p /var/www/html && \
echo "DB_PASSWORD=SuperSecret1234!!!" > /var/www/html/config.php
RUN useradd -m -s /bin/bash test
WORKDIR /home/test
USER test
CMD ["/bin/bash"]
बुनियादी PoC वातावरण बनाने के लिए Ghostscript के भेद्य संस्करण को लाने हेतु wget, tar.gz निकालने के बाद स्रोत स्थापित करने के लिए build-essential, और .ps निष्पादित करते समय दुर्भावनापूर्ण रूप से खोले जाने वाले नोटपैड (gedit) जैसे उपकरण आवश्यक हैं।

Ghostscript भेद्य संस्करण 10.01.1 को git से स्रोत लाकर स्थापित किया गया। RUN ./configure && \ make && \ make install इसलिए चलाया गया क्योंकि स्रोत डाउनलोड किए गए फ़ोल्डर में उपयोग विधि लिखी हुई थी, इसलिए उसी के अनुसार स्थापना की गई।
आमतौर पर /var/www/html/config.php में वेब एप्लिकेशन की मुख्य कॉन्फ़िगरेशन मान होते हैं। उदाहरण के लिए, डेटाबेस का नाम, पासवर्ड
इसलिए, यह मानते हुए कि DB पासवर्ड चुराया जाएगा, config.php फ़ाइल बनाई जाती है।
चूँकि PoC को root खाते के बजाय सामान्य खाते test के साथ करने की योजना है, इसलिए एक नया उपयोगकर्ता बनाया जाता है।
# Docker 이미지 빌드
docker compose -f docker-compose.yml up -d
# 컨테이너 실행
docker exec -it cve_lab bash
कंटेनर के भीतर:

python3 poc.py -p "gedit /var/www/html/config.php" -m r -f test
निर्माण परिणाम:

दर्ज किया गया दुर्भावनापूर्ण पथ .ps के अंदर सही ढंग से डाला गया देखा जा सकता है।
gs -dNOSAFER test.ps

gedit स्वचालित रूप से खुलता है और /var/www/html/config.php की सामग्री प्रदर्शित हो जाती है।
DB_PASSWORD=SuperSecret1234!!!

आधिकारिक रूप से भेद्यता को ठीक करने वाले Ghostscript 10.01.2 या उससे अधिक नए संस्करण में अपडेट किया जाना चाहिए।
आधिकारिक पैच में gp_validate_path_len() फ़ंक्शन के भीतर gp_file_name_reduce() को कॉल करने से पहले सत्यापन करने वाला लॉजिक जोड़ा गया है।
पाइप विशेष स्ट्रिंग अपवाद हैंडलिंग और ब्लॉकिंग लागू करना: एक ब्रांच स्टेटमेंट जोड़ा गया है जो इनपुट पथ का उपसर्ग %pipe% या | प्रतीक से शुरू होने की स्थिति को अलग से पूरी तरह से पहचानता है।
आधिकारिक पैच संस्करण: https://github.com/ArtifexSoftware/ghostpdl/commit/5f56c6f6f989816fc9cc671116740acecbed5b6c