प्रमुख मजकुराकडे जा

स्मार्ट कॉन्ट्रॅक्ट बग शोधण्यासाठी Slither कसे वापरावे

सॉलिडिटी
स्मार्ट कॉन्ट्रॅक्ट
सुरक्षा
चाचणी
प्रगत
Trailofbits
९ जून, २०२०
7 मिनिट वाचन

Slither कसे वापरावे

या ट्यूटोरियलचा उद्देश स्मार्ट कॉन्ट्रॅक्ट्समध्ये आपोआप बग शोधण्यासाठी Slither कसे वापरावे हे दर्शविणे आहे.

इन्स्टॉलेशन

Slitherसाठी Python >= 3.6 आवश्यक आहे. हे pip द्वारे किंवा docker वापरून इंस्टॉल केले जाऊ शकते.

pip द्वारे Slither:

pip3 install --user slither-analyzer

docker द्वारे Slither:

docker pull trailofbits/eth-security-toolbox
docker run -it -v "$PWD":/home/trufflecon trailofbits/eth-security-toolbox

शेवटचा कमांड तुमच्या सध्याच्या डिरेक्टरीमध्ये ऍक्सेस असलेल्या docker मध्ये eth-security-toolbox चालवतो. तुम्ही तुमच्या होस्टमधून फाइल्स बदलू शकता, आणि docker मधून फाइल्सवर टूल्स चालवू शकता

docker मध्ये, चालवा:

solc-select 0.5.11
cd /home/trufflecon/

स्क्रिप्ट चालवणे

python 3 सह python स्क्रिप्ट चालवण्यासाठी:

python3 script.py

कमांड लाईन

कमांड लाइन विरुद्ध युजर-डिफाइंड स्क्रिप्ट्स. Slither पूर्वनिर्धारित डिटेक्टरच्या सेटसह येते जे अनेक सामान्य बग शोधतात. कमांड लाइनवरून Slitherला कॉल केल्यास सर्व डिटेक्टर चालतील, स्टॅटिक विश्लेषणाच्या तपशीलवार ज्ञानाची आवश्यकता नाही:

slither project_paths

डिटेक्टर्स व्यतिरिक्त, Slitherमध्ये त्याच्या प्रिंटर्स (opens in a new tab) आणि टूल्स (opens in a new tab) द्वारे कोड पुनरावलोकन क्षमता आहेत.

प्रायव्हेट डिटेक्टर आणि GitHub इंटिग्रेशनमध्ये प्रवेश मिळविण्यासाठी crytic.io (opens in a new tab) वापरा.

स्थिर विश्लेषण

Slither स्टॅटिक अ‍ॅनालिसिस फ्रेमवर्कची क्षमता आणि डिझाइन ब्लॉग पोस्ट्समध्ये (1 (opens in a new tab), 2 (opens in a new tab)) आणि एका अकॅडमिक पेपरमध्ये (opens in a new tab) वर्णन केले आहे.

स्टॅटिक विश्लेषण विविध प्रकारांमध्ये अस्तित्वात आहे. तुम्हाला कदाचित याची जाणीव असेल की clang (opens in a new tab) आणि gcc (opens in a new tab) सारखे कंपाइलर या संशोधन तंत्रांवर अवलंबून असतात, परंतु ते Infer (opens in a new tab), CodeClimate (opens in a new tab), FindBugs (opens in a new tab) आणि Frama-C (opens in a new tab) आणि Polyspace (opens in a new tab) सारख्या औपचारिक पद्धतींवर आधारित टूल्सला देखील आधार देते.

आम्ही येथे स्टॅटिक विश्लेषण तंत्र आणि संशोधकाचे संपूर्ण पुनरावलोकन करणार नाही. त्याऐवजी, Slither कसे कार्य करते हे समजून घेण्यासाठी काय आवश्यक आहे यावर आम्ही लक्ष केंद्रित करू जेणेकरून आपण बग शोधण्यासाठी आणि कोड समजून घेण्यासाठी अधिक प्रभावीपणे त्याचा वापर करू शकाल.

कोड रिप्रेझेंटेशन

