본문 바로가기

Breach CTF-web-Framework Follies

블라인드로 문제파일만 받아서 풀었기에 풀고나니 10솔브 문제였다 뭐든지 마음가짐이 중요한것같다.

next.js의 지식이 부족하기에 문제는 정말 어려웠고 server.js도 라우팅도 모두 동적으로 해준다는것을 깨닫는데 시간이 조금 걸렸다.

ioEYWhJqZO폴더에서 flag를 출력하는 함수와 이폴더의 페이지에서만 button클릭시 동작하는 부분이 있는것을 볼수있다.

저함수를 실행시키는 방법을 찾는데 많은 시간을 사용했고 

test버튼을 클릭시에 다음과 같이 통신하는것을 확인했고 codegate의 웹문제에서 action값을 변조시킨것처럼 이번에도 action을 바꾸면 될것같았다.

 

/_next/static/chunks/app/ioEYWhJqZO/page-46ecf19b8ba66948.js경로에서 중요한 action id값을 찾았다.

(self.webpackChunk_N_E = self.webpackChunk_N_E || []).push([[7646], {
    8357: function(e, t, n) {
        Promise.resolve().then(n.bind(n, 2114))
    },
    5925: function(e, t, n) {
        "use strict";
        Object.defineProperty(t, "$", {
            enumerable: !0,
            get: function() {
                return i
            }
        });
        let l = n(5181);
        function i(e) {
            let {createServerReference: t} = n(7320);
            return t(e, l.callServer)
        }
    },
    2114: function(e, t, n) {
        "use strict";
        n.r(t),
        n.d(t, {
            default: function() {
                return a
            }
        });
        var l = n(9533)
          , i = n(1229);
        n(5181);
        var r = n(5925);
        (0,
        r.$)("816774a06b36f5211070d9d4f10f18e74c47f4ec");
        var s = (0,
        r.$)("27cb19eb91692fce6e188119e76dc4ccbd21679d");
        let c = e => {
            let {task: t, onToggleComplete: n, onDelete: i} = e;
            return (0,
            l.jsxs)("div", {
                style: {
                    display: "flex",
                    alignItems: "center",
                    marginBottom: "10px"
                },
                children: [(0,
                l.jsx)("input", {
                    type: "checkbox",
                    checked: t.completed,
                    onChange: () => n(t.id),
                    style: {
                        marginRight: "10px"
                    }
                }), (0,
                l.jsx)("button", {
                    style: {
                        display: "none"
                    },
                    onClick: () => s(),
                    children: "Test"
                }), (0,
                l.jsx)("span", {
                    style: {
                        textDecoration: t.completed ? "line-through" : "none",
                        flex: 1
                    },
                    children: t.name
                }), (0,
                l.jsx)("button", {
                    onClick: () => i(t.id),
                    style: {
                        marginLeft: "10px"
                    },
                    children: "Delete"
                })]
            })
        }
        ;
        var a = () => {
            let[e,t] = (0,
            i.useState)([])
              , [n,r] = (0,
            i.useState)("")
              , [s,a] = (0,
            i.useState)("all")
              , [o,d] = (0,
            i.useState)(1)
              , p = n => {
                t(e.map(e => e.id === n ? {
                    ...e,
                    completed: !e.completed
                } : e))
            }
              , u = n => {
                t(e.filter(e => e.id !== n))
            }
            ;
            return (0,
            i.useEffect)( () => {
                console.log("Current tasks:", e)
            }
            , [e]),
            (0,
            l.jsxs)("div", {
                style: {
                    padding: "20px",
                    fontFamily: "Arial, sans-serif"
                },
                children: [(0,
                l.jsx)("h1", {
                    children: "Task Manager"
                }), (0,
                l.jsxs)("div", {
                    style: {
                        marginBottom: "20px"
                    },
                    children: [(0,
                    l.jsx)("input", {
                        type: "text",
                        value: n,
                        onChange: e => {
                            r(e.target.value)
                        }
                        ,
                        placeholder: "Enter new task",
                        style: {
                            padding: "10px",
                            width: "300px",
                            marginRight: "10px"
                        }
                    }), (0,
                    l.jsx)("button", {
                        onClick: () => {
                            n.trim() && (t([...e, {
                                id: o,
                                name: n,
                                completed: !1
                            }]),
                            r(""),
                            d(o + 1))
                        }
                        ,
                        style: {
                            padding: "10px"
                        },
                        children: "Add Task"
                    })]
                }), (0,
                l.jsxs)("div", {
                    style: {
                        marginBottom: "20px"
                    },
                    children: [(0,
                    l.jsx)("label", {
                        style: {
                            marginRight: "10px"
                        },
                        children: "Filter: "
                    }), (0,
                    l.jsxs)("select", {
                        value: s,
                        onChange: e => {
                            a(e.target.value)
                        }
                        ,
                        children: [(0,
                        l.jsx)("option", {
                            value: "all",
                            children: "All"
                        }), (0,
                        l.jsx)("option", {
                            value: "completed",
                            children: "Completed"
                        }), (0,
                        l.jsx)("option", {
                            value: "incomplete",
                            children: "Incomplete"
                        })]
                    })]
                }), (0,
                l.jsx)("div", {
                    children: ( () => {
                        switch (s) {
                        case "completed":
                            return e.filter(e => e.completed);
                        case "incomplete":
                            return e.filter(e => !e.completed);
                        default:
                            return e
                        }
                    }
                    )().map(e => (0,
                    l.jsx)(c, {
                        task: e,
                        onToggleComplete: p,
                        onDelete: u
                    }, e.id))
                })]
            })
        }
    }
}, function(e) {
    e.O(0, [4170, 6842, 1744], function() {
        return e(e.s = 8357)
    }),
    _N_E = e.O()
}
]);

이후 action id값을 다른것으로 변조해줬더니 flag를 받았다.

 

'' 카테고리의 다른 글

nodejs로 파일 업로드 필터링 우회 방법  (0) 2025.04.09
dicectf-web-공부  (0) 2025.04.08
Codegate2025-공부  (0) 2025.04.02
codegate 2025-Masquerade  (0) 2025.03.30
WACon2022-Kuncɛlan 공부  (4) 2022.06.29