1 <?php 2 error_reporting(0); 3 session_start(); 4 header("Content-type:image/jpeg"); 5 echo file_get_contents($_SESSION['avatar']); 6 ?>
在第5行发现 读取的文件后,将文件进行了输出。 所以猜测此处可能存在SSRF 和 任意文件读取
搜索关键变量$_SESSION['avatar'] 发现在登陆 和修改密码 读取了改变量,而上传的地方可以修改该变量 。
因为所有的$_SESSION['avatar']变量在发送数据包时都是加密的所以不能直接修改$_SESSION['avatar']导致任意文件读取,所以采用上传时修改其路径。来改$_SESSION['avatar']
1 <?php 2 include_once('../sys/config.php'); 3 $uploaddir = '../uploads'; 4 5 if (isset($_POST['submit']) && isset($_FILES['upfile'])) { 6 7 if(is_pic($_FILES['upfile']['name'])){ 8 9 $avatar = $uploaddir . '/u_'. time(). '_' . $_FILES['upfile']['name']; 10 11 if (move_uploaded_file($_FILES['upfile']['tmp_name'], $avatar)) { 12 //更新用户信息 13 $query = "UPDATE users SET user_avatar = '$avatar' WHERE user_id = '{$_SESSION['user_id']}'"; 14 mysql_query($query, $conn) or die('update error!'); 15 mysql_close($conn); 16 //刷新缓存 17 $_SESSION['avatar'] = $avatar; 18 header('Location: edit.php'); 19 } 20 else { 21 echo 'upload error<br />'; 22 echo '<a href="edit.php">返回</a>'; 23 } 24 }else{ 25 echo '只能上傳 jpg png gif!<br />'; 26 echo '<a href="edit.php">返回</a>'; 27 } 28 } 29 else { 30 not_find($_SERVER['PHP_SELF']); 31 } 32 ?>
在第13行发现 $query = "UPDATE users SET user_avatar = '$avatar' WHERE user_id = '{$_SESSION['user_id']}'"; 他直接把上传的路径$avatar直接取出来,更新了数据库
而UPDATE有个特殊的属性在set设置多个相同的键时,只取最后一个键的值。 因此可以导致可以构造$_SESSION['avatar']
payload:
$avatar= ' , user_avatar = '读取的文件路径' WHERE user_id = 'zzz' 首先用单引号把$avatar去闭合,然后用逗号接下一个构造的变量 user_avatar = '读取的文件路径' ,但是出现了一个问题 user_id不是知道 但是可以取构造 user_name='注册的用户'
然后发现 if(is_pic($_FILES['upfile']['name'])) 对文件后缀进行了验证
最终payload: $avatar= ' , user_avatar = '读取的文件路径' WHERE user_name='注册的用户' #.jpg
然后用户登录 上传抓包,把抓到的
上传文件修改文件名的包
去取变量$avatar
将取到的$avatar读出来
修改文件名 filename
发现数据库得到是 ../upload/..........._config.php 是因为取 单引号时对单引号和 / 进行了转义导致单引号没闭合
重新编码成16进制 绕过单引号和/
成功构造。
然后先重放登录页面获取去取变量$avatar
然后在 将取到的$avatar读出来
如图所示攻击成功,本地文件任意读取。
接下来测试SSRF
因为没有内网环境,所以测试百度 将http://www.baidu.com
发现成功将百度页面读取,也就是可以读取内网信息。所以存在SSRF