डायनॅमिक विश्लेषणाच्या विपरीत, जे एकाच एक्झिक्युशन पाथबद्दल तर्क करते, स्टॅटिक विश्लेषण एकाच वेळी सर्व पाथबद्दल तर्क करते. असे करण्यासाठी, ते एका वेगळ्या कोड रिप्रेझेंटेशनवर अवलंबून असते. यातील दोन सर्वात सामान्य म्हणजे अ‍ॅबस्ट्रॅक्ट सिंटॅक्स ट्री (AST) आणि कंट्रोल फ्लो ग्राफ (CFG).

अ‍ॅबस्ट्रॅक्ट सिंटॅक्स ट्री (AST)

जेव्हाही कंपाइलर कोड पार्स करतो तेव्हा AST वापरले जातात. ही कदाचित सर्वात मूलभूत रचना आहे ज्यावर स्टॅटिक विश्लेषण केले जाऊ शकते.

थोडक्यात सांगायचे झाल्यास, AST एक संरचित ट्री आहे जिथे, सामान्यतः, प्रत्येक लीफमध्ये एक व्हेरिएबल किंवा एक कॉन्स्टंट असते आणि इंटरनल नोड्स ऑपरेंड किंवा कंट्रोल फ्लो ऑपरेशन्स असतात. पुढील कोड विचारात घ्या:

1function safeAdd(uint a, uint b) pure internal returns(uint){
2 if(a + b <= a){
3 revert();
4 }
5 return a + b;
6}

संबंधित AST यात दर्शविले आहे:

AST

Slither solc द्वारे एक्सपोर्ट केलेले AST वापरते.

तयार करण्यास सोपे असले तरी, AST एक नेस्टेड रचना आहे. काहीवेळा, विश्लेषण करणे हे सर्वात सोपे नसते. उदाहरणार्थ, a + b <= a या एक्सप्रेशनद्वारे वापरल्या जाणार्‍या ऑपरेशन्स ओळखण्यासाठी, तुम्हाला प्रथम <= आणि नंतर + चे विश्लेषण करणे आवश्यक आहे. एक सामान्य दृष्टिकोन म्हणजे तथाकथित व्हिजिटर पॅटर्न वापरणे, जे रिकर्सिव्हली ट्रीमधून नेव्हिगेट करते. Slitherमध्ये ExpressionVisitor (opens in a new tab) मध्ये एक जेनेरिक व्हिजिटर आहे.

पुढील कोड एक्सप्रेशनमध्ये अ‍ॅडिशन आहे की नाही हे शोधण्यासाठी ExpressionVisitor वापरतो:

1from slither.visitors.expression.expression import ExpressionVisitor
2from slither.core.expressions.binary_operation import BinaryOperationType
3
4class HasAddition(ExpressionVisitor):
5
6 def result(self):
7 return self._result
8
9 def _post_binary_operation(self, expression):
10 if expression.type == BinaryOperationType.ADDITION:
11 self._result = True
12
13visitor = HasAddition(expression) # expression is the expression to be tested
14print(f'The expression {expression} has a addition: {visitor.result()}')
सर्व दाखवा

कंट्रोल फ्लो ग्राफ (CFG)

दुसरे सर्वात सामान्य कोड रिप्रेझेंटेशन म्हणजे कंट्रोल फ्लो ग्राफ (CFG). त्याच्या नावाप्रमाणेच, हे ग्राफ-आधारित रिप्रेझेंटेशन आहे जे सर्व एक्झिक्युशन पाथ उघड करते. प्रत्येक नोडमध्ये एक किंवा अनेक सूचना असतात. ग्राफमधील एजेस कंट्रोल फ्लो ऑपरेशन्स (if/then/else, लूप, इत्यादी) दर्शवतात. आमच्या मागील उदाहरणाचा CFG आहे:

CFG

CFG हे असे रिप्रेझेंटेशन आहे ज्यावर बहुतेक विश्लेषणे तयार केली जातात.

इतर अनेक कोड रिप्रेझेंटेशन्स अस्तित्वात आहेत. तुम्ही करू इच्छित असलेल्या विश्लेषणानुसार प्रत्येक रिप्रेझेंटेशनचे फायदे आणि तोटे आहेत.

विश्लेषण

Slitherसह तुम्ही करू शकता असे सर्वात सोपे प्रकारचे विश्लेषण म्हणजे सिंटॅक्टिक विश्लेषण.

सिंटॅक्स विश्लेषण

Slither पॅटर्न मॅचिंग सारखा दृष्टीकोन वापरून विसंगती आणि दोष शोधण्यासाठी कोडच्या विविध घटकांमधून आणि त्यांच्या रिप्रेझेंटेशनमधून नेव्हिगेट करू शकते.

