Format string
- C kursu
- Uzman
- Ders 22/47
- 5 dk
Format string güvenlik açığını öğrenirsin.
Format string açığı nedir?
Format string açığı, kullanıcı girdisinin doğrudan printf'in ilk parametresi olarak verilmesiyle oluşur. printf(input) yazmak, saldırgana biçim dizisini kontrol etme imkânı verir.
Saldırgan %x ile yığıt değerlerini okuyabilir, %n ile belleğe yazabilir. Doğru kullanım printf("%s", input) biçimindedir; burada biçim dizesi sabittir. fprintf, sprintf, snprintf ve syslog aynı açığa sahiptir. Derleyici -Wformat-security uyarısıyla riskli kullanımları yakalar. Bu açık basit görünebilir ama gerçek dünyada çok saldırıya uğramıştır.
%n ile belleğe yazma
Format belirtici %n, o ana kadar yazılan karakter sayısını bir işaretçiye yazar. Bu özellik saldırgana printf üzerinden belleğe yazma imkânı verir.
Örneğin printf("%n", &target) target değişkenine 0 yazar. Saldırgan bu davranışla dönüş adresini değiştirebilir. Bu yüzden modern sistemlerde %n çoğu zaman kapatılır. Güvenli kodda biçim dizesi her zaman sabittir; kullanıcı girdisi yalnızca argüman olarak verilir. puts veya fputs biçimlendirme gerektirmeyen durumlarda daha güvenlidir. syslog çağrılarında da aynı titizlik gerekir.
Uygulama Güvenli biçimlendirme yazdır
void safe_print(const char *fmt, const char *arg) fonksiyonunu tanımla; gövdesi printf(fmt, arg); olsun. main içinde üç kez ("%s\n", "hello"), ("%s\n", "world"), ("%s\n", "safe") ile çağır.
Başlangıç kodu
#include <stdio.h>
// safe_print fonksiyonunu tanımla
// üç dizeyi "%s\n" biçimiyle yazdır
int main(void) {
return 0;
}Örnek çözüm
#include <stdio.h>
void safe_print(const char *fmt, const char *arg) {
printf(fmt, arg);
}
int main(void) {
safe_print("%s\n", "hello");
safe_print("%s\n", "world");
safe_print("%s\n", "safe");
return 0;
}Beklenen çıktı
hello world safe
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Hangisi güvenli bir printf çağrısıdır?
- printf(input)
- printf("%s", input) Doğru cevap
- printf(input, &x)
- printf(input, x)
Açıklama: Biçim dizesi sabit olmalı; kullanıcı girdisi argüman olarak verilmeli.
2 Format belirticilerini eşle
| Kavram | Anlamı |
|---|---|
%s |
Dize |
%d |
Tamsayı |
%x |
Onaltılık |
%n |
Yazılan sayı |
3 Güvenli printf çağrısını tamamla
printf("%s", ____);
printf("%s", name);
Açıklama: name argüman olarak verilir; biçim dizesi sabittir.