SSRF绕过filter_var(),preg_match()和parse_url()

1.利用curl的变量解释符$

php版本

利用代码

/*ssrf.php*/
<?php echo "Argument: ".$argv[1]."n"; // check if argument is a valid URL if(filter_var($argv[1], FILTER_VALIDATE_URL)) { // parse URL $r = parse_url($argv[1]); print_r($r); // check if host ends with baidu.com if(preg_match('baidu.com$/', $r['host'])) { // get page from URL exec('curl -v -s "'.$r['host'].'"', $a); print_r($a); } else { echo "Error: Host not allowed"; } } else { echo "Error: Invalid URL"; } ?>

Bash将$baidu分析为一个空变量,并且使用curl请求了sec-redclub<empty> .com。 

然而这只发生在curl语法中。 实际上,正如上面的屏幕截图所示,由parse_url()解析的主机名仍然是 sec-redclub$baidu.com。 $baidu变量并没有被解释。 只有当使用了exec()函数而且脚本又使用[host]来创建一个curl HTTP请求时,Bash才会将其转换为一个空变量。

所以应避免PHP脚本使用exec()或system()函数来调用像curl,wget之类的系统命令。

 2.file_get_content()代替exec()或system()打cookie

<?php
   echo "Argument: ".$argv[1]."n";
   // check if argument is a valid URL
   if(filter_var($argv[1], FILTER_VALIDATE_URL)) {
      // parse URL
      $r = parse_url($argv[1]);
      print_r($r);
      // check if host ends with google.com
      if(preg_match('/baidu.com$/', $r['host'])) {
         // get page from URL
         $a = file_get_contents($argv[1]);
         echo($a);
      } else {
         echo "Error: Host not allowed";
      }
   } else {
      echo "Error: Invalid URL";
   }
?>

参考:https://www.colabug.com/2413002.html

原文地址:https://www.cnblogs.com/p0pl4r/p/10642857.html