उदाहरणार्थ, खालील डिटेक्टर सिंटॅक्स-संबंधित समस्या शोधतात:

सिमॅंटिक विश्लेषण

सिंटॅक्स विश्लेषणाच्या विपरीत, सिमॅंटिक विश्लेषण अधिक खोलवर जाईल आणि कोडचा “अर्थ” विश्लेषण करेल. या फॅमिलीमध्ये काही व्यापक प्रकारचे विश्लेषण समाविष्ट आहेत. ते अधिक शक्तिशाली आणि उपयुक्त परिणामांकडे नेतात, परंतु लिहिण्यासही अधिक क्लिष्ट आहेत.

सर्वात प्रगत व्हल्नरेबिलिटी डिटेक्शनसाठी सिमॅंटिक विश्लेषण वापरले जाते.

डेटा डिपेंडन्सी विश्लेषण

एखादे व्हेरिएबल variable_a हे variable_b वर डेटा-डिपेंडंट आहे असे म्हटले जाते, जर असा एखादा मार्ग असेल ज्यासाठी variable_a चे मूल्य variable_b द्वारे प्रभावित होते.

पुढील कोडमध्ये, variable_a हे variable_b वर अवलंबून आहे:

1// ...
2variable_a = variable_b + 1;

Slither अंगभूत डेटा डिपेंडन्सी (opens in a new tab) क्षमतेसह येते, त्याच्या इंटरमीडिएट रिप्रेझेंटेशनमुळे (नंतरच्या विभागात चर्चा केली आहे).

