经常有一些脚本程序由于判断,过滤不严导致下载任意文件。通常测试的话都喜欢在文件名处替换为../../../../../../../../../../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,说不定有意外发现~!!