而透過 cURL 上傳檔案,通常是用以下簡單的指定就完成:
$ curl -F "file=@/tmp/sample.txt" http://192.168.1.1/cgi-bin/upload.cgi
但如果細看表單內容物時,產出的結果:
POST /cgi-bin/upload.cgi HTTP/1.1
Host: 192.168.1.1
Content-Type: multipart/form-data
Content-Length: ##
----------########
Content-Disposition: form-data; name="file";
filename="sample.txt"
...
這時,有些 CGI 開發上會直接拿上述 filename 參數資訊來用,寫不好就會產生跳脫問題,如:
Content-Disposition: form-data; name="file";
filename="../etc/sample.txt"
若底層是直接用 sprintf(des_filepath, "/tmp/%s", filename); 就會有機會逃脫去覆蓋掉東西。幸運的是 embedded linux 大多會設定檔案系統是 Read-only file system 來保護 :P 若是用 PHP 時,大多都靠 basename 來保護了。
最後,補上靠 curl 串改 filename 的招數:
$ curl -F "file=@/tmp/sample.txt; filename=../etc/sample.txt" http://192.168.1.1/cgi-bin/upload.cgi