Env x = '() {:;}; komut 'bash yapmak ve neden güvensiz?


237

Görünüşe göre bash'da bir güvenlik açığı (CVE-2014-6271) var: Bash özel hazırlanmış çevre değişkenleri kod ekleme saldırısı

Ne olduğunu anlamaya çalışıyorum, ama anladığımdan tam olarak emin değilim. echoTekil alıntılarda olduğu gibi nasıl yürütülür?

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test

EDIT 1 : Yamalı bir sistem şöyle görünür:

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test

EDIT 2 : Biraz farklı bir test kullanan ilgili bir güvenlik açığı / düzeltme eki: CVE-2014-7169 var:

$ env 'x=() { :;}; echo vulnerable' 'BASH_FUNC_x()=() { :;}; echo vulnerable' bash -c "echo test"

Yamasız çıktı :

vulnerable
bash: BASH_FUNC_x(): line 0: syntax error near unexpected token `)'
bash: BASH_FUNC_x(): line 0: `BASH_FUNC_x() () { :;}; echo vulnerable'
bash: error importing function definition for `BASH_FUNC_x'
test

kısmen (erken versiyon) yamalı çıktı :

bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
bash: error importing function definition for `BASH_FUNC_x()'
test

CVE-2014-7169’a aşağıdakiler dahil olmak üzere yamalı çıktı :

bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `BASH_FUNC_x'
test

EDIT 3 : hikaye devam ediyor:


İdam edilecek yankı değil. x'in işlev tanımı. Eğer x ile tanımlanan fonksiyon bazı sinsi çalışmalarda bulunursa, x fonksiyonunun gerçek olup olmadığını anlamak için bash'ın dönüş değerini kontrol etmesinin imkanı yoktur. Test kodunda fonksiyonun boş olduğuna dikkat edin. İşaretlenmemiş bir dönüş değeri, komut dosyası enjeksiyonuna neden olabilir. Komut dosyası enjeksiyonu ayrıcalık yükselmesine ve ayrıcalık yükselmesine kök erişimine neden olur. Yama işlev olarak x'in oluşturulmasını
engelliyor

26
eyoung100, hiçbir yankı edilir infaz alıyorum. Kelime vulnerableçıktıda göründüğü için yürütüldüğünü görebilirsiniz . Asıl sorun, bash'ın fonksiyon tanımlamasından sonra da kodu ayrıştırıp çalıştırmasıdır . Bkz /bin/idbölümünü seclists.org/oss-sec/2014/q3/650 başka örnek.
Mikel

4
Sadece hızlı bir yorum. Red Hat, serbest bırakılan yamanın yalnızca kısmi bir yama olduğunu ve sistemleri hala risk altında bıraktığını bildirmiştir.
Peter

2
@ eyoung100 farkı, işlev içindeki kodun yalnızca ortam değişkeni açıkça çağrıldığında çalıştırılmasıdır. İşlev tanımından sonraki kod, yeni bir Bash işlemi her başlatıldığında yürütülür.
David Farrell

1
Bkz stackoverflow.com/questions/26022248/... fazla ayrıntı için
barmar

Yanıtlar:


204

bash, dışa aktarılan işlev tanımlarını ortam değişkenleri olarak saklar. Dışa aktarılan işlevler şuna benzer:

$ foo() { bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() {  bar
}

Başka bir deyişle, ortam değişkeni foodeğişmez içeriğe sahiptir:

() {  bar
}

Yeni bir bash örneği başladığında, bu özel hazırlanmış ortam değişkenlerini arar ve bunları işlev tanımları olarak yorumlar. Birini kendiniz bile yazabilir ve hala çalıştığını görebilirsiniz:

$ export foo='() { echo "Inside function"; }'
$ bash -c 'foo'
Inside function

Ne yazık ki, fonksiyon tanımlarının karakter dizilerinden (ortam değişkenleri) ayrıştırılması amaçlanandan daha geniş etkilere sahip olabilir. Yamalı versiyonlarda, fonksiyon tanımlamasının sona ermesinden sonra oluşan rastgele komutları da yorumlar. Bu, ortamdaki kabul edilebilir işlev benzeri dizgilerin belirlenmesinde yetersiz kısıtlamalardan kaynaklanmaktadır. Örneğin:

$ export foo='() { echo "Inside function" ; }; echo "Executed echo"'
$ bash -c 'foo'
Executed echo
Inside function

İşlev tanımı dışındaki eko işleminin bash başlatma sırasında beklenmedik bir şekilde yürütüldüğünü unutmayın. İşlev tanımı, değerlendirme ve istismarın gerçekleşmesi için yalnızca bir adımdır, işlev tanımının kendisi ve kullanılan ortam değişkeni keyfidir. Kabuk, çevre değişkenlerine bakar, görür foo, bir işlev tanımının neye benzediği ile ilgili bildiği kısıtlamaları karşılar gibi görünür ve hatta istemeden ekoyu uygulayan (herhangi bir komut olabilir, kötü amaçlı olabilir) çizgiyi değerlendirir.

Bu, güvensiz olarak kabul edilir, çünkü değişkenlere genellikle kendi içinde bulunan rasgele kodların çağrılmasına doğrudan neden olmalarına izin verilmez veya beklenmez. Belki de programınız ortam değişkenlerini güvenilmeyen kullanıcı girişinden ayarlar. Bu ortam değişkenlerinin, kodda belirtilen bir nedenden dolayı bu ortam değişkenini kullanarak açıkça yapma niyetiniz olmadan, kullanıcının keyfi komutları çalıştırabileceği şekilde manipüle edilebileceği oldukça beklenmedik olacaktır.

İşte uygun bir saldırı örneği. Bir yerde savunmasız bir kabuk çalıştıran bir web sunucusunu ömrünün bir parçası olarak çalıştırıyorsunuz. Bu web sunucusu ortam değişkenlerini bir bash betiğine geçirir, örneğin, eğer CGI kullanıyorsanız, HTTP isteği hakkındaki bilgiler genellikle web sunucusundan ortam değişkenleri olarak dahil edilir. Örneğin, HTTP_USER_AGENTkullanıcı aracınızın içeriğine ayarlanmış olabilir. Bunun anlamı, kullanıcı temsilcinizi şunun gibi bir şeyle kandırırsanız, '() {:; }; echo foo ', bu kabuk betiği çalıştığında echo fooçalıştırılacak. Yine, echo fookötü ya da kötü bir şey olabilir.


3
Bu, Zsh gibi, başka bir Bash benzeri kabuğunu etkileyebilir mi?
Amelio Vazquez-Reina

3
@ user815423426 Hayır, zsh bu özelliğe sahip değildir. Ksh var, ancak farklı şekilde uygulandı, bence işlevler sadece çok zor şartlarda, ancak kabuk çevreden değil, çatallarsa iletilebilir.
Gilles

20
@ user815423426 rc, ortamdaki işlevleri ileten diğer kabuktur, ancak "fn_" ile önceden eklenmiş adlara sahip değişkendir ve yalnızca çağrıldığında yorumlanırlar.
Stéphane Chazelas 24:14

18
@ StéphaneChazelas - hatayı bildirdiğiniz için teşekkür ederiz.
Deer Hunter

13
@gnclmorais Sen çalıştırmak demek export bar='() { echo "bar" ; }'; zsh -c barve görüntüler baryerine zsh:1: command not found: bar? Testi kurmak için kullandığınız kabukla karıştırdığınız kabuğu karıştırmayacağınıza emin misiniz?
Gilles

85

Bu, neler olduğunu daha fazla göstermeye yardımcı olabilir:

$ export dummy='() { echo "hi"; }; echo "pwned"'
$ bash
pwned
$

Korunmasız bir kabuk çalıştırıyorsanız, yeni bir alt kabuk başlattığınızda (burada, bash deyimini kullanarak), rasgele kodun ( echo "pwned") hemen başlatılmasının bir parçası olarak yürütüldüğünü görürsünüz . Görünüşe göre, kabuk ortam değişkeninin (kukla) bir fonksiyon tanımı içerdiğini görür ve bu fonksiyonu kendi ortamında tanımlamak için tanımı değerlendirir (fonksiyonu yerine getirmediğine dikkat edin: 'hi' yazacaktır).

Ne yazık ki, yalnızca işlev tanımını değerlendirmekle kalmaz, işlev tanımını izleyen olası zararlı ifadeleri de içeren çevre değişkeninin değerinin tüm metnini değerlendirir. İlk işlev tanımı olmadan, ortam değişkeninin değerlendirilmeyeceğini, yalnızca çevreye metin dizesi olarak ekleneceğini unutmayın. Chris Down'ın da belirttiği gibi, dışa aktarılan kabuk fonksiyonlarının ithalatını uygulamak için özel bir mekanizma budur.

Yeni kabukta tanımlanmış işlevi görebiliriz (ve orada dışa aktarılmış olarak işaretlendi) ve uygulayabiliriz. Dahası, kukla bir metin değişkeni olarak alınmamıştır:

$ declare -f
dummy ()
{
    echo "hi"
}
declare -fx dummy
$ dummy
hi
$echo $dummy
$

Ne bu fonksiyonun yaratılması ne de ne yapılması gerekiyorsa çalıştırılması, istismarın bir parçası - yalnızca sömürünün uygulandığı araç. Asıl nokta, eğer bir saldırgan, dışa aktarılan bir ortam değişkenine konan bir metin dizesinde, asgari ve önemsiz bir işlev tanımından önce kötü amaçlı kod sağlayabiliyorsa, o zaman ortak bir olay olan bir alt kabuk başlatıldığında çalıştırılacak olan birçok senaryoda. Ayrıca, senaryonun imtiyazları ile yürütülecektir.


17
Kabul edilen cevap aslında bunu dikkatlice okursanız söylese de, bu cevabı problemin tanımının (işlevin kendisinin yerine çalışmak yerine) değerlendirilmesi olduğunu anlamada daha net ve yararlı buldum .
natevw

1
exportDiğerleri varken bu örnekte neden emir var env? i düşündüğünü envbir Bash kabuk başlatıldığında aranmak çevresel değişkenleri tanımlamak için kullanılmaktadır. o zaman bu nasıl çalışıyorexport
Haris

Bu ana kadar, kabul edilmiş bir cevap olmamıştır. Muhtemelen birini kabul etmeden önce birkaç gün daha bekleyeceğim. Bu cevabın dezavantajı, orijinal komutu bozmadığı ya da sorudaki orijinal komuttan nasıl alınacağını, bu cevaptaki komutlarla aynı olduklarını göstererek tartışmamasıdır. Bunun dışında iyi bir açıklama.
jippie

@ralph - ikisi de envve exportdışa aktarma ortamı tanımlamaları böylece alt kabukta kullanılabilirler. Asıl sorun, bu dışa aktarılan tanımların bir denizaltı ortamına ve özellikle de fonksiyon tanımlarını içe aktarma mekanizmasında nasıl içe aktarıldığı ile ilgilidir.
sdenham

1
@ralph - envbazı seçeneklerde ve ortam değişkenlerinin ayarlandığı bir komutu çalıştırır. Orijinal soru örneklerinde bir dizgeye envayarlandığına xve bash -cçalıştırmak için bir komutla çağırdığına dikkat edin. Bunu yaparsanız env x='foo' vim, Vim başlatılır ve orada içerdiği kabuğunu / ortamını çağırabilir !echo $xve yazdırır foo, ancak sonra çıkarsanız ve echo $xtanımlanır, yalnızca vim çalışırken var olduğu gibi tanımlanmaz. aracılığıyla envkomuta. Bunun exportyerine komut, geçerli ortamdaki kalıcı değerleri ayarlar, böylece daha sonra bir alt kabuk çalışması bunları kullanır.
Gary Fixler

72

Bunu, yukarıda Chris Down tarafından verilen mükemmel cevabın bir öğretici tarzı yeniden yazılması olarak yazdım.


Bash'de bunun gibi kabuk değişkenleriniz olabilir

$ t="hi there"
$ echo $t
hi there
$

Varsayılan olarak, bu değişkenler alt işlemler tarafından miras alınmaz.

$ bash
$ echo $t

$ exit

Ancak, bunları dışa aktarma için işaretlerseniz, bash, alt işlemlerin ortamına girecekleri anlamına gelen bir bayrak belirler ( envpparametre çok görülmese de, mainC programınızda üç parametre vardır: main(int argc, char *argv[], char *envp[])bu son işaretçi dizisi bir dizidir Kabuk değişkenlerinin tanımlarını içeren).

Öyleyse taşağıdaki şekilde ihracat yapalım :

$ echo $t
hi there
$ export t
$ bash
$ echo $t
hi there
$ exit

Oysa yukarıdaki talt kabukta tanımlanmadıysa, şimdi dışa aktardıktan sonra görünür ( export -n tdışa aktarmayı durdurmak istiyorsanız kullanın).

Ancak bash'deki fonksiyonlar farklı bir hayvandır. Onları böyle ilan edersiniz:

$ fn() { echo "test"; }

Ve şimdi, işlevi başka bir kabuk komutundaymış gibi çağırarak çağırmanız yeterlidir:

$ fn
test
$

Bir kez daha, bir deniz kabuğu çıkarırsanız, fonksiyonumuz dışa aktarılmaz:

$ bash
$ fn
fn: command not found
$ exit

Bir işlevi dışa aktarabiliriz export -f:

$ export -f fn
$ bash
$ fn
test
$ exit

İşin en zor kısmı: benzeri bir dışa fnaktarma işlevi , kabuk değişkeninin dışa aktarmasının tyukarıda olduğu gibi bir ortam değişkenine dönüştürülmesidir . fnYerel bir değişken olduğunda bu olmaz , ancak dışa aktardıktan sonra onu kabuk değişkeni olarak görebiliriz. Ancak, olabilir de aynı adla normal (yani olmayan fonksiyonu) kabuk değişkeni var. bash değişkenin içeriğine bağlı olarak ayırt eder:

$ echo $fn

$ # See, nothing was there
$ export fn=regular
$ echo $fn
regular
$ 

Artık env, dışa aktarma için işaretlenmiş tüm kabuk değişkenlerini ve hem normal fnhem de işlevin ortaya fnçıktığını göstermek için kullanabiliriz:

$ env
.
.
.
fn=regular
fn=() {  echo "test"
}
$

Bir alt kabuk her iki tanımı da alacaktır: biri normal değişken, biri işlev olarak:

$ bash
$ echo $fn
regular
$ fn
test
$ exit

fnYukarıda yaptığımız gibi veya doğrudan normal değişken ataması olarak tanımlayabilirsiniz :

$ fn='() { echo "direct" ; }'

Not Bu yapılacak sıradışı bir şeydir! Normalde işlevi fnyukarıda fn() {...}sözdiziminde yaptığımız gibi tanımlardık . Ancak bash onu çevreye ihraç ettiğinden, yukarıdaki normal tanımları doğrudan “kısaltabiliriz”. (Sezginizi sayaç belki) unutmayın bu mu değil yeni bir fonksiyonun neden fncari kabuk mevcuttur. Ama bir "alt ** kabuk" ortaya çıkarsanız, o zaman olur.

Fonksiyonun dışa aktarımını iptal edelim fnve yeni normal fn(yukarıda gösterildiği gibi) bozulmadan bırakalım .

$ export -nf fn

Artık işlev fnartık dışa aktarılmıyor, ancak normal değişken değişiyor fnve () { echo "direct" ; }içinde var.

Şimdi bir alt kabuk, ()onunla başlayan normal bir değişken gördüğünde , gerisini bir fonksiyon tanımı olarak yorumlar. Ancak bu yalnızca yeni bir kabuk başladığında gerçekleşir. Yukarıda gördüğümüz gibi, sadece normal bir kabuk değişkeni tanımlamak, ()fonksiyon gibi davranmasına neden olmaz. Bir deniz kabuğu başlatmak zorundasın.

Ve şimdi "kabuklu" böcek:

Az önce gördüğümüz gibi, yeni bir kabuk ()ondan başlayarak normal bir değişkenin tanımını aldığında onu bir işlev olarak yorumluyor. Bununla birlikte, işlevi tanımlayan kapanış ayracından sonra daha fazla varsa , orada ne varsa onu da uygular .

Bunlar bir kez daha gereksinimlerdir:

  1. Yeni bash doğuyor
  2. Bir ortam değişkeni yutulur
  3. Bu ortam değişkeni "()" ile başlar ve sonra ayraçların içinde bir işlev gövdesi içerir ve daha sonra komutları vardır.

Bu durumda, savunmasız bir bash bu komutları yerine getirir.

Örnek:

$ export ex='() { echo "function ex" ; }; echo "this is bad"; '
$ bash
this is bad
$ ex
function ex
$

Dışa aktarılan normal değişken exbir fonksiyon olarak yorumlanan alt kabuğa geçildi, exancak takip komutları ( this is bad) alt kabuğun doğurduğu şekilde gerçekleştirildi.


Kaygan tek hat testinin açıklanması

Shellshock kırılganlığının test edilmesi için popüler bir tek gömlek @ jippie'nin sorusunda bahsetti:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

İşte bir parçalama: ilk :olarak bash sadece bir steno true. trueve :her ikisi de, bash olarak (tahmin ettiğiniz gibi) doğru olarak değerlendirilir:

$ if true; then echo yes; fi
yes
$ if :; then echo yes; fi
yes
$

İkincisi, envkomut (bash'a da eklenir) çevre değişkenlerini (yukarıda gördüğümüz gibi) yazdırır, ancak aynı zamanda verilen bir değişkenle (veya değişkenlere) tek bir komutu çalıştırmak için kullanılabilir ve bu komuttan bash -ctek bir komut çalıştırır. Komut satırı:

$ bash -c 'echo hi'
hi
$ bash -c 'echo $t'

$ env t=exported bash -c 'echo $t'
exported
$

Böylece bütün bunları birlikte dikmek, bash'ı komut olarak çalıştırabiliriz, yapması gereken bazı aptalca şeyler verebiliriz ve onunla bash -c echo this is a testbaşlayan bir değişkeni dışa aktarabiliriz, ()böylece alt kabuk bir fonksiyon olarak yorumlanır. Eğer mermi kovanı mevcutsa, derhal alt kabuktaki herhangi bir takip komutunu da yerine getirecektir. Geçtiğimiz işlev bizim için önemli olmadığı için (ancak ayrıştırılması gerekir) akla gelebilecek en kısa geçerli işlevi kullanırız:

$ f() { :;}
$ f
$ 

Buradaki işlev fsadece :true döndüren ve çıkan komutu çalıştırır . Şimdi bazı "kötülükler" komutunu ekleyiniz ve normal bir değişkeni bir alt kabuğa veriniz ve kazanırsınız. İşte yine tek gömlek:

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Bu yüzden sonuna kadar tacked xbasit geçerli bir fonksiyon ile düzenli bir değişken olarak ihraç edilir echo vulnerable. Bu bash'a geçirilir ve bash xbir fonksiyon olarak yorumlanır (umurumuzda değil) daha sonra belki de echo vulnerablemuşamba mevcutsa çalıştırır .

this is a testMesajı kaldırarak bir astarı biraz kısaltabiliriz :

$ env x='() { :;}; echo vulnerable' bash -c :

Bu canımı sıkmaz this is a testama sessiz :komutu yine çalıştırır. (Eğer -c :oradan ayrılırsanız , alt kabuğa oturtulur ve manuel olarak çıkmak zorunda kalırsınız.) Belki de en kullanıcı dostu versiyon şudur:

$ env x='() { :;}; echo vulnerable' bash -c "echo If you see the word vulnerable above, you are vulnerable to shellshock"

12
Güzel açıklama. Bu soru çok fazla görüş almakta (muhtemelen herkes diğerleri kadar bash gibi uzman değildir) ve kimsenin { :;};gerçekte söylediği şey üzerine birkaç kelime harcadığına inanıyorum . Bence cevabınıza güzel bir ek olurdu. Örneğinizden sorudaki orijinal emirlere nasıl ulaştığınızı açıklayabilir misiniz?
jippie

20

İsteğe bağlı ortam değişkenlerini bir programa besleyebiliyorsanız, seçtiğiniz kütüphaneleri yükleyerek hemen hemen her şeyi yapmasına neden olabilirsiniz. Çoğu durumda, bu, bu ortam değişkenlerini alan programda bir güvenlik açığı olarak kabul edilmez, bunun yerine bir yabancının keyfi ortam değişkenlerinde beslenebileceği bir mekanizma olarak kabul edilir.

Ancak CVE-2014-6271 farklı.

Bir ortam değişkeninde güvenilmeyen veriye sahip olmanın yanlış bir tarafı yoktur. İnsanın program davranışını değiştirebilecek ortam değişkenlerinden hiçbirine girmemesini sağlamalıdır. Belli bir çağrı için, biraz daha soyut bir ifadeyle, doğrudan dışardan bir kişi tarafından belirtilmesine izin verilen bir ortam değişken adı beyaz listesi oluşturabilirsiniz.

CVE-2014-6271 bağlamında öne sürülen bir örnek, günlük dosyalarının ayrıştırılması için kullanılan komut dosyalarıdır. Bunların çevre değişkenlerinde güvenilmeyen verileri iletmek için çok meşru bir ihtiyacı olabilir. Elbette böyle bir ortam değişkeninin adı, olumsuz bir etkisi olmayacak şekilde seçilmiştir.

Ancak, bu belirli bash kırılganlığı hakkında kötü olan şey burada. Herhangi bir değişken adıyla kullanılabilir. Eğer denilen bir ortam değişkeni GET_REQUEST_TO_BE_PROCESSED_BY_MY_SCRIPTyaratırsanız, kendi betiğiniz dışında başka bir programın o ortam değişkeninin içeriğini yorumlamasını beklemeyeceksiniz. Ancak bu bash bölüğünden yararlanarak her bir ortam değişkeni bir saldırı vektörü haline gelir.

Bunun, ortam değişkenlerinin adlarının gizli olması gerektiği anlamına gelmediğine dikkat edin. İlgili ortam değişkenlerinin adlarını bilmek bir saldırıyı kolaylaştırmaz.

Eğer program1aramalar program2dönüş çağrıları program3, daha sonra program1verileri geçebileceği program3ortam değişkenleri yoluyla. Her programın oluşturduğu belirli bir ortam değişkenleri listesi ve üzerinde çalıştığı belirli bir liste vardır. Eğer değil tarafından tanınan bir isim seçerseniz program2, içinden verilerini geçirebilirsiniz program1için program3bu herhangi bir olumsuz üzerinde etkiler dert etmeden program2.

Tarafından verilen değişkenler tam isimlerini bilen bir saldırgan program1tarafından yorumlanır değişken isimleri program2adları seti arasında hiçbir üst üste binme varsa program2`' davranışını değiştirmek için bu bilgiyi kullanamaz.