डेटा डिपेंडन्सी वापराचे उदाहरण डेंजरस स्ट्रिक्ट इक्वलिटी डिटेक्टर (opens in a new tab) मध्ये आढळू शकते. येथे Slither एका धोकादायक मूल्याशी स्ट्रिक्ट इक्वलिटी कंपॅरिझन शोधेल (incorrect_strict_equality.py#L86-L87 (opens in a new tab)), आणि वापरकर्त्याला सूचित करेल की त्याने >= किंवा <= ऐवजी == वापरावे, जेणेकरून अटॅकरला कॉन्ट्रॅक्टमध्ये अडकवण्यापासून रोखता येईल. इतर गोष्टींबरोबरच, डिटेक्टर balanceOf(address) (incorrect_strict_equality.py#L63-L64 (opens in a new tab)) ला केलेल्या कॉलचे रिटर्न व्हॅल्यू धोकादायक मानेल आणि त्याचा वापर ट्रॅक करण्यासाठी डेटा डिपेंडन्सी इंजिन वापरेल.

फिक्स्ड-पॉइंट संगणन

जर तुमचे विश्लेषण CFG मधून नेव्हिगेट करत असेल आणि एजेसचे अनुसरण करत असेल, तर तुम्हाला आधीच भेट दिलेले नोड्स दिसण्याची शक्यता आहे. उदाहरणार्थ, जर एखादे लूप खाली दर्शविल्याप्रमाणे सादर केले असेल तर:

1for(uint i; i < range; ++){
2 variable_a += 1
3}

तुमच्या विश्लेषणाला केव्हा थांबायचे हे माहित असणे आवश्यक आहे. येथे दोन मुख्य धोरणे आहेत: (1) प्रत्येक नोडवर मर्यादित वेळा पुनरावृत्ती करणे, (2) तथाकथित फिक्सपॉइंट मोजणे. फिक्सपॉइंटचा मुळात अर्थ असा आहे की या नोडचे विश्लेषण केल्याने कोणतीही अर्थपूर्ण माहिती मिळत नाही.

फिक्सपॉइंट वापराचे उदाहरण रीएन्ट्रन्सी डिटेक्टरमध्ये आढळू शकते: Slither नोड्स एक्सप्लोर करते, आणि एक्सटर्नल कॉल्स, स्टोरेजमध्ये लिहिणे आणि वाचणे शोधते. एकदा ते फिक्सपॉइंटवर पोहोचले की (reentrancy.py#L125-L131 (opens in a new tab)), ते एक्सप्लोरेशन थांबवते, आणि रीएन्ट्रन्सी आहे की नाही हे पाहण्यासाठी परिणामांचे विश्लेषण करते, वेगवेगळ्या रीएन्ट्रन्सी पॅटर्नद्वारे (reentrancy_benign.py (opens in a new tab), reentrancy_read_before_write.py (opens in a new tab), reentrancy_eth.py (opens in a new tab)).

कार्यक्षम फिक्स्ड पॉइंट संगणन वापरून विश्लेषण लिहिण्यासाठी विश्लेषण त्याची माहिती कशी प्रसारित करते याची चांगली समज आवश्यक आहे.

इंटरमीडिएट रिप्रेझेंटेशन

इंटरमीडिएट रिप्रेझेंटेशन (IR) ही मूळ भाषेपेक्षा स्टॅटिक विश्लेषणासाठी अधिक सोयीची अशी भाषा आहे. Slither Solidity चे स्वतःच्या IR मध्ये भाषांतर करते: SlithIR (opens in a new tab).

जर तुम्हाला फक्त मूलभूत तपासण्या लिहायच्या असतील तर SlithIR समजून घेणे आवश्यक नाही. तथापि, जर तुम्ही प्रगत सिमॅंटिक विश्लेषण लिहिण्याची योजना आखत असाल तर ते उपयोगी पडेल. SlithIR (opens in a new tab) आणि SSA (opens in a new tab) प्रिंटर तुम्हाला कोडचे भाषांतर कसे केले जाते हे समजण्यास मदत करतील.

API बेसिक्स

Slitherकडे एक API आहे जे तुम्हाला कॉन्ट्रॅक्ट आणि त्याच्या फंक्शन्सचे मूलभूत गुणधर्म एक्सप्लोर करू देते.

कोडबेस लोड करण्यासाठी:

1from slither import Slither
2slither = Slither('/path/to/project')
3

कॉन्ट्रॅक्ट्स आणि फंक्शन्स एक्सप्लोर करणे

Slither ऑब्जेक्टमध्ये आहे:

  • contracts (list(Contract): कॉन्ट्रॅक्ट्सची सूची
  • contracts_derived (list(Contract): दुसऱ्या कॉन्ट्रॅक्टद्वारे वारसा न मिळालेल्या कॉन्ट्रॅक्ट्सची सूची (कॉन्ट्रॅक्ट्सचा उपसंच)
  • get_contract_from_name (str): त्याच्या नावावरून एक कॉन्ट्रॅक्ट परत करा

Contract ऑब्जेक्टमध्ये आहे:

  • name (str): कॉन्ट्रॅक्टचे नाव
  • functions (list(Function)): फंक्शन्सची सूची
  • modifiers (list(Modifier)): फंक्शन्सची सूची
  • all_functions_called (list(Function/Modifier)): कॉन्ट्रॅक्टद्वारे पोहोचता येणाऱ्या सर्व अंतर्गत फंक्शन्सची सूची
  • inheritance (list(Contract)): इनहेरिटेड कॉन्ट्रॅक्ट्सची सूची
  • get_function_from_signature (str): त्याच्या सिग्ननेचरवरून एक फंक्शन परत करा
  • get_modifier_from_signature (str): त्याच्या सिग्ननेचरवरून एक मॉडिफायर परत करा
  • get_state_variable_from_name (str): त्याच्या नावावरून एक स्टेटव्हेरिएबल परत करा

Function किंवा Modifier ऑब्जेक्टमध्ये आहे:

  • name (str): फंक्शनचे नाव
  • contract (contract): कॉन्ट्रॅक्ट जिथे फंक्शन घोषित केले आहे
  • nodes (list(Node)): फंक्शन/मॉडिफायरच्या CFG ची रचना करणाऱ्या नोड्सची सूची
  • entry_point (Node): CFG चा एंट्री पॉइंट
  • variables_read (list(Variable)): वाचलेल्या व्हेरिएबल्सची सूची
  • variables_written (list(Variable)): लिहिलेल्या व्हेरिएबल्सची सूची
  • state_variables_read (list(StateVariable)): वाचलेल्या स्टेट व्हेरिएबल्सची सूची (व्हेरिएबल्स`read चा उपसंच)
  • state_variables_written (list(StateVariable)): लिहिलेल्या स्टेट व्हेरिएबल्सची सूची (व्हेरिएबल्स`written चा उपसंच)

पृष्ठ अखेरचे अद्यतन: ३ फेब्रुवारी, २०२५

हे मार्गदर्शन उपयुक्त होते का?