经常有一些脚本程序由于判断,过滤不严导致下载任意文件。通常测试的话都喜欢在文件名处替换为../../../../../../../../../../filename,来跨目录,但是有些程序里类似下面:
<? ############################## // // + 케이보드 _ 첨부파일_다운로드(download.php) // ############################## @session_start(); include "kconf.php"; include "library.php"; // 호스트 체크 if(!eregi($HTTP_HOST,$HTTP_REFERER)) exit; // 권한정보 if(!$_SESSION[member][grade]) $_SESS_GRADE=10; else $_SESS_GRADE=$_SESSION[member][grade]; // 데이터베이스 객체 생성 $CONN=new CLASS_CONNECT($host,$db_name,$db_id,$db_pass); $ADMIN=new CLASS_ADMIN("fetch_array",$board); $ADMIN->data(""); // 권한체크 (read 와 동일 ) if($_SESS_GRADE > $ADMIN->auth_read) exit; // 다운로드수 증가 $query="UPDATE kport_".$board."_attach SET download=download+1 WHERE no=$no"; $res=@mysql_query($query); $cwd=getcwd(); //실제 파일명 또는 경로 $file = "$cwd/data/$board/$file_name"; $dnfile = "$file_name" ; // 1 이면 다운 0 이면 브라우져가 인식하면 화면에 출력 $dn = "1"; $dn_yn = ($dn) ? "attachment" : "inline"; $bin_txt = "1"; $bin_txt = ($bin_txt) ? "r" : "rb"; if(eregi("(MSIE 5.5|MSIE 6.0)", $HTTP_USER_AGENT)) { Header("Content-type: application/octet-stream"); Header("Content-Length: ".filesize("$file")); Header("Content-Disposition: $dn_yn; filename=$dnfile"); Header("Content-Transfer-Encoding: binary"); Header("Pragma: no-cache"); Header("Expires: 0"); } else { Header("Content-type: file/unknown"); Header("Content-Length: ".filesize("$file")); Header("Content-Disposition: $dn_yn; filename=$dnfile"); Header("Content-Description: PHP3 Generated Data"); Header("Pragma: no-cache"); Header("Expires: 0"); } if (is_file("$file")) { $fp = fopen("$file", "$bin_txt"); if (!fpassthru($fp)) fclose($fp); } else { echo "해당 파일이나 경로가 존재하지 않습니다."; } // 접속 종료 $CONN->disconnect(); ?>
这个下载脚本有下载漏洞,但是你正常file_name=../../../../../../../../etc/issue是不能下载的。
因为这句:
if(!eregi($HTTP_HOST,$HTTP_REFERER)) exit;
它在下载之前判断了,如果你的http请求没有Referer或者Referer里的网址不是来自网站自身的话,程序就好结束,你的下载也就不能生效。
类似判断很简单,但有时候对于没仔细分析的人就不会暴露漏洞,当然,这种不严谨的判断还是非常弱智的,所以pentest的时候不妨给可疑的下载点加个原始网站的Referer,说不定有意外发现~!!