זה עתה ראינו כיצד פרצה קטנה מובילה להפסד כספי (בסדר גודל שונה), באופן דומה לחוזים חכמים שפותחו על פני סולידטי נוטים להתקפות שונות ומוכרות. הנצלנים מנצלים את היתרון של באגים, ופרצות להציץ בחוזים חכמים ולתפעל אותם לביצוע התקפות. כאן אנו מציגים רשימה מקיפה של חמש השגיאות המובילות הנפוצות ביותר בשפת התכנות Solidity.
ב- QuillAudits אנו עוקבים אחר המתודולוגיה ההסתגלותית כדי לקבל את תמצית כל פריצה וליישם את הלמידות שלה על חוזים חכמים עתידיים כדי למנוע כל איום אפשרי.
שגיאות בשפת התכנות סולידיות
1. שיחה חיצונית לא מסומנת
מלכתחילה אנו מושכים נושא זה מכיוון שהוא אחד ממלכודות המוצקות הנפוצות ביותר. באופן כללי, שליחת אתר לכל חשבון חיצוני מתבצעת באמצעות לְהַעֲבִיר() פוּנקצִיָה. מלבד זאת, שתי הפונקציות הנפוצות ביותר לביצוע שיחה חיצונית הן; שִׂיחָה(), ו שלח (), כאן בעיקר ה שִׂיחָה() פונקציה משמשת בהרחבה לביצוע שיחות חיצוניות צדדיות על ידי המפתחים.
דרך ה שִׂיחָה() ו שלח () פונקציות מחזירות ערך בוליאני המציין אם השיחה הצליחה או לא. כך במקרה זה, אם אחת מהפונקציות שִׂיחָה() or שלח () לא מצליח לבצע את המשימה, הם יחזרו עם שקר. לפיכך, אם היזם לא בודק את ערך ההחזר, הוא יהפוך למלכודת.
הפגיעות
שקול את הדוגמה הבאה:
חוזה לוטו {
boolpublic payedOut = false;
כתובת הזוכה בציבור;
winPublic winAmount;
// ... פונקציונליות נוספת כאן
פונקציה sendToWinner () ציבורית {
דורשים (! payedOut);
winner.send (winAmount);
payedOut = נכון;
}
function pullLeftOver () ציבורי {
דורשים (payedOut);
msg.sender.send (איזון זה);
}
}
בחוזה דמוי לוטו לעיל, אנו יכולים לראות כי א זוכה מקבל winAmount של אתר שמשאיר מעט שאריות להוצאה מכל גורם חיצוני.
כאן, מלכודת החוזה קיימת בשורה [11], שם א לשלוח משמש ללא אימות צולב של התגובה. בדוגמה שלעיל, א זוכה אשר העסקה שלהם נכשלת (מחסור בגז או אם מדובר בחוזה שגורם לפונקציה החזרת בכוונה). שולמה להיות מוגדר ל נָכוֹן לא משנה אם עסקת האתר הצליחה או לא. במקרה זה, כל מנצל יכול למשוך את של זוכה זכיות באמצעות לסגת משמאל פונקציה.
הגישה של QuillAudit
צוות המפתחים הביתי שלנו מתמודד עם הבאג הזה באמצעות [לְהַעֲבִיר] פונקציה במקום [לִשְׁלוֹחַ] פונקציה, שכן [העברה] תחזור אם עסקה חיצונית תחזור. ואם אתה משתמש ב- [שלח], בדוק תמיד את ערך ההחזר.
אחת הגישות החזקות שאנו נוקטים בהן היא שימוש בדפוס [נסיגה]. כאן אנו מבודדים באופן הגיוני את פונקציונליות השליחה החיצונית משאר בסיס הקוד, ומניחים את עומס העסקאות שעלולות להיכשל על משתמש הקצה, מכיוון שהוא זה שקורא לפונקציית המשיכה.
2. כניסה מחדש
החוזים החכמים של Ethereum מתקשרים ומשתמשים בקודים מחוזים חיצוניים אחרים, וכדי לבצע זאת, החוזים נדרשים להגיש שיחות חיצוניות. שיחות חיצוניות אלה פגיעות ונוטות להתקפות, התקפה כזו התרחשה לאחרונה במקרה של פריצת DAO.
הפגיעות
תוקפים מבצעים התקפות כאלה כאשר חוזה שולח אתר לכתובת לא ידועה. במקרה זה, התוקף יכול ליצור חוזה בכתובת חיצונית שיש לה קוד זדוני בפונקציית ה- fallback, וקוד זדוני זה יופעל כאשר החוזה ישלח אתר לכתובת זו.
עוּבדָה: המונח 'רנטרנס' נטבע מהעובדה שכאשר חוזה זדוני חיצוני קורא לפונקציה על פני החוזה הפגיע ואז נתיב ביצוע הקוד 'נכנס' אליו מחדש.
שקול את הדוגמה שלהלן, מדובר בכספת את'ריום המאפשרת למפקידים למשוך אתר אחד בלבד בשבוע.
חוזה EtherStore {
נסיגה ציבורית uint256 Limit = אתר 1;
מיפוי (כתובת => uint256) ציבורי lastWithdrawTime;
מיפוי (כתובת => uint256) יתרות ציבוריות;
פונקציה depositFunds () חיצוני לתשלום {
יתרות [msg.sender] + = msg.value;
}
פונקציה pullFunds (uint256 _weiToWithdraw) ציבורית {
דורשים (מאזנים [msg.sender]> = _weiToWithdraw);
// להגביל את הנסיגה
דורשים (_weiToWithdraw <= pullLimit);
// להגביל את הזמן המותר לסגת
דורשים (עכשיו> = lastWithdrawTime [msg.sender] + שבועיים);
דורש (msg.sender.call.value (_weiToWithdraw) ());
יתרות [msg.sender] - = _weiToWithdraw;
lastWithdrawTime [msg.sender] = עכשיו;
}
}
בחוזה הנ"ל יש לנו שתי פונקציות ציבוריות, [depositFunds] ו- [pullFunds]. [DepositFunds] משמש להגדלת יתרת השולח ואילו [FundFunds] מציין את הסכום שיש למשוך. במקרה זה, זו תהיה הצלחה אם הסכום שיש למשוך הוא פחות מאתר אחד.
המלכודת כאן נמצאת בשורה [17] בה מתרחש העברת האתר. התוקף יכול ליצור חוזה זדוני עם כתובת החוזה של [EtherStores] כפרמטר הבנאי היחיד. זה יהפוך את [etherStore] למשתנה ציבורי, ולכן נוטה יותר להיות מותקף.
הגישה של QuilllAudit
אנו עוקבים אחר טכניקות שונות כדי למנוע פגיעות חוזרות אפשריות בחוזים חכמים. הדרך הראשונה והטובה ביותר היא השימוש בפונקציה המובנית [העברה] בעת העברת אתר לכל חוזה חיצוני.
שנית, חשוב לוודא כי כל השינויים ההגיוניים במשתני המצב צריכים להיעשות לפני שליחת האתר מחוץ לחוזה. בדוגמה [EtherStore], שורות [18] ו- [19] צריכות להיות מונחות לפני שורה [17].
ניתן להשתמש בטכניקה שלישית גם כדי למנוע שיחות חוזרות; דרך הצגת מוטקס. זו תוספת של משתנה מדינה שינעל את החוזה במהלך ביצוע הקוד.
3. נראות ברירת מחדל
ישנם מפרט נראות לפונקציות בהן אנו משתמשים ב- Solidity, והם קובעים את האופן שבו ניתן לקרוא להם. הנראות היא שקובעת את קריאת הפונקציות; באופן חיצוני על ידי משתמשים, על ידי חוזים נגזרים אחרים, רק באופן פנימי או רק חיצוני. בואו נסתכל כיצד שימוש שגוי במפרט מראות יכול לגרום לפגיעות עצומה בחוזים חכמים.
הפגיעות
כברירת מחדל, הנראות של הפונקציה היא [ציבורית], ומכאן שהמשתמשים החיצוניים יכולים להתקשר לפונקציות ללא נראות ספציפית. הבאג נוצר כאשר מפתחים שוכחים לציין נראות בפונקציות שצריכות להיות פרטיות (או שניתן לקרוא להן במסגרת החוזה עצמו). לדוגמה;
חוזה HashForEther {
פונקציה pullWinnings () {
// זוכה אם שמונה תווי המשושה האחרונים של הכתובת הם 8
דורש (uint32 (msg.sender) == 0);
_sendWinnings ();
}
פונקציה _sendWinnings () {
msg.sender.transfer (איזון זה);
}
}
החוזה הנ"ל הוא משחק שפע של ניחוש כתובות. בכך אנו יכולים לראות כי לא מוגדרת נראות הפונקציות, במיוחד הפונקציה [_sendWinnings] היא [ציבורית] (כברירת מחדל), ומכאן שניתן לקרוא לכך דרך כל כתובת כדי לגנוב את השפע.
הגישה של QuillAudit
הצוות הביתי שלנו מורכב ממפתחים מנוסים שעוקבים תמיד אחר שיטות הביקורת הטובות ביותר. כאן יש לציין במפורש את נראות הפונקציות, גם אם יש לשמור על פומביות, יש להזכיר זאת.
4. שמירה על השימוש בבונים
באופן כללי, קונסטרוקטורים נקראים פונקציות מיוחדות המשמשות לביצוע משימות קריטיות ומועילות בעת אתחול החוזים. לפני המוצקות [v0.4.22], הקבלנים החזיקו באותו שם שהחוזה הכיל בהם. כעת שקול מקרה בו שם החוזה שונה במהלך שלב הפיתוח אך שם הבנאי נותר זהה, פרצה זו יכולה גם לספק לתוקפים כניסה קלה לחוזה החכם שלך.
הפגיעות
זה יכול להוביל לתוצאות חמורות אם שם החוזה שונה אך שם הקונסטרוקטור ללא שינוי. לדוגמה:
חוזה OwnerWallet {
כתובת בעל ציבור;
// קונסטרוקטור
function ownerWallet (כתובת _בעלים) ציבורי {
בעל = _בעלים;
}
// לסגת. אסוף אתר.
function () יש לשלם {}
פונקציה למשוך () ציבורי {
לדרוש (msg.sender == בעל);
msg.sender.transfer (איזון זה);
}
}
בחוזה הנ"ל אנו יכולים לראות שרק הבעלים יכול למשוך אתר באמצעות קריאה לפונקציה [למשוך]. כאן, הפגיעות מתרחשת כאשר שמו של הקונסטרוקטור שונה מהחוזה (האות הראשונה שונה!). כך מנצל יכול להתקשר לפונקציה [ownerWallet] ולהסמיך את עצמם כבעלים, ואז למשוך את כל האתר בחוזה על ידי קריאה [למשוך].
הגישה של QuillAudit
אנו מצייתים לגרסה [0.4.22] של מהדר המוצקות. גרסה זו הציגה מילת מפתח; [בונה] המחייב את שם הפונקציה כדי להתאים לשם החוזה.
5. אימות מקור
כאן, [Tx.Origin] הוא המשתנה הגלובלי של Solidity, והוא מכיל את כתובת החשבון שביצע במקור את השיחה או העסקה. לא ניתן להשתמש במשתנה זה לאימות, שכן פעולה זו הופכת את החוזה לפגיע להתקפות דיוג.
הפגיעות
חוזים המאשרים משתמשים באמצעות המשתנה [tx.origin] חשופים להתקפות חיצוניות המובילות משתמשים לבצע פעולות מאומתות על החוזה השגוי. שקול את הדוגמה הבאה:
חוזה Phishable {
כתובת בעל ציבור;
קונסטרוקטור (כתובת _בעלים) {
בעל = _בעלים;
}
function () לתשלום חיצוני {} // לאסוף אתר
פונקציה pullAll (כתובת _קבל) ציבורית {
לדרוש (tx.origin == בעל);
_recipient.transfer (איזון זה);
}
}
כאן בשורה [11], החוזה מסמיך את הפונקציה [pullAll] בעזרת [tx.origin].
הגישה של QuillAudit
בדרך כלל אנו נמנעים משימוש ב- [tx.origin] לצורך הרשאה בחוזים חכמים. למרות שהשימוש ב- [tx.origin] אינו אסור בהחלט, יש בו כמה מקרי שימוש ספציפיים. אנו יכולים להשתמש ב- [tx.origin] כדי למנוע מחוזים חיצוניים להתקשר לחוזה הנוכחי, ניתן לבצע אותו באמצעות [דרישה] של הטופס [דורש (tx.origin == msg.sender)]. זה נעשה כדי להימנע מקריאה של חוזי ביניים להתקשר לחוזה הנוכחי שמגביל את החוזה לכתובות רגילות ללא קוד.
סיום סיום
כיסינו באופן מקיף את חמש המלכודות הנפוצות בשפת המוצקות. בעת פיתוח חוזים חכמים, אסור לנו לשכוח שהם בלתי ניתנים לשינוי על ידי עיצובם, מה שאומר שברגע שניצור אותם, אין שום דרך לתקן את קוד המקור.
זה מהווה אתגר גדול בפני מפתחים לנצל את היתרון של בדיקות אבטחה וכלי ביקורת זמינים לפני הפריסה.
גילוי איומים זדוניים פוטנציאליים לחוזים החכמים, והסיכונים שחלקם הזכרנו לעיל מתבצעים בצורה ייחודית וחזקה מאוד על ידי צוות מומחי הביקורת שלנו. אנו ב- QuillAudits משקיעים את מירב המאמצים במחקר אבטחה בכדי לעדכן את החוזה שלכם בכל שיטות האבטחה של התוכנה בכדי לשמור על אבטחת החוזה שלכם.
פנה אל קווילהאש
עם נוכחות בתעשייה של שנים, QuillHash סיפקה פתרונות ארגוניים ברחבי העולם. QuillHash עם צוות מומחים הינה חברה מובילה לפיתוח בלוקצ'יין המספקת פתרונות שונים בתעשייה, כולל Enterprise DeFi. אם אתה זקוק לסיוע כלשהו בביקורת החוזים החכמים, אל תהסס לפנות למומחים שלנו כאן!
עקוב אחר QuillHash לקבלת עדכונים נוספים
מקור: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- חֶשְׁבּוֹן
- יתרון
- תעשיות
- בדיקה
- אימות
- אישור
- הטוב ביותר
- blockchain
- חרק
- באגים
- שיחה
- מקרים
- לגרום
- לאתגר
- קוד
- Common
- חברה
- חוזה
- חוזים
- נוֹכְחִי
- DAO
- DeFi
- עיצוב
- מפתח
- מפתחים
- צעצועי התפתחות
- מִפְעָל
- אתר
- ethereum
- אירוע
- מומחים
- פייסבוק
- כספי
- ראשון
- לעקוב
- טופס
- חופשי
- פונקציה
- עתיד
- מִשְׂחָק
- גז
- גלוֹבָּלִי
- גדול
- לפרוץ
- כאן
- איך
- HTTPS
- עצום
- כולל
- תעשייה
- IT
- שפה
- עוֹפֶרֶת
- מוביל
- קו
- לינקדין
- רשימה
- להתאים
- אחר
- בעלים
- תיקון
- תבנית
- דיוג
- התקפות פישינג
- לקבוע
- להציג
- פְּרָטִי
- תכנות
- ציבורי
- מושך
- מחקר
- תגובה
- REST
- בטוח
- אבטחה
- שירותים
- סט
- פָּשׁוּט
- קטן
- חכם
- חוזה חכם
- חוזים חכמים
- So
- תוכנה
- מוּצָקוּת
- פתרונות
- מדינה
- הצלחה
- בדיקות
- המקור
- איומים
- זמן
- חלק עליון
- 5 העליון
- עסקה
- עסקות
- us
- משתמשים
- ערך
- קמרון
- ראות
- פגיעויות
- פגיעות
- פגיע
- שבוע
- מי
- בתוך
- שנים