Ancak bu program2bir bashbetik olsaydı bozuldu , çünkü bu hata nedeniyle bashher ortam değişkenini kod olarak yorumlayacaktı.


1
"her bir ortam değişkeni bir saldırı vektörü haline gelir" - bu eksik olan kısım. Teşekkürler.
wrschneider

9

Bağladığınız makalede açıklanmıştır ...

bash kabuğunu çağırmadan önce özel hazırlanmış değerlere sahip ortam değişkenleri oluşturabilirsiniz. Bu değişkenler, kabuk çağrıldığında derhal çalıştırılan kod içerebilir.

Bu, çağrılan bash, çağrıldığında -c "echo this is a test"tek tırnak içindeki kodu çalıştırır.

Bash, biraz sınırlı bir uygulamada olsa da fonksiyonlara sahiptir ve bu bash fonksiyonlarını çevre değişkenlerine koymak mümkündür. Bu hata, bu fonksiyon tanımlarının sonuna (enivronment değişkeninin içinde) ekstra kod eklendiğinde tetiklenir.

Gönderdiğiniz kod örneğinin, çağrılan bash'in, atamayı yaptıktan sonra bu dizgiyi değerlendirmeyi durdurmadığı gerçeğinden faydalanır. Bu durumda bir fonksiyon ataması.

Gönderdiğim kod pasajı hakkında gerçekten özel olan, anladığım kadarıyla, çalıştırmak istediğimiz kodun önüne bir fonksiyon tanımı koyarak, bazı güvenlik mekanizmalarının üstesinden gelinebilir olmasıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.